Merge remote-tracking branch 'upstream/develop' into network-thread-view

This commit is contained in:
Michael 2021-10-02 21:00:10 +00:00
commit eea355ae3b
31 changed files with 886 additions and 870 deletions

View file

@ -32,7 +32,7 @@ General
* m - Status Messages and Posts * m - Status Messages and Posts
* r - Profile Details * r - Profile Details
* h - Photo Albums * h - Photo Albums
* v - Videos * d - Media
* e - Events and Calendar * e - Events and Calendar
* t - Personal Notes * t - Personal Notes
* o - Scheduled Posts * o - Scheduled Posts
@ -49,12 +49,13 @@ General
* h - Only show hidden contacts * h - Only show hidden contacts
* e - Edit contact groups * e - Edit contact groups
../contacts (single contact view) ../contact (single contact view)
------------------------------- -------------------------------
* m - Status messages * m - Status messages
* p - Posts and Comments
* d - Media
* o - Profile * o - Profile
* t - Contacts * t - Contacts
* d - Common friends
* r - Advanced * r - Advanced
../message ../message

View file

@ -479,6 +479,22 @@ Hook data:
- **uid** (input): the user to return the contact data for (can be empty for public contacts). - **uid** (input): the user to return the contact data for (can be empty for public contacts).
- **result** (output): Set by the hook function to indicate a successful detection. - **result** (output): Set by the hook function to indicate a successful detection.
### support_follow
Called to assert whether a connector addon provides follow capabilities.
Hook data:
- **protocol** (input): shorthand for the protocol. List of values is available in `src/Core/Protocol.php`.
- **result** (output): should be true if the connector provides follow capabilities, left alone otherwise.
### support_revoke_follow
Called to assert whether a connector addon provides follow revocation capabilities.
Hook data:
- **protocol** (input): shorthand for the protocol. List of values is available in `src/Core/Protocol.php`.
- **result** (output): should be true if the connector provides follow revocation capabilities, left alone otherwise.
### follow ### follow
Called before adding a new contact for a user to handle non-native network remote contact (like Twitter). Called before adding a new contact for a user to handle non-native network remote contact (like Twitter).
@ -497,6 +513,14 @@ Hook data:
- **two_way** (input): wether to stop sharing with the remote contact as well. - **two_way** (input): wether to stop sharing with the remote contact as well.
- **result** (output): wether the unfollowing is successful or not. - **result** (output): wether the unfollowing is successful or not.
### revoke_follow
Called when making a remote contact on a non-native network (like Twitter) unfollow you.
Hook data:
- **contact** (input): the remote contact (uid = local revoking user id) array.
- **result** (output): a boolean value indicating wether the operation was successful or not.
## Complete list of hook callbacks ## Complete list of hook callbacks
Here is a complete list of all hook callbacks with file locations (as of 24-Sep-2018). Please see the source for details of any hooks not documented above. Here is a complete list of all hook callbacks with file locations (as of 24-Sep-2018). Please see the source for details of any hooks not documented above.
@ -666,7 +690,6 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('contact_photo_menu', $args); Hook::callAll('contact_photo_menu', $args);
Hook::callAll('follow', $arr); Hook::callAll('follow', $arr);
Hook::callAll('unfollow', $hook_data);
### src/Model/Profile.php ### src/Model/Profile.php
@ -750,6 +773,13 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('logged_in', $a->user); Hook::callAll('logged_in', $a->user);
### src/Core/Protocol.php
Hook::callAll('support_follow', $hook_data);
Hook::callAll('support_revoke_follow', $hook_data);
Hook::callAll('unfollow', $hook_data);
Kook::callAll('revoke_follow', $hook_data);
### src/Core/StorageManager ### src/Core/StorageManager
Hook::callAll('storage_instance', $data); Hook::callAll('storage_instance', $data);

View file

@ -356,7 +356,6 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('contact_photo_menu', $args); Hook::callAll('contact_photo_menu', $args);
Hook::callAll('follow', $arr); Hook::callAll('follow', $arr);
Hook::callAll('unfollow', $hook_data);
### src/Model/Profile.php ### src/Model/Profile.php
@ -414,6 +413,13 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('logged_in', $a->user); Hook::callAll('logged_in', $a->user);
### src/Core/Protocol.php
Hook::callAll('support_follow', $hook_data);
Hook::callAll('support_revoke_follow', $hook_data);
Hook::callAll('unfollow', $hook_data);
Kook::callAll('revoke_follow', $hook_data);
### src/Core/StorageManager ### src/Core/StorageManager
Hook::callAll('storage_instance', $data); Hook::callAll('storage_instance', $data);

View file

@ -242,17 +242,11 @@ function events_content(App $a)
} }
if ((DI::args()->getArgc() > 2) && (DI::args()->getArgv()[1] === 'ignore') && intval(DI::args()->getArgv()[2])) { if ((DI::args()->getArgc() > 2) && (DI::args()->getArgv()[1] === 'ignore') && intval(DI::args()->getArgv()[2])) {
q("UPDATE `event` SET `ignore` = 1 WHERE `id` = %d AND `uid` = %d", DBA::update('event', ['ignore' => true], ['id' => DI::args()->getArgv()[2], 'uid' => local_user()]);
intval(DI::args()->getArgv()[2]),
intval(local_user())
);
} }
if ((DI::args()->getArgc() > 2) && (DI::args()->getArgv()[1] === 'unignore') && intval(DI::args()->getArgv()[2])) { if ((DI::args()->getArgc() > 2) && (DI::args()->getArgv()[1] === 'unignore') && intval(DI::args()->getArgv()[2])) {
q("UPDATE `event` SET `ignore` = 0 WHERE `id` = %d AND `uid` = %d", DBA::update('event', ['ignore' => false], ['id' => DI::args()->getArgv()[2], 'uid' => local_user()]);
intval(DI::args()->getArgv()[2]),
intval(local_user())
);
} }
if ($a->getThemeInfoValue('events_in_profile')) { if ($a->getThemeInfoValue('events_in_profile')) {
@ -444,13 +438,7 @@ function events_content(App $a)
} }
if (($mode === 'edit' || $mode === 'copy') && $event_id) { if (($mode === 'edit' || $mode === 'copy') && $event_id) {
$r = q("SELECT * FROM `event` WHERE `id` = %d AND `uid` = %d LIMIT 1", $orig_event = DBA::selectFirst('event', [], ['id' => $event_id, 'uid' => local_user()]);
intval($event_id),
intval(local_user())
);
if (DBA::isResult($r)) {
$orig_event = $r[0];
}
} }
// Passed parameters overrides anything found in the DB // Passed parameters overrides anything found in the DB

View file

@ -158,12 +158,9 @@ function message_content(App $a)
DI::baseUrl()->redirect('message/' . $conversation['id'] ); DI::baseUrl()->redirect('message/' . $conversation['id'] );
} else { } else {
$r = q("SELECT `parent-uri`,`convid` FROM `mail` WHERE `id` = %d AND `uid` = %d LIMIT 1", $parentmail = DBA::selectFirst('mail', ['parent-uri'], ['id' => DI::args()->getArgv()[2], 'uid' => local_user()]);
intval(DI::args()->getArgv()[2]), if (DBA::isResult($parentmail)) {
intval(local_user()) $parent = $parentmail['parent-uri'];
);
if (DBA::isResult($r)) {
$parent = $r[0]['parent-uri'];
if (!DBA::delete('mail', ['parent-uri' => $parent, 'uid' => local_user()])) { if (!DBA::delete('mail', ['parent-uri' => $parent, 'uid' => local_user()])) {
notice(DI::l10n()->t('Conversation was not removed.')); notice(DI::l10n()->t('Conversation was not removed.'));

View file

@ -200,12 +200,7 @@ function photos_post(App $a)
return; // NOTREACHED return; // NOTREACHED
} }
$r = q("SELECT `album` FROM `photo` WHERE `album` = '%s' AND `uid` = %d", if (!DBA::exists('photo', ['album' => $album, 'uid' => $page_owner_uid])) {
DBA::escape($album),
intval($page_owner_uid)
);
if (!DBA::isResult($r)) {
notice(DI::l10n()->t('Album not found.')); notice(DI::l10n()->t('Album not found.'));
DI::baseUrl()->redirect('photos/' . $user['nickname'] . '/album'); DI::baseUrl()->redirect('photos/' . $user['nickname'] . '/album');
return; // NOTREACHED return; // NOTREACHED
@ -321,7 +316,7 @@ function photos_post(App $a)
} }
if (!empty($_POST['rotate']) && (intval($_POST['rotate']) == 1 || intval($_POST['rotate']) == 2)) { if (!empty($_POST['rotate']) && (intval($_POST['rotate']) == 1 || intval($_POST['rotate']) == 2)) {
Logger::log('rotate'); Logger::notice('rotate');
$photo = Photo::getPhotoForUser($page_owner_uid, $resource_id); $photo = Photo::getPhotoForUser($page_owner_uid, $resource_id);
@ -681,7 +676,7 @@ function photos_post(App $a)
$type = Images::getMimeTypeBySource($src, $filename, $type); $type = Images::getMimeTypeBySource($src, $filename, $type);
Logger::log('photos: upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes', Logger::DEBUG); Logger::info('photos: upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes');
$maximagesize = DI::config()->get('system', 'maximagesize'); $maximagesize = DI::config()->get('system', 'maximagesize');
@ -701,14 +696,14 @@ function photos_post(App $a)
return; return;
} }
Logger::log('mod/photos.php: photos_post(): loading the contents of ' . $src , Logger::DEBUG); Logger::info('loading the contents of ' . $src);
$imagedata = @file_get_contents($src); $imagedata = @file_get_contents($src);
$image = new Image($imagedata, $type); $image = new Image($imagedata, $type);
if (!$image->isValid()) { if (!$image->isValid()) {
Logger::log('mod/photos.php: photos_post(): unable to process image' , Logger::DEBUG); Logger::info('unable to process image');
notice(DI::l10n()->t('Unable to process image.')); notice(DI::l10n()->t('Unable to process image.'));
@unlink($src); @unlink($src);
$foo = 0; $foo = 0;
@ -737,7 +732,7 @@ function photos_post(App $a)
$r = Photo::store($image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 0 , 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny); $r = Photo::store($image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 0 , 0, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
if (!$r) { if (!$r) {
Logger::log('mod/photos.php: photos_post(): image store failed', Logger::DEBUG); Logger::info('image store failed');
notice(DI::l10n()->t('Image upload failed.')); notice(DI::l10n()->t('Image upload failed.'));
return; return;
} }
@ -1020,13 +1015,15 @@ function photos_content(App $a)
$drop_url = DI::args()->getQueryString(); $drop_url = DI::args()->getQueryString();
return Renderer::replaceMacros(Renderer::getMarkupTemplate('confirm.tpl'), [ return Renderer::replaceMacros(Renderer::getMarkupTemplate('confirm.tpl'), [
'$method' => 'post', '$l10n' => [
'$message' => DI::l10n()->t('Do you really want to delete this photo album and all its photos?'), 'message' => DI::l10n()->t('Do you really want to delete this photo album and all its photos?'),
'$confirm' => DI::l10n()->t('Delete Album'), 'confirm' => DI::l10n()->t('Delete Album'),
'$confirm_url' => $drop_url, 'cancel' => DI::l10n()->t('Cancel'),
'$confirm_name' => 'dropalbum', ],
'$method' => 'post',
'$confirm_url' => $drop_url,
'$confirm_name' => 'dropalbum',
'$confirm_value' => 'dropalbum', '$confirm_value' => 'dropalbum',
'$cancel' => DI::l10n()->t('Cancel'),
]); ]);
} }
@ -1127,13 +1124,15 @@ function photos_content(App $a)
$drop_url = DI::args()->getQueryString(); $drop_url = DI::args()->getQueryString();
return Renderer::replaceMacros(Renderer::getMarkupTemplate('confirm.tpl'), [ return Renderer::replaceMacros(Renderer::getMarkupTemplate('confirm.tpl'), [
'$method' => 'post', '$l10n' => [
'$message' => DI::l10n()->t('Do you really want to delete this photo?'), 'message' => DI::l10n()->t('Do you really want to delete this photo?'),
'$confirm' => DI::l10n()->t('Delete Photo'), 'confirm' => DI::l10n()->t('Delete Photo'),
'$confirm_url' => $drop_url, 'cancel' => DI::l10n()->t('Cancel'),
'$confirm_name' => 'delete', ],
'$method' => 'post',
'$confirm_url' => $drop_url,
'$confirm_name' => 'delete',
'$confirm_value' => 'delete', '$confirm_value' => 'delete',
'$cancel' => DI::l10n()->t('Cancel'),
]); ]);
} }

View file

@ -1,261 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2021, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
use Friendica\App;
use Friendica\Content\Nav;
use Friendica\Content\Pager;
use Friendica\Content\Widget;
use Friendica\Core\Renderer;
use Friendica\Core\Session;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Attach;
use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Model\User;
use Friendica\Module\BaseProfile;
use Friendica\Security\Security;
use Friendica\Network\HTTPException;
function videos_init(App $a)
{
if (DI::config()->get('system', 'block_public') && !Session::isAuthenticated()) {
return;
}
Nav::setSelected('home');
if (DI::args()->getArgc() > 1) {
$owner = User::getOwnerDataByNick(DI::args()->getArgv()[1]);
if (empty($owner)) {
throw new HTTPException\NotFoundException(DI::l10n()->t('User not found.'));
}
// If not there, create 'aside' empty
if (!isset(DI::page()['aside'])) {
DI::page()['aside'] = '';
}
DI::page()['aside'] .= Widget\VCard::getHTML($owner);
$tpl = Renderer::getMarkupTemplate("videos_head.tpl");
DI::page()['htmlhead'] .= Renderer::replaceMacros($tpl);
}
return;
}
function videos_post(App $a)
{
$user = User::getByNickname(DI::args()->getArgv()[1]);
if (!DBA::isResult($user)) {
throw new HTTPException\NotFoundException(DI::l10n()->t('User not found.'));
}
if (local_user() != $user['uid']) {
DI::baseUrl()->redirect('videos/' . $user['nickname']);
}
if ((DI::args()->getArgc() == 2) && !empty($_POST['delete']) && !empty($_POST['id'])) {
$video_id = $_POST['id'];
if (Attach::exists(['id' => $video_id, 'uid' => local_user()])) {
// delete the attachment
Attach::delete(['id' => $video_id, 'uid' => local_user()]);
// delete items where the attach is used
Item::deleteForUser(['`attach` LIKE ? AND `uid` = ?',
'%attach/' . $video_id . '%',
local_user()
], local_user());
}
DI::baseUrl()->redirect('videos/' . $user['nickname']);
return; // NOTREACHED
}
DI::baseUrl()->redirect('videos/' . $user['nickname']);
}
function videos_content(App $a)
{
// URLs (most aren't currently implemented):
// videos/name
// videos/name/upload
// videos/name/upload/xxxxx (xxxxx is album name)
// videos/name/album/xxxxx
// videos/name/album/xxxxx/edit
// videos/name/video/xxxxx
// videos/name/video/xxxxx/edit
$user = User::getByNickname(DI::args()->getArgv()[1]);
if (!DBA::isResult($user)) {
throw new HTTPException\NotFoundException(DI::l10n()->t('User not found.'));
}
if (DI::config()->get('system', 'block_public') && !Session::isAuthenticated()) {
notice(DI::l10n()->t('Public access denied.'));
return;
}
if (empty($user)) {
notice(DI::l10n()->t('No videos selected') . EOL );
return;
}
$profile = Profile::getByUID($user['uid']);
//$phototypes = Photo::supportedTypes();
$_SESSION['video_return'] = DI::args()->getCommand();
//
// Parse arguments
//
if (DI::args()->getArgc() > 3) {
$datatype = DI::args()->getArgv()[2];
} elseif((DI::args()->getArgc() > 2) && (DI::args()->getArgv()[2] === 'upload')) {
$datatype = 'upload';
} else {
$datatype = 'summary';
}
//
// Setup permissions structures
//
$can_post = false;
$visitor = 0;
$remote_contact = false;
$contact_id = 0;
$community_page = (($user['page-flags'] == User::PAGE_FLAGS_COMMUNITY) ? true : false);
if ((local_user()) && (local_user() == $user['uid'])) {
$can_post = true;
} elseif ($community_page && !empty(Session::getRemoteContactID($user['uid']))) {
$contact_id = Session::getRemoteContactID($user['uid']);
$can_post = true;
$remote_contact = true;
$visitor = $contact_id;
}
// perhaps they're visiting - but not a community page, so they wouldn't have write access
if (!empty(Session::getRemoteContactID($user['uid'])) && !$visitor) {
$contact_id = Session::getRemoteContactID($user['uid']);
$remote_contact = true;
}
if ($user['hidewall'] && (local_user() != $user['uid']) && !$remote_contact) {
notice(DI::l10n()->t('Access to this item is restricted.'));
return;
}
$sql_extra = Security::getPermissionsSQLByUserId($user['uid']);
$o = "";
// tabs
$_is_owner = (local_user() && (local_user() == $user['uid']));
$o .= BaseProfile::getTabsHTML($a, 'videos', $_is_owner, $user['nickname'], $profile['hide-friends']);
//
// dispatch request
//
if ($datatype === 'upload') {
return; // no uploading for now
// DELETED -- look at mod/photos.php if you want to implement
}
if ($datatype === 'album') {
return; // no albums for now
// DELETED -- look at mod/photos.php if you want to implement
}
if ($datatype === 'video') {
return; // no single video view for now
// DELETED -- look at mod/photos.php if you want to implement
}
// Default - show recent videos (no upload link for now)
//$o = '';
$total = 0;
$r = q("SELECT hash FROM `attach` WHERE `uid` = %d AND filetype LIKE '%%video%%'
$sql_extra GROUP BY hash",
intval($user['uid'])
);
if (DBA::isResult($r)) {
$total = count($r);
}
$pager = new Pager(DI::l10n(), DI::args()->getQueryString(), 20);
$r = q("SELECT hash, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`created`) AS `created`,
ANY_VALUE(`filename`) AS `filename`, ANY_VALUE(`filetype`) as `filetype`
FROM `attach`
WHERE `uid` = %d AND filetype LIKE '%%video%%'
$sql_extra GROUP BY hash ORDER BY `created` DESC LIMIT %d , %d",
intval($user['uid']),
$pager->getStart(),
$pager->getItemsPerPage()
);
$videos = [];
if (DBA::isResult($r)) {
foreach ($r as $rr) {
$alt_e = $rr['filename'];
/// @todo The album isn't part of the above query. This seems to be some unfinished code that needs to be reworked completely.
$rr['album'] = '';
$name_e = $rr['album'];
$videos[] = [
'id' => $rr['id'],
'link' => DI::baseUrl() . '/videos/' . $user['nickname'] . '/video/' . $rr['hash'],
'title' => DI::l10n()->t('View Video'),
'src' => DI::baseUrl() . '/attach/' . $rr['id'] . '?attachment=0',
'alt' => $alt_e,
'mime' => $rr['filetype'],
'album' => [
'link' => DI::baseUrl() . '/videos/' . $user['nickname'] . '/album/' . bin2hex($rr['album']),
'name' => $name_e,
'alt' => DI::l10n()->t('View Album'),
],
];
}
}
$tpl = Renderer::getMarkupTemplate('videos_recent.tpl');
$o .= Renderer::replaceMacros($tpl, [
'$title' => DI::l10n()->t('Recent Videos'),
'$can_post' => $can_post,
'$upload' => [DI::l10n()->t('Upload New Videos'), DI::baseUrl() . '/videos/' . $user['nickname'] . '/upload'],
'$videos' => $videos,
'$delete_url' => (($can_post) ? DI::baseUrl() . '/videos/' . $user['nickname'] : false)
]);
$o .= $pager->renderFull($total);
return $o;
}

View file

@ -71,6 +71,44 @@ class Protocol
const PHANTOM = 'unkn'; // Place holder const PHANTOM = 'unkn'; // Place holder
/**
* Returns whether the provided protocol supports following
*
* @param $protocol
* @return bool
* @throws HTTPException\InternalServerErrorException
*/
public static function supportsFollow($protocol): bool
{
if (in_array($protocol, self::NATIVE_SUPPORT)) {
return true;
}
$result = null;
Hook::callAll('support_follow', $result);
return $result === true;
}
/**
* Returns whether the provided protocol supports revoking inbound follows
*
* @param $protocol
* @return bool
* @throws HTTPException\InternalServerErrorException
*/
public static function supportsRevokeFollow($protocol): bool
{
if (in_array($protocol, self::NATIVE_SUPPORT)) {
return true;
}
$result = null;
Hook::callAll('support_revoke_follow', $result);
return $result === true;
}
/** /**
* Returns the address string for the provided profile URL * Returns the address string for the provided profile URL
* *
@ -212,7 +250,7 @@ class Protocol
return ActivityPub\Transmitter::sendContactUndo($contact['url'], $contact['id'], $user['uid']); return ActivityPub\Transmitter::sendContactUndo($contact['url'], $contact['id'], $user['uid']);
} }
// Catch-all addon hook // Catch-all hook for connector addons
$hook_data = [ $hook_data = [
'contact' => $contact, 'contact' => $contact,
'two_way' => $two_way, 'two_way' => $two_way,
@ -222,4 +260,36 @@ class Protocol
return $hook_data['result']; return $hook_data['result'];
} }
/**
* Revoke an incoming follow from the provided contact
*
* @param array $contact Private contact (uid != 0) array
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function revokeFollow(array $contact)
{
if (empty($contact['network'])) {
throw new \InvalidArgumentException('Missing network key in contact array');
}
$protocol = $contact['network'];
if ($protocol == Protocol::DFRN && !empty($contact['protocol'])) {
$protocol = $contact['protocol'];
}
if ($protocol == Protocol::ACTIVITYPUB) {
return ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $contact['uid']);
}
// Catch-all hook for connector addons
$hook_data = [
'contact' => $contact,
'result' => null,
];
Hook::callAll('revoke_follow', $hook_data);
return $hook_data['result'];
}
} }

View file

@ -849,6 +849,36 @@ class Contact
return $result; return $result;
} }
/**
* Revoke follow privileges of the remote user contact
*
* @param array $contact Contact unfriended
* @return bool|null Whether the remote operation is successful or null if no remote operation was performed
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function revokeFollow(array $contact): bool
{
if (empty($contact['network'])) {
throw new \InvalidArgumentException('Empty network in contact array');
}
if (empty($contact['uid'])) {
throw new \InvalidArgumentException('Unexpected public contact record');
}
$result = Protocol::revokeFollow($contact);
// A null value here means the remote network doesn't support explicit follow revocation, we can still
// break the locally recorded relationship
if ($result !== false) {
DBA::update('contact', ['rel' => $contact['rel'] == self::FRIEND ? self::SHARING : self::NOTHING], ['id' => $contact['id']]);
}
return $result;
}
/** /**
* Marks a contact for archival after a communication issue delay * Marks a contact for archival after a communication issue delay
* *
@ -964,7 +994,6 @@ class Contact
$pm_url = ''; $pm_url = '';
$status_link = ''; $status_link = '';
$photos_link = ''; $photos_link = '';
$contact_drop_link = '';
$poke_link = ''; $poke_link = '';
if ($uid == 0) { if ($uid == 0) {
@ -1016,13 +1045,9 @@ class Contact
$posts_link = DI::baseUrl() . '/contact/' . $contact['id'] . '/conversations'; $posts_link = DI::baseUrl() . '/contact/' . $contact['id'] . '/conversations';
if (!$contact['self']) {
$contact_drop_link = DI::baseUrl() . '/contact/' . $contact['id'] . '/drop?confirm=1';
}
$follow_link = ''; $follow_link = '';
$unfollow_link = ''; $unfollow_link = '';
if (!$contact['self'] && in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { if (!$contact['self'] && Protocol::supportsFollow($contact['network'])) {
if ($contact['uid'] && in_array($contact['rel'], [self::SHARING, self::FRIEND])) { if ($contact['uid'] && in_array($contact['rel'], [self::SHARING, self::FRIEND])) {
$unfollow_link = 'unfollow?url=' . urlencode($contact['url']) . '&auto=1'; $unfollow_link = 'unfollow?url=' . urlencode($contact['url']) . '&auto=1';
} elseif(!$contact['pending']) { } elseif(!$contact['pending']) {
@ -1030,10 +1055,6 @@ class Contact
} }
} }
if (!empty($follow_link) || !empty($unfollow_link)) {
$contact_drop_link = '';
}
/** /**
* Menu array: * Menu array:
* "name" => [ "Label", "link", (bool)Should the link opened in a new tab? ] * "name" => [ "Label", "link", (bool)Should the link opened in a new tab? ]
@ -1053,7 +1074,6 @@ class Contact
'photos' => [DI::l10n()->t('View Photos') , $photos_link , true], 'photos' => [DI::l10n()->t('View Photos') , $photos_link , true],
'network' => [DI::l10n()->t('Network Posts') , $posts_link , false], 'network' => [DI::l10n()->t('Network Posts') , $posts_link , false],
'edit' => [DI::l10n()->t('View Contact') , $contact_url , false], 'edit' => [DI::l10n()->t('View Contact') , $contact_url , false],
'drop' => [DI::l10n()->t('Drop Contact') , $contact_drop_link, false],
'pm' => [DI::l10n()->t('Send PM') , $pm_url , false], 'pm' => [DI::l10n()->t('Send PM') , $pm_url , false],
'poke' => [DI::l10n()->t('Poke') , $poke_link , false], 'poke' => [DI::l10n()->t('Poke') , $poke_link , false],
'follow' => [DI::l10n()->t('Connect/Follow'), $follow_link , true], 'follow' => [DI::l10n()->t('Connect/Follow'), $follow_link , true],
@ -1340,12 +1360,13 @@ class Contact
* @param bool $thread_mode * @param bool $thread_mode
* @param int $update Update mode * @param int $update Update mode
* @param int $parent Item parent ID for the update mode * @param int $parent Item parent ID for the update mode
* @param bool $only_media Only display media content
* @return string posts in HTML * @return string posts in HTML
* @throws \Exception * @throws \Exception
*/ */
public static function getPostsFromUrl($contact_url, $thread_mode = false, $update = 0, $parent = 0) public static function getPostsFromUrl($contact_url, $thread_mode = false, $update = 0, $parent = 0, bool $only_media = false)
{ {
return self::getPostsFromId(self::getIdForURL($contact_url), $thread_mode, $update, $parent); return self::getPostsFromId(self::getIdForURL($contact_url), $thread_mode, $update, $parent, $only_media);
} }
/** /**
@ -1354,14 +1375,13 @@ class Contact
* @param int $cid Contact ID * @param int $cid Contact ID
* @param bool $thread_mode * @param bool $thread_mode
* @param int $update Update mode * @param int $update Update mode
* @param int $parent Item parent ID for the update mode * @param int $parent Item parent ID for the update mode
* @param bool $only_media Only display media content
* @return string posts in HTML * @return string posts in HTML
* @throws \Exception * @throws \Exception
*/ */
public static function getPostsFromId($cid, $thread_mode = false, $update = 0, $parent = 0) public static function getPostsFromId($cid, $thread_mode = false, $update = 0, $parent = 0, bool $only_media = false)
{ {
$a = DI::app();
$contact = DBA::selectFirst('contact', ['contact-type', 'network'], ['id' => $cid]); $contact = DBA::selectFirst('contact', ['contact-type', 'network'], ['id' => $cid]);
if (!DBA::isResult($contact)) { if (!DBA::isResult($contact)) {
return ''; return '';
@ -1392,6 +1412,11 @@ class Contact
} }
} }
if ($only_media) {
$condition = DBA::mergeConditions($condition, ["`uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?))",
Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO]);
}
if (DI::mode()->isMobile()) { if (DI::mode()->isMobile()) {
$itemsPerPage = DI::pConfig()->get(local_user(), 'system', 'itemspage_mobile_network', $itemsPerPage = DI::pConfig()->get(local_user(), 'system', 'itemspage_mobile_network',
DI::config()->get('system', 'itemspage_network_mobile')); DI::config()->get('system', 'itemspage_network_mobile'));

View file

@ -68,15 +68,14 @@ class BaseProfile extends BaseModule
'id' => 'photo-tab', 'id' => 'photo-tab',
'accesskey' => 'h', 'accesskey' => 'h',
], ],
// @todo Currently deactivated since it doesn't really work [
// [ 'label' => DI::l10n()->t('Media'),
// 'label' => DI::l10n()->t('Videos'), 'url' => $baseProfileUrl . '/media',
// 'url' => DI::baseUrl() . '/videos/' . $nickname, 'sel' => $current == 'media' ? 'active' : '',
// 'sel' => $current == 'videos' ? 'active' : '', 'title' => DI::l10n()->t('Media'),
// 'title' => DI::l10n()->t('Videos'), 'id' => 'media-tab',
// 'id' => 'video-tab', 'accesskey' => 'd',
// 'accesskey' => 'v', ],
// ],
]; ];
// the calendar link for the full featured events calendar // the calendar link for the full featured events calendar

View file

@ -52,6 +52,7 @@ class Contact extends BaseModule
const TAB_PROFILE = 3; const TAB_PROFILE = 3;
const TAB_CONTACTS = 4; const TAB_CONTACTS = 4;
const TAB_ADVANCED = 5; const TAB_ADVANCED = 5;
const TAB_MEDIA = 6;
private static function batchActions() private static function batchActions()
{ {
@ -86,12 +87,6 @@ class Contact extends BaseModule
self::toggleIgnoreContact($cdata['public']); self::toggleIgnoreContact($cdata['public']);
$count_actions++; $count_actions++;
} }
if (!empty($_POST['contacts_batch_drop']) && $cdata['user']
&& self::dropContact($cdata['user'], local_user())
) {
$count_actions++;
}
} }
if ($count_actions > 0) { if ($count_actions > 0) {
info(DI::l10n()->tt('%d contact edited.', '%d contacts edited.', $count_actions)); info(DI::l10n()->tt('%d contact edited.', '%d contacts edited.', $count_actions));
@ -229,31 +224,6 @@ class Contact extends BaseModule
Model\Contact\User::setIgnored($contact_id, local_user(), $ignored); Model\Contact\User::setIgnored($contact_id, local_user(), $ignored);
} }
/**
* @param int $contact_id Id for contact with uid != 0
* @param int $uid Id for user we want to drop the contact for
* @return bool
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
private static function dropContact(int $contact_id, int $uid): bool
{
$contact = Model\Contact::getContactForUser($contact_id, $uid);
if (!DBA::isResult($contact)) {
return false;
}
$owner = Model\User::getOwnerDataById($uid);
if (!DBA::isResult($owner)) {
return false;
}
Model\Contact::terminateFriendship($owner, $contact, true);
Model\Contact::remove($contact['id']);
return true;
}
public static function content(array $parameters = [], $update = 0) public static function content(array $parameters = [], $update = 0)
{ {
if (!local_user()) { if (!local_user()) {
@ -372,7 +342,7 @@ class Contact extends BaseModule
} }
if ($cmd === 'posts') { if ($cmd === 'posts') {
return self::getPostsHTML($a, $contact_id); return self::getPostsHTML($contact_id);
} }
if ($cmd === 'conversations') { if ($cmd === 'conversations') {
@ -425,36 +395,6 @@ class Contact extends BaseModule
DI::baseUrl()->redirect('contact/' . $cdata['public']); DI::baseUrl()->redirect('contact/' . $cdata['public']);
// NOTREACHED // NOTREACHED
} }
if ($cmd === 'drop' && $cdata['user']) {
// Check if we should do HTML-based delete confirmation
if (!empty($_REQUEST['confirm'])) {
DI::page()['aside'] = '';
return Renderer::replaceMacros(Renderer::getMarkupTemplate('contact_drop_confirm.tpl'), [
'$header' => DI::l10n()->t('Drop contact'),
'$contact' => self::getContactTemplateVars($orig_record),
'$method' => 'get',
'$message' => DI::l10n()->t('Do you really want to delete this contact?'),
'$confirm' => DI::l10n()->t('Yes'),
'$confirm_url' => DI::args()->getCommand(),
'$confirm_name' => 't',
'$confirm_value' => BaseModule::getFormSecurityToken('contact_action'),
'$cancel' => DI::l10n()->t('Cancel'),
]);
}
// Now check how the user responded to the confirmation query
if (!empty($_REQUEST['canceled'])) {
DI::baseUrl()->redirect('contact');
}
if (self::dropContact($cdata['user'], local_user())) {
info(DI::l10n()->t('Contact has been removed.'));
}
DI::baseUrl()->redirect('contact');
// NOTREACHED
}
} }
$_SESSION['return_path'] = DI::args()->getQueryString(); $_SESSION['return_path'] = DI::args()->getQueryString();
@ -856,13 +796,11 @@ class Contact extends BaseModule
'$cmd' => DI::args()->getCommand(), '$cmd' => DI::args()->getCommand(),
'$contacts' => $contacts, '$contacts' => $contacts,
'$form_security_token' => BaseModule::getFormSecurityToken('contact_batch_actions'), '$form_security_token' => BaseModule::getFormSecurityToken('contact_batch_actions'),
'$contact_drop_confirm' => DI::l10n()->t('Do you really want to delete this contact?'),
'multiselect' => 1, 'multiselect' => 1,
'$batch_actions' => [ '$batch_actions' => [
'contacts_batch_update' => DI::l10n()->t('Update'), 'contacts_batch_update' => DI::l10n()->t('Update'),
'contacts_batch_block' => DI::l10n()->t('Block') . '/' . DI::l10n()->t('Unblock'), 'contacts_batch_block' => DI::l10n()->t('Block') . '/' . DI::l10n()->t('Unblock'),
'contacts_batch_ignore' => DI::l10n()->t('Ignore') . '/' . DI::l10n()->t('Unignore'), 'contacts_batch_ignore' => DI::l10n()->t('Ignore') . '/' . DI::l10n()->t('Unignore'),
'contacts_batch_drop' => DI::l10n()->t('Delete'),
], ],
'$h_batch_actions' => DI::l10n()->t('Batch Actions'), '$h_batch_actions' => DI::l10n()->t('Batch Actions'),
'$paginate' => $pager->renderFull($total), '$paginate' => $pager->renderFull($total),
@ -911,6 +849,14 @@ class Contact extends BaseModule
'id' => 'posts-tab', 'id' => 'posts-tab',
'accesskey' => 'p', 'accesskey' => 'p',
], ],
[
'label' => DI::l10n()->t('Media'),
'url' => 'contact/' . $pcid . '/media',
'sel' => (($active_tab == self::TAB_MEDIA) ? 'active' : ''),
'title' => DI::l10n()->t('Posts containing media objects'),
'id' => 'media-tab',
'accesskey' => 'd',
],
[ [
'label' => DI::l10n()->t('Profile'), 'label' => DI::l10n()->t('Profile'),
'url' => 'contact/' . $cid, 'url' => 'contact/' . $cid,
@ -979,7 +925,7 @@ class Contact extends BaseModule
return $o; return $o;
} }
private static function getPostsHTML($a, $contact_id) private static function getPostsHTML(int $contact_id)
{ {
$contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id, 'deleted' => false]); $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id, 'deleted' => false]);
@ -1145,13 +1091,13 @@ class Contact extends BaseModule
'id' => 'toggle-ignore', 'id' => 'toggle-ignore',
]; ];
if ($contact['uid'] != 0) { if ($contact['uid'] != 0 && Protocol::supportsRevokeFollow($contact['network']) && in_array($contact['rel'], [Model\Contact::FOLLOWER, Model\Contact::FRIEND])) {
$contact_actions['delete'] = [ $contact_actions['revoke_follow'] = [
'label' => DI::l10n()->t('Delete'), 'label' => DI::l10n()->t('Revoke Follow'),
'url' => 'contact/' . $contact['id'] . '/drop?t=' . $formSecurityToken, 'url' => 'contact/' . $contact['id'] . '/revoke',
'title' => DI::l10n()->t('Delete contact'), 'title' => DI::l10n()->t('Revoke the follow from this contact'),
'sel' => '', 'sel' => '',
'id' => 'delete', 'id' => 'revoke_follow',
]; ];
} }

View file

@ -0,0 +1,54 @@
<?php
/**
* @copyright Copyright (C) 2010-2021, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Module\Contact;
use Friendica\BaseModule;
use Friendica\Content\Widget;
use Friendica\DI;
use Friendica\Model;
use Friendica\Model\Contact as ModelContact;
use Friendica\Module\Contact;
use Friendica\Network\HTTPException\BadRequestException;
/**
* GUI for media posts of a contact
*/
class Media extends BaseModule
{
public static function content(array $parameters = [])
{
$cid = $parameters['id'];
$contact = Model\Contact::selectFirst([], ['id' => $cid]);
if (empty($contact)) {
throw new BadRequestException(DI::l10n()->t('Contact not found.'));
}
DI::page()['aside'] = Widget\VCard::getHTML($contact);
$o = Contact::getTabsHTML($contact, Contact::TAB_MEDIA);
$o .= ModelContact::getPostsFromUrl($contact['url'], false, 0, 0, true);
return $o;
}
}

View file

@ -0,0 +1,108 @@
<?php
/**
* @copyright Copyright (C) 2010-2021, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Module\Contact;
use Friendica\BaseModule;
use Friendica\Content\Nav;
use Friendica\Core\Protocol;
use Friendica\Core\Renderer;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model;
use Friendica\Module\Contact;
use Friendica\Module\Security\Login;
use Friendica\Network\HTTPException;
class Revoke extends BaseModule
{
/** @var array */
private static $contact;
public static function init(array $parameters = [])
{
if (!local_user()) {
return;
}
$data = Model\Contact::getPublicAndUserContactID($parameters['id'], local_user());
if (!DBA::isResult($data)) {
throw new HTTPException\NotFoundException(DI::l10n()->t('Unknown contact.'));
}
if (empty($data['user'])) {
throw new HTTPException\ForbiddenException();
}
self::$contact = Model\Contact::getById($data['user']);
if (self::$contact['deleted']) {
throw new HTTPException\NotFoundException(DI::l10n()->t('Contact is deleted.'));
}
if (!empty(self::$contact['network']) && self::$contact['network'] == Protocol::PHANTOM) {
throw new HTTPException\NotFoundException(DI::l10n()->t('Contact is being deleted.'));
}
}
public static function post(array $parameters = [])
{
if (!local_user()) {
throw new HTTPException\UnauthorizedException();
}
self::checkFormSecurityTokenRedirectOnError('contact/' . $parameters['id'], 'contact_revoke');
$result = Model\Contact::revokeFollow(self::$contact);
if ($result === true) {
notice(DI::l10n()->t('Follow was successfully revoked.'));
} elseif ($result === null) {
notice(DI::l10n()->t('Follow was successfully revoked, however the remote contact won\'t be aware of this revokation.'));
} else {
notice(DI::l10n()->t('Unable to revoke follow, please try again later or contact the administrator.'));
}
DI::baseUrl()->redirect('contact/' . $parameters['id']);
}
public static function content(array $parameters = []): string
{
if (!local_user()) {
return Login::form($_SERVER['REQUEST_URI']);
}
Nav::setSelected('contact');
return Renderer::replaceMacros(Renderer::getMarkupTemplate('contact_drop_confirm.tpl'), [
'$l10n' => [
'header' => DI::l10n()->t('Revoke Follow'),
'message' => DI::l10n()->t('Do you really want to revoke this contact\'s follow? This cannot be undone and they will have to manually follow you back again.'),
'confirm' => DI::l10n()->t('Yes'),
'cancel' => DI::l10n()->t('Cancel'),
],
'$contact' => Contact::getContactTemplateVars(self::$contact),
'$method' => 'post',
'$confirm_url' => DI::args()->getCommand(),
'$confirm_name' => 'form_security_token',
'$confirm_value' => BaseModule::getFormSecurityToken('contact_revoke'),
]);
}
}

View file

@ -0,0 +1,53 @@
<?php
/**
* @copyright Copyright (C) 2010-2021, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Module\Profile;
use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\Profile as ProfileModel;
use Friendica\Module\BaseProfile;
use Friendica\Network\HTTPException;
class Media extends BaseProfile
{
public static function content(array $parameters = [])
{
$a = DI::app();
$profile = ProfileModel::load($a, $parameters['nickname']);
if (empty($profile)) {
throw new HTTPException\NotFoundException(DI::l10n()->t('User not found.'));
}
if (!$profile['net-publish']) {
DI::page()['htmlhead'] .= '<meta content="noindex, noarchive" name="robots" />' . "\n";
}
$is_owner = local_user() == $profile['uid'];
$o = self::getTabsHTML($a, 'media', $is_owner, $profile['nickname'], $profile['hide-friends']);
$o .= Contact::getPostsFromUrl($profile['url'], false, 0, 0, true);
return $o;
}
}

View file

@ -1037,9 +1037,12 @@ class Processor
self::switchContact($cid); self::switchContact($cid);
if (DBA::exists('contact', ['id' => $cid, 'rel' => Contact::SHARING])) { $contact = Contact::getById($cid, ['rel']);
if ($contact['rel'] == Contact::SHARING) {
Contact::remove($cid); Contact::remove($cid);
Logger::info('Rejected contact request - contact removed', ['contact' => $cid, 'user' => $uid]); Logger::info('Rejected contact request - contact removed', ['contact' => $cid, 'user' => $uid]);
} elseif ($contact['rel'] == Contact::FRIEND) {
Contact::update(['rel' => Contact::FOLLOWER], ['id' => $cid]);
} else { } else {
Logger::info('Rejected contact request', ['contact' => $cid, 'user' => $uid]); Logger::info('Rejected contact request', ['contact' => $cid, 'user' => $uid]);
} }

View file

@ -2047,15 +2047,16 @@ class Transmitter
* @param string $target Target profile * @param string $target Target profile
* @param $id * @param $id
* @param integer $uid User ID * @param integer $uid User ID
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @return bool Operation success
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException * @throws \ImagickException
*/ */
public static function sendContactReject($target, $id, $uid) public static function sendContactReject($target, $id, $uid): bool
{ {
$profile = APContact::getByURL($target); $profile = APContact::getByURL($target);
if (empty($profile['inbox'])) { if (empty($profile['inbox'])) {
Logger::warning('No inbox found for target', ['target' => $target, 'profile' => $profile]); Logger::warning('No inbox found for target', ['target' => $target, 'profile' => $profile]);
return; return false;
} }
$owner = User::getOwnerDataById($uid); $owner = User::getOwnerDataById($uid);
@ -2075,7 +2076,7 @@ class Transmitter
Logger::debug('Sending reject to ' . $target . ' for user ' . $uid . ' with id ' . $id); Logger::debug('Sending reject to ' . $target . ' for user ' . $uid . ' with id ' . $id);
$signed = LDSignature::sign($data, $owner); $signed = LDSignature::sign($data, $owner);
HTTPSignature::transmit($signed, $profile['inbox'], $uid); return HTTPSignature::transmit($signed, $profile['inbox'], $uid);
} }
/** /**

View file

@ -37,6 +37,7 @@ $profileRoutes = [
'/contacts/common' => [Module\Profile\Common::class, [R::GET]], '/contacts/common' => [Module\Profile\Common::class, [R::GET]],
'/contacts[/{type}]' => [Module\Profile\Contacts::class, [R::GET]], '/contacts[/{type}]' => [Module\Profile\Contacts::class, [R::GET]],
'/status[/{category}[/{date1}[/{date2}]]]' => [Module\Profile\Status::class, [R::GET]], '/status[/{category}[/{date1}[/{date2}]]]' => [Module\Profile\Status::class, [R::GET]],
'/media' => [Module\Profile\Media::class, [R::GET]],
]; ];
return [ return [
@ -235,10 +236,11 @@ return [
'/{id:\d+}/block' => [Module\Contact::class, [R::GET]], '/{id:\d+}/block' => [Module\Contact::class, [R::GET]],
'/{id:\d+}/conversations' => [Module\Contact::class, [R::GET]], '/{id:\d+}/conversations' => [Module\Contact::class, [R::GET]],
'/{id:\d+}/contacts[/{type}]' => [Module\Contact\Contacts::class, [R::GET]], '/{id:\d+}/contacts[/{type}]' => [Module\Contact\Contacts::class, [R::GET]],
'/{id:\d+}/drop' => [Module\Contact::class, [R::GET]],
'/{id:\d+}/ignore' => [Module\Contact::class, [R::GET]], '/{id:\d+}/ignore' => [Module\Contact::class, [R::GET]],
'/{id:\d+}/media' => [Module\Contact\Media::class, [R::GET]],
'/{id:\d+}/poke' => [Module\Contact\Poke::class, [R::GET, R::POST]], '/{id:\d+}/poke' => [Module\Contact\Poke::class, [R::GET, R::POST]],
'/{id:\d+}/posts' => [Module\Contact::class, [R::GET]], '/{id:\d+}/posts' => [Module\Contact::class, [R::GET]],
'/{id:\d+}/revoke' => [Module\Contact\Revoke::class, [R::GET, R::POST]],
'/{id:\d+}/update' => [Module\Contact::class, [R::GET]], '/{id:\d+}/update' => [Module\Contact::class, [R::GET]],
'/{id:\d+}/updateprofile' => [Module\Contact::class, [R::GET]], '/{id:\d+}/updateprofile' => [Module\Contact::class, [R::GET]],
'/archived' => [Module\Contact::class, [R::GET]], '/archived' => [Module\Contact::class, [R::GET]],

File diff suppressed because it is too large Load diff

View file

@ -49,8 +49,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: friendica\n" "Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-01 16:40+0200\n" "POT-Creation-Date: 2021-10-02 08:34-0400\n"
"PO-Revision-Date: 2021-10-01 15:32+0000\n" "PO-Revision-Date: 2021-10-02 19:18+0000\n"
"Last-Translator: Tobias Diekershoff <tobias.diekershoff@gmx.net>\n" "Last-Translator: Tobias Diekershoff <tobias.diekershoff@gmx.net>\n"
"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n" "Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -79,7 +79,7 @@ msgstr[1] "Das wöchentliche Limit von %d Beiträgen wurde erreicht. Der Beitrag
msgid "Monthly posting limit of %d post reached. The post was rejected." msgid "Monthly posting limit of %d post reached. The post was rejected."
msgstr "Das monatliche Limit von %d Beiträgen wurde erreicht. Der Beitrag wurde verworfen." msgstr "Das monatliche Limit von %d Beiträgen wurde erreicht. Der Beitrag wurde verworfen."
#: include/api.php:4437 mod/photos.php:89 mod/photos.php:198 #: include/api.php:4430 mod/photos.php:89 mod/photos.php:198
#: mod/photos.php:626 mod/photos.php:1035 mod/photos.php:1052 #: mod/photos.php:626 mod/photos.php:1035 mod/photos.php:1052
#: mod/photos.php:1599 src/Model/User.php:1169 src/Model/User.php:1177 #: mod/photos.php:1599 src/Model/User.php:1169 src/Model/User.php:1177
#: src/Model/User.php:1185 src/Module/Settings/Profile/Photo/Crop.php:101 #: src/Model/User.php:1185 src/Module/Settings/Profile/Photo/Crop.php:101
@ -602,7 +602,7 @@ msgstr "Abbrechen"
#: mod/editpost.php:134 src/Content/Conversation.php:380 #: mod/editpost.php:134 src/Content/Conversation.php:380
#: src/Content/Widget/VCard.php:107 src/Model/Profile.php:459 #: src/Content/Widget/VCard.php:107 src/Model/Profile.php:459
#: src/Module/Admin/Logs/View.php:93 #: src/Module/Admin/Logs/View.php:92
msgid "Message" msgid "Message"
msgstr "Nachricht" msgstr "Nachricht"
@ -632,7 +632,7 @@ msgstr "Der Veranstaltungstitel und die Anfangszeit müssen angegeben werden."
msgid "Create New Event" msgid "Create New Event"
msgstr "Neue Veranstaltung erstellen" msgstr "Neue Veranstaltung erstellen"
#: mod/events.php:536 src/Module/Admin/Logs/View.php:97 #: mod/events.php:536 src/Module/Admin/Logs/View.php:96
msgid "Event details" msgid "Event details"
msgstr "Veranstaltungsdetails" msgstr "Veranstaltungsdetails"
@ -761,7 +761,7 @@ msgid "OStatus support is disabled. Contact can't be added."
msgstr "OStatus-Unterstützung ist nicht aktiviert. Der Kontakt kann nicht zugefügt werden." msgstr "OStatus-Unterstützung ist nicht aktiviert. Der Kontakt kann nicht zugefügt werden."
#: mod/follow.php:138 src/Content/Item.php:463 src/Content/Widget.php:76 #: mod/follow.php:138 src/Content/Item.php:463 src/Content/Widget.php:76
#: src/Model/Contact.php:1051 src/Model/Contact.php:1064 #: src/Model/Contact.php:1046 src/Model/Contact.php:1059
#: view/theme/vier/theme.php:172 #: view/theme/vier/theme.php:172
msgid "Connect/Follow" msgid "Connect/Follow"
msgstr "Verbinden/Folgen" msgstr "Verbinden/Folgen"
@ -2321,11 +2321,11 @@ msgid ""
"select \"Export account\"" "select \"Export account\""
msgstr "Um Deinen Account zu exportieren, rufe \"Einstellungen -> Persönliche Daten exportieren\" auf und wähle \"Account exportieren\"" msgstr "Um Deinen Account zu exportieren, rufe \"Einstellungen -> Persönliche Daten exportieren\" auf und wähle \"Account exportieren\""
#: mod/unfollow.php:65 mod/unfollow.php:129 #: mod/unfollow.php:65 mod/unfollow.php:135
msgid "You aren't following this contact." msgid "You aren't following this contact."
msgstr "Du folgst diesem Kontakt." msgstr "Du folgst diesem Kontakt."
#: mod/unfollow.php:71 mod/unfollow.php:135 #: mod/unfollow.php:71
msgid "Unfollowing is currently not supported by your network." msgid "Unfollowing is currently not supported by your network."
msgstr "Bei diesem Netzwerk wird das Entfolgen derzeit nicht unterstützt." msgstr "Bei diesem Netzwerk wird das Entfolgen derzeit nicht unterstützt."
@ -2333,6 +2333,24 @@ msgstr "Bei diesem Netzwerk wird das Entfolgen derzeit nicht unterstützt."
msgid "Disconnect/Unfollow" msgid "Disconnect/Unfollow"
msgstr "Verbindung lösen/Nicht mehr folgen" msgstr "Verbindung lösen/Nicht mehr folgen"
#: mod/unfollow.php:149
msgid "Unfollowing is currently not supported by this contact's network."
msgstr "Bei dem Netzwerk dieses Kontakts wird das Entfolgen derzeit nicht unterstützt."
#: mod/unfollow.php:153
msgid ""
"Unable to unfollow this contact, please retry in a few minutes or contact "
"your administrator."
msgstr "Konnte dem Kontakt nicht entfolgen. Bitte warte ein paar Minuten und versuche es dann noch einmal, oder kontaktiere deinen Administrator."
#: mod/unfollow.php:157
msgid "Contact was successfully unfollowed"
msgstr "Kontakt wurde erfolgreich entfolgt."
#: mod/unfollow.php:161
msgid "Unable to unfollow this contact, please contact your administrator"
msgstr "Konnte dem Kontakt nicht entfolgen. Bitte kontaktiere deinen Administrator."
#: mod/videos.php:120 #: mod/videos.php:120
msgid "No videos selected" msgid "No videos selected"
msgstr "Keine Videos ausgewählt" msgstr "Keine Videos ausgewählt"
@ -2469,12 +2487,12 @@ msgstr "Addon bereits aktiviert"
msgid "Addon already disabled" msgid "Addon already disabled"
msgstr "Addon bereits deaktiviert" msgstr "Addon bereits deaktiviert"
#: src/Console/ArchiveContact.php:105 #: src/Console/ArchiveContact.php:106
#, php-format #, php-format
msgid "Could not find any unarchived contact entry for this URL (%s)" msgid "Could not find any unarchived contact entry for this URL (%s)"
msgstr "Für die URL (%s) konnte kein nicht-archivierter Kontakt gefunden werden" msgstr "Für die URL (%s) konnte kein nicht-archivierter Kontakt gefunden werden"
#: src/Console/ArchiveContact.php:108 #: src/Console/ArchiveContact.php:109
msgid "The contact entries have been archived" msgid "The contact entries have been archived"
msgstr "Die Kontakteinträge wurden archiviert." msgstr "Die Kontakteinträge wurden archiviert."
@ -3047,31 +3065,31 @@ msgstr "Veranstaltung"
msgid "Follow Thread" msgid "Follow Thread"
msgstr "Folge der Unterhaltung" msgstr "Folge der Unterhaltung"
#: src/Content/Item.php:443 src/Model/Contact.php:1056 #: src/Content/Item.php:443 src/Model/Contact.php:1051
msgid "View Status" msgid "View Status"
msgstr "Status anschauen" msgstr "Status anschauen"
#: src/Content/Item.php:444 src/Content/Item.php:466 src/Model/Contact.php:982 #: src/Content/Item.php:444 src/Content/Item.php:466 src/Model/Contact.php:977
#: src/Model/Contact.php:1048 src/Model/Contact.php:1057 #: src/Model/Contact.php:1043 src/Model/Contact.php:1052
#: src/Module/Directory.php:160 src/Module/Settings/Profile/Index.php:223 #: src/Module/Directory.php:160 src/Module/Settings/Profile/Index.php:223
msgid "View Profile" msgid "View Profile"
msgstr "Profil anschauen" msgstr "Profil anschauen"
#: src/Content/Item.php:445 src/Model/Contact.php:1058 #: src/Content/Item.php:445 src/Model/Contact.php:1053
msgid "View Photos" msgid "View Photos"
msgstr "Bilder anschauen" msgstr "Bilder anschauen"
#: src/Content/Item.php:446 src/Model/Contact.php:1049 #: src/Content/Item.php:446 src/Model/Contact.php:1044
#: src/Model/Contact.php:1059 #: src/Model/Contact.php:1054
msgid "Network Posts" msgid "Network Posts"
msgstr "Netzwerkbeiträge" msgstr "Netzwerkbeiträge"
#: src/Content/Item.php:447 src/Model/Contact.php:1050 #: src/Content/Item.php:447 src/Model/Contact.php:1045
#: src/Model/Contact.php:1060 #: src/Model/Contact.php:1055
msgid "View Contact" msgid "View Contact"
msgstr "Kontakt anzeigen" msgstr "Kontakt anzeigen"
#: src/Content/Item.php:448 src/Model/Contact.php:1062 #: src/Content/Item.php:448 src/Model/Contact.php:1057
msgid "Send PM" msgid "Send PM"
msgstr "Private Nachricht senden" msgstr "Private Nachricht senden"
@ -3094,7 +3112,7 @@ msgstr "Ignorieren"
msgid "Languages" msgid "Languages"
msgstr "Sprachen" msgstr "Sprachen"
#: src/Content/Item.php:458 src/Model/Contact.php:1063 #: src/Content/Item.php:458 src/Model/Contact.php:1058
msgid "Poke" msgid "Poke"
msgstr "Anstupsen" msgstr "Anstupsen"
@ -3211,7 +3229,7 @@ msgid "Addon applications, utilities, games"
msgstr "Zusätzliche Anwendungen, Dienstprogramme, Spiele" msgstr "Zusätzliche Anwendungen, Dienstprogramme, Spiele"
#: src/Content/Nav.php:230 src/Content/Text/HTML.php:891 #: src/Content/Nav.php:230 src/Content/Text/HTML.php:891
#: src/Module/Admin/Logs/View.php:87 src/Module/Search/Index.php:99 #: src/Module/Admin/Logs/View.php:86 src/Module/Search/Index.php:99
msgid "Search" msgid "Search"
msgstr "Suche" msgstr "Suche"
@ -3543,7 +3561,7 @@ msgstr "Personen"
msgid "Organisations" msgid "Organisations"
msgstr "Organisationen" msgstr "Organisationen"
#: src/Content/Widget.php:529 src/Model/Contact.php:1480 #: src/Content/Widget.php:529 src/Model/Contact.php:1474
msgid "News" msgid "News"
msgstr "Nachrichten" msgstr "Nachrichten"
@ -4407,85 +4425,85 @@ msgstr "%s ist jetzt mit %s befreundet"
msgid "Legacy module file not found: %s" msgid "Legacy module file not found: %s"
msgstr "Legacy-Moduldatei nicht gefunden: %s" msgstr "Legacy-Moduldatei nicht gefunden: %s"
#: src/Model/Contact.php:1052 src/Model/Contact.php:1065 #: src/Model/Contact.php:1047 src/Model/Contact.php:1060
msgid "UnFollow" msgid "UnFollow"
msgstr "Entfolgen" msgstr "Entfolgen"
#: src/Model/Contact.php:1061 #: src/Model/Contact.php:1056
msgid "Drop Contact" msgid "Drop Contact"
msgstr "Kontakt löschen" msgstr "Kontakt löschen"
#: src/Model/Contact.php:1071 src/Module/Admin/Users/Pending.php:107 #: src/Model/Contact.php:1066 src/Module/Admin/Users/Pending.php:107
#: src/Module/Notifications/Introductions.php:111 #: src/Module/Notifications/Introductions.php:111
#: src/Module/Notifications/Introductions.php:183 #: src/Module/Notifications/Introductions.php:183
msgid "Approve" msgid "Approve"
msgstr "Genehmigen" msgstr "Genehmigen"
#: src/Model/Contact.php:1476 #: src/Model/Contact.php:1470
msgid "Organisation" msgid "Organisation"
msgstr "Organisation" msgstr "Organisation"
#: src/Model/Contact.php:1484 #: src/Model/Contact.php:1478
msgid "Forum" msgid "Forum"
msgstr "Forum" msgstr "Forum"
#: src/Model/Contact.php:2340 #: src/Model/Contact.php:2334
msgid "Disallowed profile URL." msgid "Disallowed profile URL."
msgstr "Nicht erlaubte Profil-URL." msgstr "Nicht erlaubte Profil-URL."
#: src/Model/Contact.php:2345 src/Module/Friendica.php:81 #: src/Model/Contact.php:2339 src/Module/Friendica.php:81
msgid "Blocked domain" msgid "Blocked domain"
msgstr "Blockierte Domain" msgstr "Blockierte Domain"
#: src/Model/Contact.php:2350 #: src/Model/Contact.php:2344
msgid "Connect URL missing." msgid "Connect URL missing."
msgstr "Connect-URL fehlt" msgstr "Connect-URL fehlt"
#: src/Model/Contact.php:2359 #: src/Model/Contact.php:2353
msgid "" msgid ""
"The contact could not be added. Please check the relevant network " "The contact could not be added. Please check the relevant network "
"credentials in your Settings -> Social Networks page." "credentials in your Settings -> Social Networks page."
msgstr "Der Kontakt konnte nicht hinzugefügt werden. Bitte überprüfe die Einstellungen unter Einstellungen -> Soziale Netzwerke" msgstr "Der Kontakt konnte nicht hinzugefügt werden. Bitte überprüfe die Einstellungen unter Einstellungen -> Soziale Netzwerke"
#: src/Model/Contact.php:2396 #: src/Model/Contact.php:2390
msgid "The profile address specified does not provide adequate information." msgid "The profile address specified does not provide adequate information."
msgstr "Die angegebene Profiladresse liefert unzureichende Informationen." msgstr "Die angegebene Profiladresse liefert unzureichende Informationen."
#: src/Model/Contact.php:2398 #: src/Model/Contact.php:2392
msgid "No compatible communication protocols or feeds were discovered." msgid "No compatible communication protocols or feeds were discovered."
msgstr "Es wurden keine kompatiblen Kommunikationsprotokolle oder Feeds gefunden." msgstr "Es wurden keine kompatiblen Kommunikationsprotokolle oder Feeds gefunden."
#: src/Model/Contact.php:2401 #: src/Model/Contact.php:2395
msgid "An author or name was not found." msgid "An author or name was not found."
msgstr "Es wurde kein Autor oder Name gefunden." msgstr "Es wurde kein Autor oder Name gefunden."
#: src/Model/Contact.php:2404 #: src/Model/Contact.php:2398
msgid "No browser URL could be matched to this address." msgid "No browser URL could be matched to this address."
msgstr "Zu dieser Adresse konnte keine passende Browser-URL gefunden werden." msgstr "Zu dieser Adresse konnte keine passende Browser-URL gefunden werden."
#: src/Model/Contact.php:2407 #: src/Model/Contact.php:2401
msgid "" msgid ""
"Unable to match @-style Identity Address with a known protocol or email " "Unable to match @-style Identity Address with a known protocol or email "
"contact." "contact."
msgstr "Konnte die @-Adresse mit keinem der bekannten Protokolle oder Email-Kontakte abgleichen." msgstr "Konnte die @-Adresse mit keinem der bekannten Protokolle oder Email-Kontakte abgleichen."
#: src/Model/Contact.php:2408 #: src/Model/Contact.php:2402
msgid "Use mailto: in front of address to force email check." msgid "Use mailto: in front of address to force email check."
msgstr "Verwende mailto: vor der E-Mail-Adresse, um eine Überprüfung der E-Mail-Adresse zu erzwingen." msgstr "Verwende mailto: vor der E-Mail-Adresse, um eine Überprüfung der E-Mail-Adresse zu erzwingen."
#: src/Model/Contact.php:2414 #: src/Model/Contact.php:2408
msgid "" msgid ""
"The profile address specified belongs to a network which has been disabled " "The profile address specified belongs to a network which has been disabled "
"on this site." "on this site."
msgstr "Die Adresse dieses Profils gehört zu einem Netzwerk, mit dem die Kommunikation auf dieser Seite ausgeschaltet wurde." msgstr "Die Adresse dieses Profils gehört zu einem Netzwerk, mit dem die Kommunikation auf dieser Seite ausgeschaltet wurde."
#: src/Model/Contact.php:2419 #: src/Model/Contact.php:2413
msgid "" msgid ""
"Limited profile. This person will be unable to receive direct/personal " "Limited profile. This person will be unable to receive direct/personal "
"notifications from you." "notifications from you."
msgstr "Eingeschränktes Profil. Diese Person wird keine direkten/privaten Nachrichten von dir erhalten können." msgstr "Eingeschränktes Profil. Diese Person wird keine direkten/privaten Nachrichten von dir erhalten können."
#: src/Model/Contact.php:2478 #: src/Model/Contact.php:2472
msgid "Unable to retrieve contact information." msgid "Unable to retrieve contact information."
msgstr "Konnte die Kontaktinformationen nicht empfangen." msgstr "Konnte die Kontaktinformationen nicht empfangen."
@ -5081,7 +5099,7 @@ msgstr "Einschalten"
#: src/Module/Admin/Blocklist/Contact.php:78 #: src/Module/Admin/Blocklist/Contact.php:78
#: src/Module/Admin/Blocklist/Server.php:88 #: src/Module/Admin/Blocklist/Server.php:88
#: src/Module/Admin/Federation.php:159 src/Module/Admin/Item/Delete.php:65 #: src/Module/Admin/Federation.php:159 src/Module/Admin/Item/Delete.php:65
#: src/Module/Admin/Logs/Settings.php:80 src/Module/Admin/Logs/View.php:84 #: src/Module/Admin/Logs/Settings.php:80 src/Module/Admin/Logs/View.php:83
#: src/Module/Admin/Queue.php:72 src/Module/Admin/Site.php:497 #: src/Module/Admin/Queue.php:72 src/Module/Admin/Site.php:497
#: src/Module/Admin/Storage.php:131 src/Module/Admin/Summary.php:233 #: src/Module/Admin/Storage.php:131 src/Module/Admin/Summary.php:233
#: src/Module/Admin/Themes/Details.php:90 #: src/Module/Admin/Themes/Details.php:90
@ -5519,7 +5537,7 @@ msgstr "Mention"
msgid "Implicit Mention" msgid "Implicit Mention"
msgstr "Implicit Mention" msgstr "Implicit Mention"
#: src/Module/Admin/Item/Source.php:73 src/Module/Admin/Logs/View.php:99 #: src/Module/Admin/Item/Source.php:73 src/Module/Admin/Logs/View.php:98
#: src/Module/Debug/ActivityPubConversion.php:62 #: src/Module/Debug/ActivityPubConversion.php:62
msgid "Source" msgid "Source"
msgstr "Quelle" msgstr "Quelle"
@ -5577,82 +5595,82 @@ msgid ""
"'display_errors' is to enable these options, set to '0' to disable them." "'display_errors' is to enable these options, set to '0' to disable them."
msgstr "Um die Protokollierung von PHP-Fehlern und Warnungen vorübergehend zu aktivieren, kannst du der Datei index.php deiner Installation Folgendes voranstellen. Der in der Datei 'error_log' angegebene Dateiname ist relativ zum obersten Verzeichnis von Friendica und muss vom Webserver beschreibbar sein. Die Option '1' für 'log_errors' und 'display_errors' aktiviert diese Optionen, ersetze die '1' durch eine '0', um sie zu deaktivieren." msgstr "Um die Protokollierung von PHP-Fehlern und Warnungen vorübergehend zu aktivieren, kannst du der Datei index.php deiner Installation Folgendes voranstellen. Der in der Datei 'error_log' angegebene Dateiname ist relativ zum obersten Verzeichnis von Friendica und muss vom Webserver beschreibbar sein. Die Option '1' für 'log_errors' und 'display_errors' aktiviert diese Optionen, ersetze die '1' durch eine '0', um sie zu deaktivieren."
#: src/Module/Admin/Logs/View.php:71 #: src/Module/Admin/Logs/View.php:70
#, php-format #, php-format
msgid "" msgid ""
"Error trying to open <strong>%1$s</strong> log file.<br/>Check to see if " "Error trying to open <strong>%1$s</strong> log file.<br/>Check to see if "
"file %1$s exist and is readable." "file %1$s exist and is readable."
msgstr "Fehler beim Öffnen der Logdatei <strong>%1$s</strong>.<br/>Bitte überprüfe ob die Datei %1$s existiert und gelesen werden kann." msgstr "Fehler beim Öffnen der Logdatei <strong>%1$s</strong>.<br/>Bitte überprüfe ob die Datei %1$s existiert und gelesen werden kann."
#: src/Module/Admin/Logs/View.php:80 #: src/Module/Admin/Logs/View.php:79
#, php-format #, php-format
msgid "" msgid ""
"Couldn't open <strong>%1$s</strong> log file.<br/>Check to see if file %1$s " "Couldn't open <strong>%1$s</strong> log file.<br/>Check to see if file %1$s "
"is readable." "is readable."
msgstr "Konnte die Logdatei <strong>%1$s</strong> nicht öffnen.<br/>Bitte stelle sicher, dass die Datei %1$s lesbar ist." msgstr "Konnte die Logdatei <strong>%1$s</strong> nicht öffnen.<br/>Bitte stelle sicher, dass die Datei %1$s lesbar ist."
#: src/Module/Admin/Logs/View.php:85 src/Module/BaseAdmin.php:110 #: src/Module/Admin/Logs/View.php:84 src/Module/BaseAdmin.php:110
msgid "View Logs" msgid "View Logs"
msgstr "Protokolle anzeigen" msgstr "Protokolle anzeigen"
#: src/Module/Admin/Logs/View.php:88 #: src/Module/Admin/Logs/View.php:87
msgid "Search in logs" msgid "Search in logs"
msgstr "Logs durchsuchen" msgstr "Logs durchsuchen"
#: src/Module/Admin/Logs/View.php:89 #: src/Module/Admin/Logs/View.php:88
#: src/Module/Notifications/Notifications.php:138 #: src/Module/Notifications/Notifications.php:138
msgid "Show all" msgid "Show all"
msgstr "Alle anzeigen" msgstr "Alle anzeigen"
#: src/Module/Admin/Logs/View.php:90 #: src/Module/Admin/Logs/View.php:89
msgid "Date" msgid "Date"
msgstr "Datum" msgstr "Datum"
#: src/Module/Admin/Logs/View.php:91 #: src/Module/Admin/Logs/View.php:90
msgid "Level" msgid "Level"
msgstr "Level" msgstr "Level"
#: src/Module/Admin/Logs/View.php:92 #: src/Module/Admin/Logs/View.php:91
msgid "Context" msgid "Context"
msgstr "Zusammenhang" msgstr "Zusammenhang"
#: src/Module/Admin/Logs/View.php:94 #: src/Module/Admin/Logs/View.php:93
msgid "ALL" msgid "ALL"
msgstr "ALLE" msgstr "ALLE"
#: src/Module/Admin/Logs/View.php:95 #: src/Module/Admin/Logs/View.php:94
msgid "View details" msgid "View details"
msgstr "Details anzeigen" msgstr "Details anzeigen"
#: src/Module/Admin/Logs/View.php:96 #: src/Module/Admin/Logs/View.php:95
msgid "Click to view details" msgid "Click to view details"
msgstr "Anklicken zum Anzeigen der Details" msgstr "Anklicken zum Anzeigen der Details"
#: src/Module/Admin/Logs/View.php:98 #: src/Module/Admin/Logs/View.php:97
msgid "Data" msgid "Data"
msgstr "Daten" msgstr "Daten"
#: src/Module/Admin/Logs/View.php:100 #: src/Module/Admin/Logs/View.php:99
msgid "File" msgid "File"
msgstr "Datei" msgstr "Datei"
#: src/Module/Admin/Logs/View.php:101 #: src/Module/Admin/Logs/View.php:100
msgid "Line" msgid "Line"
msgstr "Zeile" msgstr "Zeile"
#: src/Module/Admin/Logs/View.php:102 #: src/Module/Admin/Logs/View.php:101
msgid "Function" msgid "Function"
msgstr "Funktion" msgstr "Funktion"
#: src/Module/Admin/Logs/View.php:103 #: src/Module/Admin/Logs/View.php:102
msgid "UID" msgid "UID"
msgstr "UID" msgstr "UID"
#: src/Module/Admin/Logs/View.php:104 #: src/Module/Admin/Logs/View.php:103
msgid "Process ID" msgid "Process ID"
msgstr "Prozess ID" msgstr "Prozess ID"
#: src/Module/Admin/Logs/View.php:105 #: src/Module/Admin/Logs/View.php:104
msgid "Close" msgid "Close"
msgstr "Schließen" msgstr "Schließen"

View file

@ -491,6 +491,10 @@ $a->strings["To export your account, go to \"Settings->Export your personal data
$a->strings["You aren't following this contact."] = "Du folgst diesem Kontakt."; $a->strings["You aren't following this contact."] = "Du folgst diesem Kontakt.";
$a->strings["Unfollowing is currently not supported by your network."] = "Bei diesem Netzwerk wird das Entfolgen derzeit nicht unterstützt."; $a->strings["Unfollowing is currently not supported by your network."] = "Bei diesem Netzwerk wird das Entfolgen derzeit nicht unterstützt.";
$a->strings["Disconnect/Unfollow"] = "Verbindung lösen/Nicht mehr folgen"; $a->strings["Disconnect/Unfollow"] = "Verbindung lösen/Nicht mehr folgen";
$a->strings["Unfollowing is currently not supported by this contact's network."] = "Bei dem Netzwerk dieses Kontakts wird das Entfolgen derzeit nicht unterstützt.";
$a->strings["Unable to unfollow this contact, please retry in a few minutes or contact your administrator."] = "Konnte dem Kontakt nicht entfolgen. Bitte warte ein paar Minuten und versuche es dann noch einmal, oder kontaktiere deinen Administrator.";
$a->strings["Contact was successfully unfollowed"] = "Kontakt wurde erfolgreich entfolgt.";
$a->strings["Unable to unfollow this contact, please contact your administrator"] = "Konnte dem Kontakt nicht entfolgen. Bitte kontaktiere deinen Administrator.";
$a->strings["No videos selected"] = "Keine Videos ausgewählt"; $a->strings["No videos selected"] = "Keine Videos ausgewählt";
$a->strings["View Video"] = "Video ansehen"; $a->strings["View Video"] = "Video ansehen";
$a->strings["Recent Videos"] = "Neueste Videos"; $a->strings["Recent Videos"] = "Neueste Videos";

View file

@ -2,10 +2,10 @@
<center> <center>
<form action="{{$confirm_url}}" id="confirm-form" method="{{$method}}"> <form action="{{$confirm_url}}" id="confirm-form" method="{{$method}}">
<h3 id="confirm-message">{{$message}}</h3> <h3 id="confirm-message">{{$l10n.message}}</h3>
<button class="confirm-button" id="confirm-submit-button" type="submit" name="{{$confirm_name}}" value="{{$confirm_value}}">{{$confirm}}</button> <button class="confirm-button" id="confirm-submit-button" type="submit" name="{{$confirm_name}}" value="{{$confirm_value}}">{{$l10n.confirm}}</button>
<button class="confirm-button" id="confirm-cancel-button" type="submit" name="canceled" value="{{$cancel}}">{{$cancel}}</button> <button class="confirm-button" id="confirm-cancel-button" type="submit" name="canceled" value="{{$l10n.cancel}}">{{$l10n.cancel}}</button>
</form> </form>
</center> </center>

View file

@ -1,4 +1,4 @@
<h1>{{$header}}</h1> <h1>{{$l10n.header}}</h1>
{{include file="contact_template.tpl" no_contacts_checkbox=True}} {{include file="contact_template.tpl" no_contacts_checkbox=True}}

View file

@ -15,13 +15,13 @@
<a class="btn" rel="#contact-actions-menu" href="#" id="contact-edit-actions-button">{{$contact_action_button}}</a> <a class="btn" rel="#contact-actions-menu" href="#" id="contact-edit-actions-button">{{$contact_action_button}}</a>
<ul role="menu" aria-haspopup="true" id="contact-actions-menu" class="menu-popup"> <ul role="menu" aria-haspopup="true" id="contact-actions-menu" class="menu-popup">
{{if $lblsuggest}}<li role="menuitem"><a href="#" title="{{$contact_actions.suggest.title}}" onclick="window.location.href='{{$contact_actions.suggest.url}}'; return false;">{{$contact_actions.suggest.label}}</a></li>{{/if}} {{if $lblsuggest}}<li role="menuitem"><a href="#" title="{{$contact_actions.suggest.title}}" onclick="window.location.href='{{$contact_actions.suggest.url}}'; return false;">{{$contact_actions.suggest.label}}</a></li>{{/if}}
{{if $poll_enabled}}<li role="menuitem"><a href="#" title="{{$contact_actions.update.title}}" onclick="window.location.href='{{$contact_actions.update.url}}'; return false;">{{$contact_actions.update.label}}</a></li>{{/if}} {{if $poll_enabled}}<li role="menuitem"><a href="#" title="{{$contact_actions.update.title}}" onclick="window.location.href='{{$contact_actions.update.url}}'; return false;">{{$contact_actions.update.label}}</a></li>{{/if}}
{{if $contact_actions.updateprofile}}<li role="menuitem"><a href="{{$contact_actions.updateprofile.url}}" title="{{$contact_actions.updateprofile.title}}">{{$contact_actions.updateprofile.label}}</a></li>{{/if}} {{if $contact_actions.updateprofile}}<li role="menuitem"><a href="{{$contact_actions.updateprofile.url}}" title="{{$contact_actions.updateprofile.title}}">{{$contact_actions.updateprofile.label}}</a></li>{{/if}}
<li class="divider"></li> <li class="divider"></li>
<li role="menuitem"><a href="#" title="{{$contact_actions.block.title}}" onclick="window.location.href='{{$contact_actions.block.url}}'; return false;">{{$contact_actions.block.label}}</a></li> <li role="menuitem"><a href="#" title="{{$contact_actions.block.title}}" onclick="window.location.href='{{$contact_actions.block.url}}'; return false;">{{$contact_actions.block.label}}</a></li>
<li role="menuitem"><a href="#" title="{{$contact_actions.ignore.title}}" onclick="window.location.href='{{$contact_actions.ignore.url}}'; return false;">{{$contact_actions.ignore.label}}</a></li> <li role="menuitem"><a href="#" title="{{$contact_actions.ignore.title}}" onclick="window.location.href='{{$contact_actions.ignore.url}}'; return false;">{{$contact_actions.ignore.label}}</a></li>
{{if $contact_actions.delete.url}}<li role="menuitem"><a href="{{$contact_actions.delete.url}}" title="{{$contact_actions.delete.title}}" onclick="return confirmDelete();">{{$contact_actions.delete.label}}</a></li> {{/if}} {{if $contact_actions.revoke_follow.url}}<li role="menuitem"><a href="{{$contact_actions.revoke_follow.url}}" title="{{$contact_actions.revoke_follow.title}}">{{$contact_actions.revoke_follow.label}}</a></li>{{/if}}
</ul> </ul>
</div> </div>

View file

@ -38,20 +38,6 @@
return false; return false;
} }
}); });
// add javascript confirm dialog to "drop" links. Plain html url have "?confirm=1" to show confirmation form, we need to remove it
$(".drop").each(function() {
$(this).attr('href', $(this).attr('href').replace("confirm=1","") );
$(this).click(function(e){
if (confirm("{{$contact_drop_confirm}}")) {
return true;
} else {
e.preventDefault();
return false;
}
});
});
}); });
</script> </script>

View file

@ -2504,14 +2504,6 @@ ul li:hover .contact-wrapper .contact-action-link:hover {
#directory-search-wrapper { #directory-search-wrapper {
padding: 10px 0; padding: 10px 0;
} }
#contact-drop-confirm .contact-actions,
#contact-drop-confirm .contact-photo-overlay,
#contact-drop-confirm .contact-photo-menu {
display: none;
}
#contact-drop-confirm #confirm-form {
margin-top: 20px;
}
/* contact-edit */ /* contact-edit */
#contact-edit-actions { #contact-edit-actions {

View file

@ -1,9 +1,9 @@
<form action="{{$confirm_url}}" id="confirm-form" method="{{$method}}" class="generic-page-wrapper"> <form action="{{$confirm_url}}" id="confirm-form" method="{{$method}}" class="generic-page-wrapper">
<div id="confirm-message">{{$message}}</div> <div id="confirm-message">{{$l10n.message}}</div>
<div class="form-group pull-right settings-submit-wrapper"> <div class="form-group pull-right settings-submit-wrapper">
<button type="submit" name="{{$confirm_name}}" id="confirm-submit-button" class="btn btn-primary confirm-button" value="{{$confirm_value}}">{{$confirm}}</button> <button type="submit" name="{{$confirm_name}}" id="confirm-submit-button" class="btn btn-primary confirm-button" value="{{$confirm_value}}">{{$l10n.confirm}}</button>
<button type="submit" name="canceled" value="{{$cancel}} id="confirm-cancel-button" class="btn confirm-button" data-dismiss="modal">{{$cancel}}</button> <button type="submit" name="canceled" value="{{$l10n.cancel}}" id="confirm-cancel-button" class="btn confirm-button" data-dismiss="modal">{{$l10n.cancel}}</button>
</div> </div>
</form> </form>

View file

@ -1,5 +1,5 @@
<div id="contact-drop-confirm"> <div id="contact-drop-confirm">
<h2 class="heading">{{$header}}</h2> <h2 class="heading">{{$l10n.header}}</h2>
{{include file="contact_template.tpl" no_contacts_checkbox=True}} {{include file="contact_template.tpl" no_contacts_checkbox=True}}

View file

@ -27,7 +27,7 @@
{{/if}} {{/if}}
<li role="presentation"><a role="menuitem" href="{{$contact_actions.block.url}}" title="{{$contact_actions.block.title}}">{{$contact_actions.block.label}}</a></li> <li role="presentation"><a role="menuitem" href="{{$contact_actions.block.url}}" title="{{$contact_actions.block.title}}">{{$contact_actions.block.label}}</a></li>
<li role="presentation"><a role="menuitem" href="{{$contact_actions.ignore.url}}" title="{{$contact_actions.ignore.title}}">{{$contact_actions.ignore.label}}</a></li> <li role="presentation"><a role="menuitem" href="{{$contact_actions.ignore.url}}" title="{{$contact_actions.ignore.title}}">{{$contact_actions.ignore.label}}</a></li>
{{if $contact_actions.delete.url}}<li role="presentation"><button role="menuitem" type="button" class="btn-link" title="{{$contact_actions.delete.title}}" onclick="addToModal('{{$contact_actions.delete.url}}&confirm=1');">{{$contact_actions.delete.label}}</button></li>{{/if}} {{if $contact_actions.revoke_follow.url}}<li role="presentation"><button role="menuitem" type="button" class="btn-link" title="{{$contact_actions.revoke_follow.title}}" onclick="addToModal('{{$contact_actions.revoke_follow.url}}');">{{$contact_actions.revoke_follow.label}}</button></li>{{/if}}
</ul> </ul>
</li> </li>
</ul> </ul>

View file

@ -65,11 +65,6 @@
<i class="fa fa-user" aria-hidden="true"></i> <i class="fa fa-user" aria-hidden="true"></i>
</a> </a>
{{/if}} {{/if}}
{{if $contact.photo_menu.drop}}
<button type="button" class="contact-action-link btn-link" onclick="addToModal('{{$contact.photo_menu.drop.1}}'); return false;" data-toggle="tooltip" title="{{$contact.photo_menu.drop.0}}">
<i class="fa fa-user-times" aria-hidden="true"></i>
</button>
{{/if}}
{{if $contact.photo_menu.follow}} {{if $contact.photo_menu.follow}}
<a class="contact-action-link btn-link" href="{{$contact.photo_menu.follow.1}}" data-toggle="tooltip" title="{{$contact.photo_menu.follow.0}}"> <a class="contact-action-link btn-link" href="{{$contact.photo_menu.follow.1}}" data-toggle="tooltip" title="{{$contact.photo_menu.follow.0}}">
<i class="fa fa-user-plus" aria-hidden="true"></i> <i class="fa fa-user-plus" aria-hidden="true"></i>
@ -198,11 +193,6 @@ We use this part to filter the contacts with jquery.textcomplete *}}
<i class="fa fa-user" aria-hidden="true"></i> <i class="fa fa-user" aria-hidden="true"></i>
</a> </a>
{/if} {/if}
{if $photo_menu.drop}
<a class="contact-action-link btn-link" href="{$photo_menu.drop.1}" data-toggle="tooltip" title="{$photo_menu.drop.0}">
<i class="fa fa-user-times" aria-hidden="true"></i>
</a>
{/if}
{if $photo_menu.follow} {if $photo_menu.follow}
<a class="contact-action-link btn-link" href="{$photo_menu.follow.1}" data-toggle="tooltip" title="{$photo_menu.follow.0}"> <a class="contact-action-link btn-link" href="{$photo_menu.follow.1}" data-toggle="tooltip" title="{$photo_menu.follow.0}">
<i class="fa fa-user-plus" aria-hidden="true"></i> <i class="fa fa-user-plus" aria-hidden="true"></i>

View file

@ -1,8 +1,4 @@
<script type="text/javascript">
var dropContact = "{{$contact_drop_confirm}}";
</script>
{{$tabs nofilter}} {{$tabs nofilter}}
<div id="contacts" class="generic-page-wrapper"> <div id="contacts" class="generic-page-wrapper">

View file

@ -16,13 +16,13 @@
<a class="btn" id="contact-edit-actions-button">{{$contact_action_button}}</a> <a class="btn" id="contact-edit-actions-button">{{$contact_action_button}}</a>
<ul role="menu" aria-haspopup="true" id="contact-actions-menu" class="menu-popup"> <ul role="menu" aria-haspopup="true" id="contact-actions-menu" class="menu-popup">
{{if $lblsuggest}}<li role="menuitem"><a href="#" title="{{$contact_actions.suggest.title}}" onclick="window.location.href='{{$contact_actions.suggest.url}}'; return false;">{{$contact_actions.suggest.label}}</a></li>{{/if}} {{if $lblsuggest}}<li role="menuitem"><a href="#" title="{{$contact_actions.suggest.title}}" onclick="window.location.href='{{$contact_actions.suggest.url}}'; return false;">{{$contact_actions.suggest.label}}</a></li>{{/if}}
{{if $poll_enabled}}<li role="menuitem"><a href="#" title="{{$contact_actions.update.title}}" onclick="window.location.href='{{$contact_actions.update.url}}'; return false;">{{$contact_actions.update.label}}</a></li>{{/if}} {{if $poll_enabled}}<li role="menuitem"><a href="#" title="{{$contact_actions.update.title}}" onclick="window.location.href='{{$contact_actions.update.url}}'; return false;">{{$contact_actions.update.label}}</a></li>{{/if}}
{{if $contact_actions.updateprofile}}<li role="menuitem"><a href="{{$contact_actions.updateprofile.url}}" title="{{$contact_actions.updateprofile.title}}">{{$contact_actions.updateprofile.label}}</a></li>{{/if}} {{if $contact_actions.updateprofile}}<li role="menuitem"><a href="{{$contact_actions.updateprofile.url}}" title="{{$contact_actions.updateprofile.title}}">{{$contact_actions.updateprofile.label}}</a></li>{{/if}}
<li class="divider"></li> <li class="divider"></li>
<li role="menuitem"><a href="#" title="{{$contact_actions.block.title}}" onclick="window.location.href='{{$contact_actions.block.url}}'; return false;">{{$contact_actions.block.label}}</a></li> <li role="menuitem"><a href="#" title="{{$contact_actions.block.title}}" onclick="window.location.href='{{$contact_actions.block.url}}'; return false;">{{$contact_actions.block.label}}</a></li>
<li role="menuitem"><a href="#" title="{{$contact_actions.ignore.title}}" onclick="window.location.href='{{$contact_actions.ignore.url}}'; return false;">{{$contact_actions.ignore.label}}</a></li> <li role="menuitem"><a href="#" title="{{$contact_actions.ignore.title}}" onclick="window.location.href='{{$contact_actions.ignore.url}}'; return false;">{{$contact_actions.ignore.label}}</a></li>
{{if $contact_actions.delete.url}}<li role="menuitem"><a href="{{$contact_actions.delete.url}}" title="{{$contact_actions.delete.title}}" onclick="return confirmDelete();">{{$contact_actions.delete.label}}</a></li>{{/if}} {{if $contact_actions.revoke_follow.url}}<li role="menuitem"><a href="{{$contact_actions.revoke_follow.url}}" title="{{$contact_actions.revoke_follow.title}}">{{$contact_actions.revoke_follow.label}}</a></li>{{/if}}
</ul> </ul>
</div> </div>