diff --git a/database.sql b/database.sql index 7305e65d2..b0f3ca796 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2023.09-dev (Giant Rhubarb) --- DB_UPDATE_VERSION 1525 +-- DB_UPDATE_VERSION 1527 -- ------------------------------------------ @@ -101,6 +101,18 @@ CREATE TABLE IF NOT EXISTS `user` ( FOREIGN KEY (`parent-uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='The local users'; +-- +-- TABLE user-gserver +-- +CREATE TABLE IF NOT EXISTS `user-gserver` ( + `uid` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Owner User id', + `gsid` int unsigned NOT NULL DEFAULT 0 COMMENT 'Gserver id', + `ignored` boolean NOT NULL DEFAULT '0' COMMENT 'server accounts are ignored for the user', + PRIMARY KEY(`uid`,`gsid`), + FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE, + FOREIGN KEY (`gsid`) REFERENCES `gserver` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE +) DEFAULT COLLATE utf8mb4_general_ci COMMENT='User settings about remote servers'; + -- -- TABLE item-uri -- @@ -2044,6 +2056,7 @@ CREATE VIEW `post-user-view` AS SELECT `owner`.`blocked` AS `owner-blocked`, `owner`.`hidden` AS `owner-hidden`, `owner`.`updated` AS `owner-updated`, + `owner`.`gsid` AS `owner-gsid`, `owner`.`contact-type` AS `owner-contact-type`, `post-user`.`causer-id` AS `causer-id`, `causer`.`uri-id` AS `causer-uri-id`, @@ -2056,6 +2069,7 @@ CREATE VIEW `post-user-view` AS SELECT `causer`.`network` AS `causer-network`, `causer`.`blocked` AS `causer-blocked`, `causer`.`hidden` AS `causer-hidden`, + `causer`.`gsid` AS `causer-gsid`, `causer`.`contact-type` AS `causer-contact-type`, `post-delivery-data`.`postopts` AS `postopts`, `post-delivery-data`.`inform` AS `inform`, @@ -2189,6 +2203,7 @@ CREATE VIEW `post-thread-user-view` AS SELECT `contact`.`pending` AS `contact-pending`, `contact`.`rel` AS `contact-rel`, `contact`.`uid` AS `contact-uid`, + `contact`.`gsid` AS `contact-gsid`, `contact`.`contact-type` AS `contact-contact-type`, IF (`post-user`.`network` IN ('apub', 'dfrn', 'dspr', 'stat'), true, `contact`.`writable`) AS `writable`, `contact`.`self` AS `self`, @@ -2224,6 +2239,7 @@ CREATE VIEW `post-thread-user-view` AS SELECT `owner`.`blocked` AS `owner-blocked`, `owner`.`hidden` AS `owner-hidden`, `owner`.`updated` AS `owner-updated`, + `owner`.`gsid` AS `owner-gsid`, `owner`.`contact-type` AS `owner-contact-type`, `post-thread-user`.`causer-id` AS `causer-id`, `causer`.`uri-id` AS `causer-uri-id`, @@ -2236,6 +2252,7 @@ CREATE VIEW `post-thread-user-view` AS SELECT `causer`.`network` AS `causer-network`, `causer`.`blocked` AS `causer-blocked`, `causer`.`hidden` AS `causer-hidden`, + `causer`.`gsid` AS `causer-gsid`, `causer`.`contact-type` AS `causer-contact-type`, `post-delivery-data`.`postopts` AS `postopts`, `post-delivery-data`.`inform` AS `inform`, @@ -2391,6 +2408,7 @@ CREATE VIEW `post-view` AS SELECT `owner`.`hidden` AS `owner-hidden`, `owner`.`updated` AS `owner-updated`, `owner`.`contact-type` AS `owner-contact-type`, + `owner`.`gsid` AS `owner-gsid`, `post`.`causer-id` AS `causer-id`, `causer`.`uri-id` AS `causer-uri-id`, `causer`.`url` AS `causer-link`, @@ -2403,6 +2421,7 @@ CREATE VIEW `post-view` AS SELECT `causer`.`blocked` AS `causer-blocked`, `causer`.`hidden` AS `causer-hidden`, `causer`.`contact-type` AS `causer-contact-type`, + `causer`.`gsid` AS `causer-gsid`, `post-question`.`id` AS `question-id`, `post-question`.`multiple` AS `question-multiple`, `post-question`.`voters` AS `question-voters`, @@ -2533,6 +2552,7 @@ CREATE VIEW `post-thread-view` AS SELECT `owner`.`blocked` AS `owner-blocked`, `owner`.`hidden` AS `owner-hidden`, `owner`.`updated` AS `owner-updated`, + `owner`.`gsid` AS `owner-gsid`, `owner`.`contact-type` AS `owner-contact-type`, `post-thread`.`causer-id` AS `causer-id`, `causer`.`uri-id` AS `causer-uri-id`, @@ -2545,6 +2565,7 @@ CREATE VIEW `post-thread-view` AS SELECT `causer`.`network` AS `causer-network`, `causer`.`blocked` AS `causer-blocked`, `causer`.`hidden` AS `causer-hidden`, + `causer`.`gsid` AS `causer-gsid`, `causer`.`contact-type` AS `causer-contact-type`, `post-question`.`id` AS `question-id`, `post-question`.`multiple` AS `question-multiple`, @@ -2666,7 +2687,7 @@ CREATE VIEW `network-item-view` AS SELECT `post-user`.`contact-id` AS `contact-id`, `ownercontact`.`contact-type` AS `contact-type` FROM `post-user` - INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-thread-user`.`contact-id` STRAIGHT_JOIN `contact` AS `authorcontact` ON `authorcontact`.`id` = `post-thread-user`.`author-id` STRAIGHT_JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `post-thread-user`.`owner-id` @@ -2707,7 +2728,8 @@ CREATE VIEW `network-thread-view` AS SELECT AND (`post-thread-user`.`hidden` IS NULL OR NOT `post-thread-user`.`hidden`) AND NOT `authorcontact`.`blocked` AND NOT `ownercontact`.`blocked` AND (`author`.`blocked` IS NULL OR NOT `author`.`blocked`) - AND (`owner`.`blocked` IS NULL OR NOT `owner`.`blocked`); + AND (`owner`.`blocked` IS NULL OR NOT `owner`.`blocked`) + AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = `post-thread-user`.`uid` AND `gsid` IN (`authorcontact`.`gsid`, `ownercontact`.`gsid`) AND `ignored`); -- -- VIEW owner-view diff --git a/doc/database.md b/doc/database.md index b92859157..284870657 100644 --- a/doc/database.md +++ b/doc/database.md @@ -86,6 +86,7 @@ Database Tables | [tag](help/database/db_tag) | tags and mentions | | [user](help/database/db_user) | The local users | | [user-contact](help/database/db_user-contact) | User specific public contact data | +| [user-gserver](help/database/db_user-gserver) | User settings about remote servers | | [userd](help/database/db_userd) | Deleted usernames | | [verb](help/database/db_verb) | Activity Verbs | | [worker-ipc](help/database/db_worker-ipc) | Inter process communication between the frontend and the worker | diff --git a/doc/database/db_user-gserver.md b/doc/database/db_user-gserver.md new file mode 100644 index 000000000..b49a288f4 --- /dev/null +++ b/doc/database/db_user-gserver.md @@ -0,0 +1,30 @@ +Table user-gserver +=========== + +User settings about remote servers + +Fields +------ + +| Field | Description | Type | Null | Key | Default | Extra | +| ------- | ---------------------------------------- | ------------------ | ---- | --- | ------- | ----- | +| uid | Owner User id | mediumint unsigned | NO | | 0 | | +| gsid | Gserver id | int unsigned | NO | | 0 | | +| ignored | server accounts are ignored for the user | boolean | NO | | 0 | | + +Indexes +------------ + +| Name | Fields | +| ------- | --------- | +| PRIMARY | uid, gsid | + +Foreign Keys +------------ + +| Field | Target Table | Target Field | +|-------|--------------|--------------| +| uid | [user](help/database/db_user) | uid | +| gsid | [gserver](help/database/db_gserver) | id | + +Return to [database documentation](help/database) diff --git a/src/App/Page.php b/src/App/Page.php index 96bb59425..e369d482e 100644 --- a/src/App/Page.php +++ b/src/App/Page.php @@ -245,10 +245,12 @@ class Page implements ArrayAccess */ $this->page['htmlhead'] = Renderer::replaceMacros($tpl, [ '$l10n' => [ - 'delitem' => $l10n->t('Delete this item?'), - 'blockAuthor' => $l10n->t('Block this author? They won\'t be able to follow you nor see your public posts, and you won\'t be able to see their posts and their notifications.'), - 'ignoreAuthor' => $l10n->t('Ignore this author? You won\'t be able to see their posts and their notifications.'), - 'collapseAuthor' => $l10n->t('Collapse this author\'s posts?'), + 'delitem' => $l10n->t('Delete this item?'), + 'blockAuthor' => $l10n->t("Block this author? They won't be able to follow you nor see your public posts, and you won't be able to see their posts and their notifications."), + 'ignoreAuthor' => $l10n->t("Ignore this author? You won't be able to see their posts and their notifications."), + 'collapseAuthor' => $l10n->t("Collapse this author's posts?"), + 'ignoreServer' => $l10n->t("Ignore this author's server?"), + 'ignoreServerDesc' => $l10n->t("You won't see any content from this server including reshares in your Network page, the community pages and individual conversations."), 'likeError' => $l10n->t('Like not successful'), 'dislikeError' => $l10n->t('Dislike not successful'), diff --git a/src/Content/Conversation.php b/src/Content/Conversation.php index 710422ee7..151a2bfc7 100644 --- a/src/Content/Conversation.php +++ b/src/Content/Conversation.php @@ -45,6 +45,8 @@ use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Object\Post as PostObject; use Friendica\Object\Thread; use Friendica\Protocol\Activity; +use Friendica\User\Settings\Entity\UserGServer; +use Friendica\User\Settings\Repository; use Friendica\Util\Crypto; use Friendica\Util\DateTimeFormat; use Friendica\Util\Profiler; @@ -90,22 +92,25 @@ class Conversation private $mode; /** @var IHandleUserSessions */ private $session; + /** @var Repository\UserGServer */ + private $userGServer; - public function __construct(LoggerInterface $logger, Profiler $profiler, Activity $activity, L10n $l10n, Item $item, Arguments $args, BaseURL $baseURL, IManageConfigValues $config, IManagePersonalConfigValues $pConfig, App\Page $page, App\Mode $mode, App $app, IHandleUserSessions $session) + public function __construct(Repository\UserGServer $userGServer, LoggerInterface $logger, Profiler $profiler, Activity $activity, L10n $l10n, Item $item, Arguments $args, BaseURL $baseURL, IManageConfigValues $config, IManagePersonalConfigValues $pConfig, App\Page $page, App\Mode $mode, App $app, IHandleUserSessions $session) { - $this->activity = $activity; - $this->item = $item; - $this->config = $config; - $this->mode = $mode; - $this->baseURL = $baseURL; - $this->profiler = $profiler; - $this->logger = $logger; - $this->l10n = $l10n; - $this->args = $args; - $this->pConfig = $pConfig; - $this->page = $page; - $this->app = $app; - $this->session = $session; + $this->activity = $activity; + $this->item = $item; + $this->config = $config; + $this->mode = $mode; + $this->baseURL = $baseURL; + $this->profiler = $profiler; + $this->logger = $logger; + $this->l10n = $l10n; + $this->args = $args; + $this->pConfig = $pConfig; + $this->page = $page; + $this->app = $app; + $this->session = $session; + $this->userGServer = $userGServer; } /** @@ -459,8 +464,14 @@ class Conversation $live_update_div = ''; + $userGservers = $this->userGServer->listIgnoredByUser($this->session->getLocalUserId()); + + $ignoredGsids = array_map(function (UserGServer $userGServer) { + return $userGServer->gsid; + }, $userGservers->getArrayCopy()); + if ($mode === self::MODE_NETWORK) { - $items = $this->addChildren($items, false, $order, $uid, $mode); + $items = $this->addChildren($items, false, $order, $uid, $mode, $ignoredGsids); if (!$update) { /* * The special div is needed for liveUpdate to kick in for this page. @@ -486,7 +497,7 @@ class Conversation . "'; \r\n"; } } elseif ($mode === self::MODE_PROFILE) { - $items = $this->addChildren($items, false, $order, $uid, $mode); + $items = $this->addChildren($items, false, $order, $uid, $mode, $ignoredGsids); if (!$update) { $tab = !empty($_GET['tab']) ? trim($_GET['tab']) : 'posts'; @@ -511,7 +522,7 @@ class Conversation . "; var netargs = '?f='; \r\n"; } } elseif ($mode === self::MODE_DISPLAY) { - $items = $this->addChildren($items, false, $order, $uid, $mode); + $items = $this->addChildren($items, false, $order, $uid, $mode, $ignoredGsids); if (!$update) { $live_update_div = '
' . "\r\n" @@ -519,7 +530,7 @@ class Conversation . ""; } } elseif ($mode === self::MODE_COMMUNITY) { - $items = $this->addChildren($items, true, $order, $uid, $mode); + $items = $this->addChildren($items, true, $order, $uid, $mode, $ignoredGsids); if (!$update) { $live_update_div = '
' . "\r\n" @@ -530,7 +541,7 @@ class Conversation . "'; \r\n"; } } elseif ($mode === self::MODE_CONTACTS) { - $items = $this->addChildren($items, false, $order, $uid, $mode); + $items = $this->addChildren($items, false, $order, $uid, $mode, $ignoredGsids); if (!$update) { $live_update_div = '
' . "\r\n" @@ -812,13 +823,14 @@ class Conversation * * @param array $parents Parent items * @param bool $block_authors - * @param bool $order + * @param string $order Either "received" or "commented" * @param int $uid - * @param string $mode + * @param string $mode One of self::MODE_* + * @param array $ignoredGsids List of ids of servers ignored by the user * @return array items with parents and comments - * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ - private function addChildren(array $parents, bool $block_authors, string $order, int $uid, string $mode): array + private function addChildren(array $parents, bool $block_authors, string $order, int $uid, string $mode, array $ignoredGsids = []): array { $this->profiler->startRecording('rendering'); if (count($parents) > 1) { @@ -900,6 +912,13 @@ class Conversation continue; } + if (in_array($row['author-gsid'], $ignoredGsids) + || in_array($row['owner-gsid'], $ignoredGsids) + || in_array($row['causer-gsid'], $ignoredGsids) + ) { + continue; + } + if (($mode != self::MODE_CONTACTS) && !$row['origin']) { $row['featured'] = false; } @@ -1462,6 +1481,7 @@ class Conversation 'received' => $item['received'], 'created_date' => $item['created'], 'uriid' => $item['uri-id'], + 'author_gsid' => $item['author-gsid'], 'network' => $item['network'], 'network_name' => ContactSelector::networkToName($item['author-network'], $item['author-link'], $item['network'], $item['author-gsid']), 'network_icon' => ContactSelector::networkToIcon($item['network'], $item['author-link'], $item['author-gsid']), diff --git a/src/Content/Item.php b/src/Content/Item.php index c25e5296f..86493385f 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -50,6 +50,7 @@ use Friendica\Protocol\Activity; use Friendica\Util\ACLFormatter; use Friendica\Util\DateTimeFormat; use Friendica\Util\Emailer; +use Friendica\Util\Network; use Friendica\Util\ParseUrl; use Friendica\Util\Profiler; use Friendica\Util\Proxy; @@ -367,7 +368,7 @@ class Item { $this->profiler->startRecording('rendering'); $sub_link = $contact_url = $pm_url = $status_link = ''; - $photos_link = $posts_link = $block_link = $ignore_link = ''; + $photos_link = $posts_link = $block_link = $ignore_link = $collapse_link = $ignoreserver_link = ''; if ($this->userSession->getLocalUserId() && $this->userSession->getLocalUserId() == $item['uid'] && $item['gravity'] == ItemModel::GRAVITY_PARENT && !$item['self'] && !$item['mention']) { $sub_link = 'javascript:doFollowThread(' . $item['id'] . '); return false;'; @@ -407,6 +408,10 @@ class Item $collapse_link = $item['self'] ? '' : $contact_url . '/collapse?t=' . $formSecurityToken; } + if (!empty($item['author-gsid'])) { + $ignoreserver_link = Network::isLocalLink($contact_url) ? '' : 'settings/server/' . $item['author-gsid'] . '/ignore'; + } + if ($cid && !$item['self']) { $contact_url = 'contact/' . $cid; $posts_link = $contact_url . '/posts'; @@ -427,7 +432,8 @@ class Item $this->l10n->t('Send PM') => $pm_url, $this->l10n->t('Block') => $block_link, $this->l10n->t('Ignore') => $ignore_link, - $this->l10n->t('Collapse') => $collapse_link + $this->l10n->t('Collapse') => $collapse_link, + $this->l10n->t("Ignore %s's server", $item['author-name']) => $ignoreserver_link, ]; if (!empty($item['language'])) { diff --git a/src/DI.php b/src/DI.php index 34cf1c68d..2d6eb6ede 100644 --- a/src/DI.php +++ b/src/DI.php @@ -671,6 +671,15 @@ abstract class DI return self::$dice->create(Security\Authentication::class); } + // + // "User" namespace instances + // + + public static function userGServer(): User\Settings\Repository\UserGServer + { + return self::$dice->create(User\Settings\Repository\UserGServer::class); + } + // // "Util" namespace instances // diff --git a/src/Federation/Entity/GServer.php b/src/Federation/Entity/GServer.php new file mode 100644 index 000000000..0e331f480 --- /dev/null +++ b/src/Federation/Entity/GServer.php @@ -0,0 +1,151 @@ +. + * + */ + +namespace Friendica\Federation\Entity; + +use DateTimeImmutable; +use Psr\Http\Message\UriInterface; + +/** + * @property-read int $id + * @property-read string $url + * @property-read string $nurl + * @property-read string $version + * @property-read string $siteName + * @property-read string $info + * @property-read int $registerPolicy + * @property-read int $registeredUsers + * @property-read string $poco + * @property-read string $noscrape + * @property-read string $network + * @property-read string $platform + * @property-read int $relaySubscribe + * @property-read string $relayScope + * @property-read DateTimeImmutable $created + * @property-read ?DateTimeImmutable $lastPocoQuery + * @property-read ?DateTimeImmutable $lastContact + * @property-read ?DateTimeImmutable $lastFailure + * @property-read int $directoryType + * @property-read int $detectionMethod + * @property-read bool $failed + * @property-read DateTimeImmutable $nextContact + * @property-read int $protocol + * @property-read int $activeWeekUsers + * @property-read int $activeMonthUsers + * @property-read int $activeHalfyearUsers + * @property-read int $localPosts + * @property-read int $localComments + * @property-read bool $blocked + */ +class GServer extends \Friendica\BaseEntity +{ + /** @var ?int */ + protected $id; + /** @var UriInterface */ + protected $url; + /** @var UriInterface */ + protected $nurl; + /** @var string */ + protected $version; + /** @var string */ + protected $siteName; + /** @var string */ + protected $info; + /** @var int One of Module\Register::* constant values */ + protected $registerPolicy; + /** @var int */ + protected $registeredUsers; + /** @var ?UriInterface */ + protected $poco; + /** @var ?UriInterface */ + protected $noscrape; + /** @var string One of the Protocol::* constant values */ + protected $network; + /** @var string */ + protected $platform; + /** @var bool */ + protected $relaySubscribe; + /** @var string */ + protected $relayScope; + /** @var DateTimeImmutable */ + protected $created; + /** @var DateTimeImmutable */ + protected $lastPocoQuery; + /** @var DateTimeImmutable */ + protected $lastContact; + /** @var DateTimeImmutable */ + protected $lastFailure; + /** @var int One of Model\Gserver::DT_* constant values */ + protected $directoryType; + /** @var ?int One of Model\Gserver::DETECT_* constant values */ + protected $detectionMethod; + /** @var bool */ + protected $failed; + /** @var DateTimeImmutable */ + protected $nextContact; + /** @var ?int One of Model\Post\DeliveryData::* constant values */ + protected $protocol; + /** @var ?int */ + protected $activeWeekUsers; + /** @var ?int */ + protected $activeMonthUsers; + /** @var ?int */ + protected $activeHalfyearUsers; + /** @var ?int */ + protected $localPosts; + /** @var ?int */ + protected $localComments; + /** @var bool */ + protected $blocked; + + public function __construct(UriInterface $url, UriInterface $nurl, string $version, string $siteName, string $info, int $registerPolicy, int $registeredUsers, ?UriInterface $poco, ?UriInterface $noscrape, string $network, string $platform, bool $relaySubscribe, string $relayScope, DateTimeImmutable $created, ?DateTimeImmutable $lastPocoQuery, ?DateTimeImmutable $lastContact, ?DateTimeImmutable $lastFailure, int $directoryType, ?int $detectionMethod, bool $failed, ?DateTimeImmutable $nextContact, ?int $protocol, ?int $activeWeekUsers, ?int $activeMonthUsers, ?int $activeHalfyearUsers, ?int $localPosts, ?int $localComments, bool $blocked, ?int $id = null) + { + $this->url = $url; + $this->nurl = $nurl; + $this->version = $version; + $this->siteName = $siteName; + $this->info = $info; + $this->registerPolicy = $registerPolicy; + $this->registeredUsers = $registeredUsers; + $this->poco = $poco; + $this->noscrape = $noscrape; + $this->network = $network; + $this->platform = $platform; + $this->relaySubscribe = $relaySubscribe; + $this->relayScope = $relayScope; + $this->created = $created; + $this->lastPocoQuery = $lastPocoQuery; + $this->lastContact = $lastContact; + $this->lastFailure = $lastFailure; + $this->directoryType = $directoryType; + $this->detectionMethod = $detectionMethod; + $this->failed = $failed; + $this->nextContact = $nextContact; + $this->protocol = $protocol; + $this->activeWeekUsers = $activeWeekUsers; + $this->activeMonthUsers = $activeMonthUsers; + $this->activeHalfyearUsers = $activeHalfyearUsers; + $this->localPosts = $localPosts; + $this->localComments = $localComments; + $this->blocked = $blocked; + $this->id = $id; + } +} diff --git a/src/Federation/Factory/GServer.php b/src/Federation/Factory/GServer.php new file mode 100644 index 000000000..681cad7af --- /dev/null +++ b/src/Federation/Factory/GServer.php @@ -0,0 +1,68 @@ +. + * + */ + +namespace Friendica\Federation\Factory; + +use Friendica\Capabilities\ICanCreateFromTableRow; +use Friendica\Database\DBA; +use Friendica\Federation\Entity; +use GuzzleHttp\Psr7\Uri; + +class GServer extends \Friendica\BaseFactory implements ICanCreateFromTableRow +{ + /** + * @inheritDoc + */ + public function createFromTableRow(array $row): Entity\GServer + { + return new Entity\GServer( + new Uri($row['url']), + new Uri($row['nurl']), + $row['version'], + $row['site_name'], + $row['info'] ?? '', + $row['register_policy'], + $row['registered-users'], + $row['poco'] ? new Uri($row['poco']) : null, + $row['noscrape'] ? new Uri($row['noscrape']) : null, + $row['network'], + $row['platform'], + $row['relay-subscribe'], + $row['relay-scope'], + new \DateTimeImmutable($row['created']), + $row['last_poco_query'] !== DBA::NULL_DATETIME ? new \DateTimeImmutable($row['last_poco_query']) : null, + $row['last_contact'] !== DBA::NULL_DATETIME ? new \DateTimeImmutable($row['last_contact']) : null, + $row['last_failure'] !== DBA::NULL_DATETIME ? new \DateTimeImmutable($row['last_failure']) : null, + $row['directory-type'], + $row['detection-method'], + $row['failed'], + $row['next_contact'] !== DBA::NULL_DATETIME ? new \DateTimeImmutable($row['next_contact']) : null, + $row['protocol'], + $row['active-week-users'], + $row['active-month-users'], + $row['active-halfyear-users'], + $row['local-posts'], + $row['local-comments'], + $row['blocked'], + $row['id'], + ); + } +} diff --git a/src/Federation/Repository/GServer.php b/src/Federation/Repository/GServer.php new file mode 100644 index 000000000..47a9244f6 --- /dev/null +++ b/src/Federation/Repository/GServer.php @@ -0,0 +1,47 @@ +. + * + */ + +namespace Friendica\Federation\Repository; + +use Friendica\Database\Database; +use Friendica\Federation\Factory; +use Friendica\Federation\Entity; +use Psr\Log\LoggerInterface; + +class GServer extends \Friendica\BaseRepository +{ + protected static $table_name = 'gserver'; + + public function __construct(Database $database, LoggerInterface $logger, Factory\GServer $factory) + { + parent::__construct($database, $logger, $factory); + } + + /** + * @param int $gsid + * @return Entity\GServer + * @throws \Friendica\Network\HTTPException\NotFoundException + */ + public function selectOneById(int $gsid): Entity\GServer + { + return $this->_selectOne(['id' => $gsid]); + } +} diff --git a/src/Model/Item.php b/src/Model/Item.php index a2304056d..cf039da3a 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -96,8 +96,8 @@ class Item 'content-warning', 'location', 'coord', 'app', 'rendered-hash', 'rendered-html', 'object', 'quote-uri', 'quote-uri-id', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'mention', 'global', 'author-id', 'author-link', 'author-alias', 'author-name', 'author-avatar', 'author-network', 'author-updated', 'author-gsid', 'author-addr', 'author-uri-id', - 'owner-id', 'owner-link', 'owner-alias', 'owner-name', 'owner-avatar', 'owner-network', 'owner-contact-type', 'owner-updated', - 'causer-id', 'causer-link', 'causer-alias', 'causer-name', 'causer-avatar', 'causer-contact-type', 'causer-network', + 'owner-id', 'owner-link', 'owner-alias', 'owner-name', 'owner-avatar', 'owner-network', 'owner-contact-type', 'owner-updated', 'owner-gsid', + 'causer-id', 'causer-link', 'causer-alias', 'causer-name', 'causer-avatar', 'causer-contact-type', 'causer-network', 'causer-gsid', 'contact-id', 'contact-uid', 'contact-link', 'contact-name', 'contact-avatar', 'writable', 'self', 'cid', 'alias', 'event-created', 'event-edited', 'event-start', 'event-finish', diff --git a/src/Model/Post.php b/src/Model/Post.php index 770ab0831..6f855867f 100644 --- a/src/Model/Post.php +++ b/src/Model/Post.php @@ -453,12 +453,10 @@ class Post AND (NOT `causer-blocked` OR `causer-id` = ? OR `causer-id` IS NULL) AND NOT `contact-blocked` AND ((NOT `contact-readonly` AND NOT `contact-pending` AND (`contact-rel` IN (?, ?))) OR `self` OR `contact-uid` = ?) - AND NOT `" . $view . "`.`uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `uid` = ? AND `hidden`) - AND NOT `author-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND `blocked` AND `cid` = `author-id`) - AND NOT `owner-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND `blocked` AND `cid` = `owner-id`) - AND NOT `author-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND `ignored` AND `cid` = `author-id`) - AND NOT `owner-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND `ignored` AND `cid` = `owner-id`)", - 0, Contact::SHARING, Contact::FRIEND, 0, $uid, $uid, $uid, $uid, $uid]); + AND NOT EXISTS(SELECT `uri-id` FROM `post-user` WHERE `uid` = ? AND `uri-id` = " . DBA::quoteIdentifier($view) . ".`uri-id` AND `hidden`) + AND NOT EXISTS(SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND `cid` IN (`author-id`, `owner-id`) AND (`blocked` OR `ignored`)) + AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = ? AND `gsid` IN (`author-gsid`, `owner-gsid`, `causer-gsid`) AND `ignored`)", + 0, Contact::SHARING, Contact::FRIEND, 0, $uid, $uid, $uid]); $select_string = implode(', ', array_map([DBA::class, 'quoteIdentifier'], $selected)); diff --git a/src/Model/Post/UserNotification.php b/src/Model/Post/UserNotification.php index 012a49dbf..726e82d7e 100644 --- a/src/Model/Post/UserNotification.php +++ b/src/Model/Post/UserNotification.php @@ -133,14 +133,14 @@ class UserNotification public static function setNotification(int $uri_id, int $uid) { $fields = ['id', 'uri-id', 'parent-uri-id', 'uid', 'body', 'parent', 'gravity', 'vid', 'gravity', - 'contact-id', 'author-id', 'owner-id', 'causer-id', + 'contact-id', 'author-id', 'author-gsid', 'owner-id', 'owner-gsid', 'causer-id', 'causer-gsid', 'private', 'thr-parent', 'thr-parent-id', 'parent-uri-id', 'parent-uri', 'verb']; $item = Post::selectFirst($fields, ['uri-id' => $uri_id, 'uid' => $uid, 'origin' => false]); if (!DBA::isResult($item)) { return; } - $parent = Post::selectFirstPost(['author-id', 'owner-id', 'causer-id'], ['uri-id' => $item['parent-uri-id']]); + $parent = Post::selectFirstPost(['author-id', 'author-gsid', 'owner-id', 'owner-gsid', 'causer-id', 'causer-gsid',], ['uri-id' => $item['parent-uri-id']]); if (!DBA::isResult($parent)) { return; } @@ -195,6 +195,13 @@ class UserNotification } } + foreach (array_unique([$parent['author-gsid'], $parent['owner-gsid'], $parent['causer-gsid'], $item['author-gsid'], $item['owner-gsid'], $item['causer-gsid']]) as $gsid) { + if ($gsid && DI::userGServer()->isIgnoredByUser($uid, $gsid)) { + Logger::debug('Server is ignored by user', ['uid' => $uid, 'gsid' => $gsid, 'uri-id' => $item['uri-id']]); + return; + } + } + $user = User::getById($uid, ['account-type', 'account_removed', 'account_expired']); if (in_array($user['account-type'], [User::ACCOUNT_TYPE_COMMUNITY, User::ACCOUNT_TYPE_RELAY])) { return; diff --git a/src/Module/BaseSettings.php b/src/Module/BaseSettings.php index a1e88e9a1..4b26a0f26 100644 --- a/src/Module/BaseSettings.php +++ b/src/Module/BaseSettings.php @@ -151,6 +151,13 @@ class BaseSettings extends BaseModule 'accesskey' => 'b', ]; + $tabs[] = [ + 'label' => $this->t('Remote servers'), + 'url' => 'settings/server', + 'selected' => static::class == Settings\Server\Index::class ? 'active' : '', + 'accesskey' => 's', + ]; + $tabs[] = [ 'label' => $this->t('Export personal data'), 'url' => 'settings/userexport', diff --git a/src/Module/Contact/Profile.php b/src/Module/Contact/Profile.php index 090f7cd86..399198062 100644 --- a/src/Module/Contact/Profile.php +++ b/src/Module/Contact/Profile.php @@ -23,8 +23,7 @@ namespace Friendica\Module\Contact; use Friendica\App; use Friendica\BaseModule; -use Friendica\Contact\LocalRelationship\Entity; -use Friendica\Contact\LocalRelationship\Repository; +use Friendica\Contact\LocalRelationship; use Friendica\Content\ContactSelector; use Friendica\Content\Nav; use Friendica\Content\Text\BBCode; @@ -34,13 +33,16 @@ use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Core\Renderer; +use Friendica\Core\Session\Capability\IHandleUserSessions; +use Friendica\Database\Database; use Friendica\Database\DBA; -use Friendica\DI; -use Friendica\Model\Contact; use Friendica\Model\Circle; +use Friendica\Model\Contact; use Friendica\Module; use Friendica\Module\Response; +use Friendica\Navigation\SystemMessages; use Friendica\Network\HTTPException; +use Friendica\User\Settings; use Friendica\Util\DateTimeFormat; use Friendica\Util\Profiler; use Psr\Log\LoggerInterface; @@ -50,31 +52,37 @@ use Psr\Log\LoggerInterface; */ class Profile extends BaseModule { - /** - * @var Repository\LocalRelationship - */ + /** @var LocalRelationship\Repository\LocalRelationship */ private $localRelationship; - /** - * @var App\Page - */ + /** @var App\Page */ private $page; - /** - * @var IManageConfigValues - */ + /** @var IManageConfigValues */ private $config; + /** @var IHandleUserSessions */ + private $session; + /** @var SystemMessages */ + private $systemMessages; + /** @var Database */ + private $db; + /** @var Settings\Repository\UserGServer */ + private $userGServer; - public function __construct(L10n $l10n, Repository\LocalRelationship $localRelationship, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, App\Page $page, IManageConfigValues $config, array $server, array $parameters = []) + public function __construct(Settings\Repository\UserGServer $userGServer, Database $db, SystemMessages $systemMessages, IHandleUserSessions $session, L10n $l10n, LocalRelationship\Repository\LocalRelationship $localRelationship, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, App\Page $page, IManageConfigValues $config, array $server, array $parameters = []) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->localRelationship = $localRelationship; $this->page = $page; $this->config = $config; + $this->session = $session; + $this->systemMessages = $systemMessages; + $this->db = $db; + $this->userGServer = $userGServer; } protected function post(array $request = []) { - if (!DI::userSession()->getLocalUserId()) { + if (!$this->session->getLocalUserId()) { return; } @@ -82,8 +90,8 @@ class Profile extends BaseModule // Backward compatibility: The update still needs a user-specific contact ID // Change to user-contact table check by version 2022.03 - $cdata = Contact::getPublicAndUserContactID($contact_id, DI::userSession()->getLocalUserId()); - if (empty($cdata['user']) || !DBA::exists('contact', ['id' => $cdata['user'], 'deleted' => false])) { + $cdata = Contact::getPublicAndUserContactID($contact_id, $this->session->getLocalUserId()); + if (empty($cdata['user']) || !$this->db->exists('contact', ['id' => $cdata['user'], 'deleted' => false])) { return; } @@ -124,35 +132,35 @@ class Profile extends BaseModule $fields['info'] = $_POST['info']; } - if (!Contact::update($fields, ['id' => $cdata['user'], 'uid' => DI::userSession()->getLocalUserId()])) { - DI::sysmsg()->addNotice($this->t('Failed to update contact record.')); + if (!Contact::update($fields, ['id' => $cdata['user'], 'uid' => $this->session->getLocalUserId()])) { + $this->systemMessages->addNotice($this->t('Failed to update contact record.')); } } protected function content(array $request = []): string { - if (!DI::userSession()->getLocalUserId()) { + if (!$this->session->getLocalUserId()) { return Module\Security\Login::form($_SERVER['REQUEST_URI']); } // Backward compatibility: Ensure to use the public contact when the user contact is provided // Remove by version 2022.03 - $data = Contact::getPublicAndUserContactID(intval($this->parameters['id']), DI::userSession()->getLocalUserId()); + $data = Contact::getPublicAndUserContactID(intval($this->parameters['id']), $this->session->getLocalUserId()); if (empty($data)) { throw new HTTPException\NotFoundException($this->t('Contact not found.')); } $contact = Contact::getById($data['public']); - if (!DBA::isResult($contact)) { + if (!$this->db->isResult($contact)) { throw new HTTPException\NotFoundException($this->t('Contact not found.')); } // Don't display contacts that are about to be deleted - if (DBA::isResult($contact) && (!empty($contact['deleted']) || !empty($contact['network']) && $contact['network'] == Protocol::PHANTOM)) { + if ($this->db->isResult($contact) && (!empty($contact['deleted']) || !empty($contact['network']) && $contact['network'] == Protocol::PHANTOM)) { throw new HTTPException\NotFoundException($this->t('Contact not found.')); } - $localRelationship = $this->localRelationship->getForUserContact(DI::userSession()->getLocalUserId(), $contact['id']); + $localRelationship = $this->localRelationship->getForUserContact($this->session->getLocalUserId(), $contact['id']); if ($localRelationship->rel === Contact::SELF) { $this->baseUrl->redirect('profile/' . $contact['nick'] . '/profile'); @@ -167,55 +175,55 @@ class Profile extends BaseModule } if ($cmd === 'updateprofile') { - self::updateContactFromProbe($contact['id']); + $this->updateContactFromProbe($contact['id']); } if ($cmd === 'block') { if ($localRelationship->blocked) { // @TODO Backward compatibility, replace with $localRelationship->unblock() - Contact\User::setBlocked($contact['id'], DI::userSession()->getLocalUserId(), false); + Contact\User::setBlocked($contact['id'], $this->session->getLocalUserId(), false); $message = $this->t('Contact has been unblocked'); } else { // @TODO Backward compatibility, replace with $localRelationship->block() - Contact\User::setBlocked($contact['id'], DI::userSession()->getLocalUserId(), true); + Contact\User::setBlocked($contact['id'], $this->session->getLocalUserId(), true); $message = $this->t('Contact has been blocked'); } // @TODO: add $this->localRelationship->save($localRelationship); - DI::sysmsg()->addInfo($message); + $this->systemMessages->addInfo($message); } if ($cmd === 'ignore') { if ($localRelationship->ignored) { // @TODO Backward compatibility, replace with $localRelationship->unblock() - Contact\User::setIgnored($contact['id'], DI::userSession()->getLocalUserId(), false); + Contact\User::setIgnored($contact['id'], $this->session->getLocalUserId(), false); $message = $this->t('Contact has been unignored'); } else { // @TODO Backward compatibility, replace with $localRelationship->block() - Contact\User::setIgnored($contact['id'], DI::userSession()->getLocalUserId(), true); + Contact\User::setIgnored($contact['id'], $this->session->getLocalUserId(), true); $message = $this->t('Contact has been ignored'); } // @TODO: add $this->localRelationship->save($localRelationship); - DI::sysmsg()->addInfo($message); + $this->systemMessages->addInfo($message); } if ($cmd === 'collapse') { if ($localRelationship->collapsed) { // @TODO Backward compatibility, replace with $localRelationship->unblock() - Contact\User::setCollapsed($contact['id'], DI::userSession()->getLocalUserId(), false); + Contact\User::setCollapsed($contact['id'], $this->session->getLocalUserId(), false); $message = $this->t('Contact has been uncollapsed'); } else { // @TODO Backward compatibility, replace with $localRelationship->block() - Contact\User::setCollapsed($contact['id'], DI::userSession()->getLocalUserId(), true); + Contact\User::setCollapsed($contact['id'], $this->session->getLocalUserId(), true); $message = $this->t('Contact has been collapsed'); } // @TODO: add $this->localRelationship->save($localRelationship); - DI::sysmsg()->addInfo($message); + $this->systemMessages->addInfo($message); } $this->baseUrl->redirect('contact/' . $contact['id']); @@ -259,6 +267,11 @@ class Profile extends BaseModule $insecure = $this->t('Private communications are not available for this contact.'); + $serverIgnored = + $this->userGServer->isIgnoredByUser($this->session->getLocalUserId(), $contact['gsid']) ? + $this->t('This contact is on a server you ignored.') + : ''; + $last_update = (($contact['last-update'] <= DBA::NULL_DATETIME) ? $this->t('Never') : DateTimeFormat::local($contact['last-update'], 'D, j M Y, g:i A')); if ($contact['last-update'] > DBA::NULL_DATETIME) { @@ -363,6 +376,8 @@ class Profile extends BaseModule '$collapsed' => $localRelationship->collapsed ? $this->t('Currently collapsed') : '', '$archived' => ($contact['archive'] ? $this->t('Currently archived') : ''), '$insecure' => (in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA]) ? '' : $insecure), + '$serverIgnored' => $serverIgnored, + '$manageServers' => $this->t('Manage remote servers'), '$cinfo' => ['info', '', $localRelationship->info, ''], '$hidden' => ['hidden', $this->t('Hide this contact from others'), $localRelationship->hidden, $this->t('Replies/likes to your public posts may still be visible')], '$notify_new_posts' => ['notify_new_posts', $this->t('Notification for new posts'), ($localRelationship->notifyNewPosts), $this->t('Send a notification of every new post of this contact')], @@ -413,11 +428,11 @@ class Profile extends BaseModule * This includes actions like e.g. 'block', 'hide', 'delete' and others * * @param array $contact Public contact row - * @param Entity\LocalRelationship $localRelationship + * @param LocalRelationship\Entity\LocalRelationship $localRelationship * @return array with contact related actions * @throws HTTPException\InternalServerErrorException */ - private function getContactActions(array $contact, Entity\LocalRelationship $localRelationship): array + private function getContactActions(array $contact, LocalRelationship\Entity\LocalRelationship $localRelationship): array { $poll_enabled = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]); $contact_actions = []; @@ -518,10 +533,9 @@ class Profile extends BaseModule * @throws HTTPException\InternalServerErrorException * @throws \ImagickException */ - private static function updateContactFromProbe(int $contact_id) + private function updateContactFromProbe(int $contact_id) { - $contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => [0, DI::userSession()->getLocalUserId()], 'deleted' => false]); - if (!DBA::isResult($contact)) { + if (!$this->db->exists('contact', ['id' => $contact_id, 'uid' => [0, $this->session->getLocalUserId()], 'deleted' => false])) { return; } diff --git a/src/Module/Conversation/Community.php b/src/Module/Conversation/Community.php index 7525ba1c1..3c3bbb8a8 100644 --- a/src/Module/Conversation/Community.php +++ b/src/Module/Conversation/Community.php @@ -356,7 +356,7 @@ class Community extends BaseModule } } - $r = Post::selectThreadForUser(0, ['uri-id', 'commented', 'author-link'], $condition, $params); + $r = Post::selectThreadForUser(DI::userSession()->getLocalUserId() ?: 0, ['uri-id', 'commented', 'author-link'], $condition, $params); $items = Post::toArray($r); if (empty($items)) { diff --git a/src/Module/Item/Display.php b/src/Module/Item/Display.php index 21046628f..714598a8e 100644 --- a/src/Module/Item/Display.php +++ b/src/Module/Item/Display.php @@ -133,7 +133,9 @@ class Display extends BaseModule } if (empty($item)) { - throw new HTTPException\NotFoundException($this->t('The requested item doesn\'t exist or has been deleted.')); + $this->page['aside'] = ''; + $displayNotFound = new DisplayNotFound($this->l10n, $this->baseUrl, $this->args, $this->logger, $this->profiler, $this->response, $this->server, $this->parameters); + return $displayNotFound->content(); } if ($item['gravity'] != Item::GRAVITY_PARENT) { diff --git a/src/Module/Settings/Server/Action.php b/src/Module/Settings/Server/Action.php new file mode 100644 index 000000000..e06cbf26b --- /dev/null +++ b/src/Module/Settings/Server/Action.php @@ -0,0 +1,117 @@ +. + * + */ + +namespace Friendica\Module\Settings\Server; + +use Friendica\App; +use Friendica\Core\L10n; +use Friendica\Core\Renderer; +use Friendica\Core\Session\Capability\IHandleUserSessions; +use Friendica\Core\System; +use Friendica\Federation\Repository\GServer; +use Friendica\Module\Response; +use Friendica\Network\HTTPException\BadRequestException; +use Friendica\User\Settings\Repository\UserGServer; +use Friendica\Util\Profiler; +use Psr\Log\LoggerInterface; + +class Action extends \Friendica\BaseModule +{ + /** @var IHandleUserSessions */ + private $session; + /** @var UserGServer */ + private $repository; + /** @var GServer */ + private $gserverRepo; + + public function __construct(GServer $gserverRepo, UserGServer $repository, IHandleUserSessions $session, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) + { + parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + + $this->session = $session; + $this->repository = $repository; + $this->gserverRepo = $gserverRepo; + } + + public function content(array $request = []): string + { + $GServer = $this->gserverRepo->selectOneById($this->parameters['gsid']); + + switch ($this->parameters['action']) { + case 'ignore': + $action = $this->t('Do you want to ignore this server?'); + $desc = $this->t("You won't see any content from this server including reshares in your Network page, the community pages and individual conversations."); + break; + case 'unignore': + $action = $this->t('Do you want to unignore this server?'); + $desc = ''; + break; + default: + throw new BadRequestException('Unknown user server action ' . $this->parameters['action']); + } + + $tpl = Renderer::getMarkupTemplate('settings/server/action.tpl'); + return Renderer::replaceMacros($tpl, [ + '$l10n' => [ + 'title' => $this->t('Remote server settings'), + 'action' => $action, + 'siteName' => $this->t('Server Name'), + 'siteUrl' => $this->t('Server URL'), + 'desc' => $desc, + 'submit' => $this->t('Submit'), + ], + + '$action' => $this->args->getQueryString(), + + '$GServer' => $GServer, + + '$form_security_token' => self::getFormSecurityToken('settings-server'), + ]); + } + + public function post(array $request = []) + { + if (!empty($request['redirect_url'])) { + self::checkFormSecurityTokenRedirectOnError($this->args->getQueryString(), 'settings-server'); + } + + $userGServer = $this->repository->getOneByUserAndServer($this->session->getLocalUserId(), $this->parameters['gsid']); + + switch ($this->parameters['action']) { + case 'ignore': + $userGServer->ignore(); + break; + case 'unignore': + $userGServer->unignore(); + break; + default: + throw new BadRequestException('Unknown user server action ' . $this->parameters['action']); + } + + $this->repository->save($userGServer); + + if (!empty($request['redirect_url'])) { + $this->baseUrl->redirect($request['redirect_url']); + } + + System::exit(); + } +} diff --git a/src/Module/Settings/Server/Index.php b/src/Module/Settings/Server/Index.php new file mode 100644 index 000000000..f59e23a87 --- /dev/null +++ b/src/Module/Settings/Server/Index.php @@ -0,0 +1,126 @@ +. + * + */ + +namespace Friendica\Module\Settings\Server; + +use Friendica\App; +use Friendica\Content\Pager; +use Friendica\Core\L10n; +use Friendica\Core\Renderer; +use Friendica\Core\Session\Capability\IHandleUserSessions; +use Friendica\Module\BaseSettings; +use Friendica\Module\Response; +use Friendica\Navigation\SystemMessages; +use Friendica\Network\HTTPException\NotFoundException; +use Friendica\User\Settings\Entity\UserGServer; +use Friendica\User\Settings\Repository; +use Friendica\Util\Profiler; +use Psr\Log\LoggerInterface; + +class Index extends BaseSettings +{ + /** @var Repository\UserGServer */ + private $repository; + /** @var SystemMessages */ + private $systemMessages; + + public function __construct(SystemMessages $systemMessages, Repository\UserGServer $repository, IHandleUserSessions $session, App\Page $page, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) + { + parent::__construct($session, $page, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + + $this->repository = $repository; + $this->systemMessages = $systemMessages; + } + + protected function post(array $request = []) + { + self::checkFormSecurityTokenRedirectOnError($this->args->getQueryString(), 'settings-server'); + + foreach ($request['delete'] ?? [] as $gsid => $delete) { + if ($delete) { + unset($request['ignored'][$gsid]); + + try { + $userGServer = $this->repository->selectOneByUserAndServer($this->session->getLocalUserId(), $gsid, false); + $this->repository->delete($userGServer); + } catch (NotFoundException $e) { + // Nothing to delete + } + } + } + + foreach ($request['ignored'] ?? [] as $gsid => $ignored) { + $userGServer = $this->repository->getOneByUserAndServer($this->session->getLocalUserId(), $gsid, false); + if ($userGServer->ignored != $ignored) { + $userGServer->toggleIgnored(); + $this->repository->save($userGServer); + } + } + + $this->systemMessages->addInfo($this->t('Settings saved')); + + $this->baseUrl->redirect($this->args->getQueryString()); + } + + protected function content(array $request = []): string + { + parent::content(); + + $pager = new Pager($this->l10n, $this->args->getQueryString(), 30); + + $total = $this->repository->countByUser($this->session->getLocalUserId()); + + $servers = $this->repository->selectByUserWithPagination($this->session->getLocalUserId(), $pager); + + $ignoredCheckboxes = array_map(function (UserGServer $server) { + return ['ignored[' . $server->gsid . ']', '', $server->ignored]; + }, $servers->getArrayCopy()); + + $deleteCheckboxes = array_map(function (UserGServer $server) { + return ['delete[' . $server->gsid . ']']; + }, $servers->getArrayCopy()); + + $tpl = Renderer::getMarkupTemplate('settings/server/index.tpl'); + return Renderer::replaceMacros($tpl, [ + '$l10n' => [ + 'title' => $this->t('Remote server settings'), + 'desc' => $this->t('Here you can find all the remote servers you have taken individual moderation actions against. For a list of servers your node has blocked, please check out the Information page.'), + 'siteName' => $this->t('Server Name'), + 'ignored' => $this->t('Ignored'), + 'ignored_title' => $this->t("You won't see any content from this server including reshares in your Network page, the community pages and individual conversations."), + 'delete' => $this->t('Delete'), + 'delete_title' => $this->t('Delete all your settings for the remote server'), + 'submit' => $this->t('Save changes'), + ], + + '$count' => $total, + + '$servers' => $servers, + + '$form_security_token' => self::getFormSecurityToken('settings-server'), + + '$ignoredCheckboxes' => $ignoredCheckboxes, + '$deleteCheckboxes' => $deleteCheckboxes, + + '$paginate' => $pager->renderFull($total), + ]); + } +} diff --git a/src/Module/Special/DisplayNotFound.php b/src/Module/Special/DisplayNotFound.php index d66ececdd..293f40aa0 100644 --- a/src/Module/Special/DisplayNotFound.php +++ b/src/Module/Special/DisplayNotFound.php @@ -31,18 +31,21 @@ class DisplayNotFound extends \Friendica\BaseModule { protected function content(array $request = []): string { + $reasons = [ + $this->t("The top-level post isn't visible."), + $this->t('The top-level post was deleted.'), + $this->t('This node has blocked the top-level author or the author of the shared post.'), + $this->t('You have ignored or blocked the top-level author or the author of the shared post.'), + $this->t("You have ignored the top-level author's server or the shared post author's server."), + ]; + $tpl = Renderer::getMarkupTemplate('special/displaynotfound.tpl'); return Renderer::replaceMacros($tpl, [ '$l10n' => [ - 'title' => $this->t('Not Found'), - 'message' => $this->t("

Unfortunately, the requested conversation isn't available to you.

-

Possible reasons include:

-"), + 'title' => $this->t('Conversation Not Found'), + 'desc1' => $this->t("Unfortunately, the requested conversation isn't available to you."), + 'desc2' => $this->t('Possible reasons include:'), + 'reasons' => $reasons, ] ]); } diff --git a/src/Object/Post.php b/src/Object/Post.php index e7a178ef1..15a135079 100644 --- a/src/Object/Post.php +++ b/src/Object/Post.php @@ -38,6 +38,7 @@ use Friendica\Model\User; use Friendica\Protocol\Activity; use Friendica\Util\Crypto; use Friendica\Util\DateTimeFormat; +use Friendica\Util\Network; use Friendica\Util\Proxy; use Friendica\Util\Strings; use Friendica\Util\Temporal; @@ -248,11 +249,12 @@ class Post $pinned = DI::l10n()->t('Pinned item'); } - $drop = false; - $block = false; - $ignore = false; - $collapse = false; - $report = false; + $drop = false; + $block = false; + $ignore = false; + $collapse = false; + $report = false; + $ignoreServer = false; if (DI::userSession()->getLocalUserId()) { $drop = [ 'dropping' => $dropping, @@ -282,6 +284,11 @@ class Post 'label' => DI::l10n()->t('Report post'), 'href' => 'moderation/report/create?' . http_build_query(['cid' => $item['author-id'], 'uri-ids' => [$item['uri-id']]]), ]; + if (!Network::isLocalLink($item['plink'])) { + $ignoreServer = [ + 'label' => DI::l10n()->t("Ignore %s's server", $item['author-name']), + ]; + } } $filer = DI::userSession()->getLocalUserId() ? DI::l10n()->t('Save to folder') : false; @@ -557,6 +564,7 @@ class Post 'ignore_author' => $ignore, 'collapse' => $collapse, 'report' => $report, + 'ignore_server' => $ignoreServer, 'vote' => $buttons, 'like_html' => $responses['like']['output'], 'dislike_html' => $responses['dislike']['output'], @@ -571,6 +579,7 @@ class Post 'wait' => DI::l10n()->t('Please wait'), 'thread_level' => $thread_level, 'edited' => $edited, + 'author_gsid' => $item['author-gsid'], 'network' => $item['network'], 'network_name' => ContactSelector::networkToName($item['author-network'], $item['author-link'], $item['network'], $item['author-gsid']), 'network_icon' => ContactSelector::networkToIcon($item['network'], $item['author-link'], $item['author-gsid']), diff --git a/src/User/Settings/Collection/UserGServers.php b/src/User/Settings/Collection/UserGServers.php new file mode 100644 index 000000000..689b801cf --- /dev/null +++ b/src/User/Settings/Collection/UserGServers.php @@ -0,0 +1,30 @@ +. + * + */ + +namespace Friendica\User\Settings\Collection; + +class UserGServers extends \Friendica\BaseCollection +{ + public function current(): \Friendica\User\Settings\Entity\UserGServer + { + return parent::current(); + } +} diff --git a/src/User/Settings/Entity/UserGServer.php b/src/User/Settings/Entity/UserGServer.php new file mode 100644 index 000000000..e5afdc51e --- /dev/null +++ b/src/User/Settings/Entity/UserGServer.php @@ -0,0 +1,92 @@ +. + * + */ + +namespace Friendica\User\Settings\Entity; + +use Friendica\Federation\Entity\GServer; + +/** + * @property-read int $uid + * @property-read int $gsid + * @property-read bool $ignored + * @property-read ?GServer $gserver + */ +class UserGServer extends \Friendica\BaseEntity +{ + /** @var int User id */ + protected $uid; + /** @var int GServer id */ + protected $gsid; + /** @var bool Whether the user ignored this server */ + protected $ignored; + /** @var ?GServer */ + protected $gserver; + + public function __construct(int $uid, int $gsid, bool $ignored = false, ?GServer $gserver = null) + { + $this->uid = $uid; + $this->gsid = $gsid; + $this->ignored = $ignored; + $this->gserver = $gserver; + } + + /** + * Toggle the ignored property. + * + * Chainable. + * + * @return $this + */ + public function toggleIgnored(): UserGServer + { + $this->ignored = !$this->ignored; + + return $this; + } + + /** + * Set the ignored property. + * + * Chainable. + * + * @return $this + */ + public function ignore(): UserGServer + { + $this->ignored = true; + + return $this; + } + + /** + * Unset the ignored property. + * + * Chainable. + * + * @return $this + */ + public function unignore(): UserGServer + { + $this->ignored = false; + + return $this; + } +} diff --git a/src/User/Settings/Factory/UserGServer.php b/src/User/Settings/Factory/UserGServer.php new file mode 100644 index 000000000..61abe28cc --- /dev/null +++ b/src/User/Settings/Factory/UserGServer.php @@ -0,0 +1,60 @@ +. + * + */ + +namespace Friendica\User\Settings\Factory; + +use Friendica\Capabilities\ICanCreateFromTableRow; +use Friendica\Federation\Entity\GServer; +use Friendica\User\Settings\Entity; + +class UserGServer extends \Friendica\BaseFactory implements ICanCreateFromTableRow +{ + /** + * @param array $row `user-gserver` table row + * @param GServer|null $server Corresponding GServer entity + * @return Entity\UserGServer + */ + public function createFromTableRow(array $row, GServer $server = null): Entity\UserGServer + { + return new Entity\UserGServer( + $row['uid'], + $row['gsid'], + $row['ignored'], + $server, + ); + } + + /** + * @param int $uid + * @param int $gsid + * @param GServer|null $gserver Corresponding GServer entity + * @return Entity\UserGServer + */ + public function createFromUserAndServer(int $uid, int $gsid, GServer $gserver = null): Entity\UserGServer + { + return new Entity\UserGServer( + $uid, + $gsid, + false, + $gserver, + ); + } +} diff --git a/src/User/Settings/Repository/UserGServer.php b/src/User/Settings/Repository/UserGServer.php new file mode 100644 index 000000000..baf70095c --- /dev/null +++ b/src/User/Settings/Repository/UserGServer.php @@ -0,0 +1,156 @@ +. + * + */ + +namespace Friendica\User\Settings\Repository; + +use Exception; +use Friendica\BaseCollection; +use Friendica\BaseEntity; +use Friendica\Content\Pager; +use Friendica\Database\Database; +use Friendica\Federation\Repository\GServer; +use Friendica\Network\HTTPException\InternalServerErrorException; +use Friendica\Network\HTTPException\NotFoundException; +use Friendica\User\Settings\Collection; +use Friendica\User\Settings\Entity; +use Friendica\User\Settings\Factory; +use Psr\Log\LoggerInterface; + +class UserGServer extends \Friendica\BaseRepository +{ + protected static $table_name = 'user-gserver'; + + /** @var Factory\UserGServer */ + protected $factory; + /** @var GServer */ + protected $gserverRepository; + + public function __construct(GServer $gserverRepository, Database $database, LoggerInterface $logger, Factory\UserGServer $factory) + { + parent::__construct($database, $logger, $factory); + + $this->gserverRepository = $gserverRepository; + } + + /** + * Returns an existing UserGServer entity or create one on the fly + * + * @param int $uid + * @param int $gsid + * @param bool $hydrate Populate the related GServer entity + * @return Entity\UserGServer + */ + public function getOneByUserAndServer(int $uid, int $gsid, bool $hydrate = true): Entity\UserGServer + { + try { + return $this->selectOneByUserAndServer($uid, $gsid, $hydrate); + } catch (NotFoundException $e) { + return $this->factory->createFromUserAndServer($uid, $gsid, $hydrate ? $this->gserverRepository->selectOneById($gsid) : null); + } + } + + /** + * @param int $uid + * @param int $gsid + * @param bool $hydrate Populate the related GServer entity + * @return Entity\UserGServer + * @throws NotFoundException + */ + public function selectOneByUserAndServer(int $uid, int $gsid, bool $hydrate = true): Entity\UserGServer + { + return $this->_selectOne(['uid' => $uid, 'gsid' => $gsid], [], $hydrate); + } + + public function save(Entity\UserGServer $userGServer): Entity\UserGServer + { + $fields = [ + 'uid' => $userGServer->uid, + 'gsid' => $userGServer->gsid, + 'ignored' => $userGServer->ignored, + ]; + + $this->db->insert(static::$table_name, $fields, Database::INSERT_UPDATE); + + return $userGServer; + } + + public function selectByUserWithPagination(int $uid, Pager $pager): Collection\UserGServers + { + return $this->_select(['uid' => $uid], ['limit' => [$pager->getStart(), $pager->getItemsPerPage()]]); + } + + public function countByUser(int $uid): int + { + return $this->count(['uid' => $uid]); + } + + public function isIgnoredByUser(int $uid, int $gsid): bool + { + return $this->exists(['uid' => $uid, 'gsid' => $gsid, 'ignored' => 1]); + } + + /** + * @param Entity\UserGServer $userGServer + * @return bool + * @throws InternalServerErrorException in case the underlying storage cannot delete the record + */ + public function delete(Entity\UserGServer $userGServer): bool + { + try { + return $this->db->delete(self::$table_name, ['uid' => $userGServer->uid, 'gsid' => $userGServer->gsid]); + } catch (\Exception $exception) { + throw new InternalServerErrorException('Cannot delete the UserGServer', $exception); + } + } + + protected function _selectOne(array $condition, array $params = [], bool $hydrate = true): BaseEntity + { + $fields = $this->db->selectFirst(static::$table_name, [], $condition, $params); + if (!$this->db->isResult($fields)) { + throw new NotFoundException(); + } + + return $this->factory->createFromTableRow($fields, $hydrate ? $this->gserverRepository->selectOneById($fields['gsid']) : null); + } + + /** + * @param array $condition + * @param array $params + * @return Collection\UserGServers + * @throws Exception + */ + protected function _select(array $condition, array $params = [], bool $hydrate = true): BaseCollection + { + $rows = $this->db->selectToArray(static::$table_name, [], $condition, $params); + + $Entities = new Collection\UserGServers(); + foreach ($rows as $fields) { + $Entities[] = $this->factory->createFromTableRow($fields, $hydrate ? $this->gserverRepository->selectOneById($fields['gsid']) : null); + } + + return $Entities; + } + + public function listIgnoredByUser(int $uid): Collection\UserGServers + { + return $this->_select(['uid' => $uid, 'ignored' => 1], [], false); + } +} diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index c7575528e..dcda833aa 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -56,7 +56,7 @@ use Friendica\Database\DBA; // This file is required several times during the test in DbaDefinition which justifies this condition if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1525); + define('DB_UPDATE_VERSION', 1527); } return [ @@ -159,6 +159,17 @@ return [ "email" => ["email(64)"], ] ], + "user-gserver" => [ + "comment" => "User settings about remote servers", + "fields" => [ + "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], + "gsid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["gserver" => "id"], "comment" => "Gserver id"], + "ignored" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "server accounts are ignored for the user"], + ], + "indexes" => [ + "PRIMARY" => ["uid", "gsid"], + ], + ], "item-uri" => [ "comment" => "URI and GUID for items", "fields" => [ diff --git a/static/dbview.config.php b/static/dbview.config.php index e8641240c..5da17a42e 100644 --- a/static/dbview.config.php +++ b/static/dbview.config.php @@ -197,6 +197,7 @@ "owner-blocked" => ["owner", "blocked"], "owner-hidden" => ["owner", "hidden"], "owner-updated" => ["owner", "updated"], + "owner-gsid" => ["owner", "gsid"], "owner-contact-type" => ["owner", "contact-type"], "causer-id" => ["post-user", "causer-id"], "causer-uri-id" => ["causer", "uri-id"], @@ -209,6 +210,7 @@ "causer-network" => ["causer", "network"], "causer-blocked" => ["causer", "blocked"], "causer-hidden" => ["causer", "hidden"], + "causer-gsid" => ["causer", "gsid"], "causer-contact-type" => ["causer", "contact-type"], "postopts" => ["post-delivery-data", "postopts"], "inform" => ["post-delivery-data", "inform"], @@ -340,6 +342,7 @@ "contact-pending" => ["contact", "pending"], "contact-rel" => ["contact", "rel"], "contact-uid" => ["contact", "uid"], + "contact-gsid" => ["contact", "gsid"], "contact-contact-type" => ["contact", "contact-type"], "writable" => "IF (`post-user`.`network` IN ('apub', 'dfrn', 'dspr', 'stat'), true, `contact`.`writable`)", "self" => ["contact", "self"], @@ -375,6 +378,7 @@ "owner-blocked" => ["owner", "blocked"], "owner-hidden" => ["owner", "hidden"], "owner-updated" => ["owner", "updated"], + "owner-gsid" => ["owner", "gsid"], "owner-contact-type" => ["owner", "contact-type"], "causer-id" => ["post-thread-user", "causer-id"], "causer-uri-id" => ["causer", "uri-id"], @@ -387,6 +391,7 @@ "causer-network" => ["causer", "network"], "causer-blocked" => ["causer", "blocked"], "causer-hidden" => ["causer", "hidden"], + "causer-gsid" => ["causer", "gsid"], "causer-contact-type" => ["causer", "contact-type"], "postopts" => ["post-delivery-data", "postopts"], "inform" => ["post-delivery-data", "inform"], @@ -540,6 +545,7 @@ "owner-hidden" => ["owner", "hidden"], "owner-updated" => ["owner", "updated"], "owner-contact-type" => ["owner", "contact-type"], + "owner-gsid" => ["owner", "gsid"], "causer-id" => ["post", "causer-id"], "causer-uri-id" => ["causer", "uri-id"], "causer-link" => ["causer", "url"], @@ -552,6 +558,7 @@ "causer-blocked" => ["causer", "blocked"], "causer-hidden" => ["causer", "hidden"], "causer-contact-type" => ["causer", "contact-type"], + "causer-gsid" => ["causer", "gsid"], "question-id" => ["post-question", "id"], "question-multiple" => ["post-question", "multiple"], "question-voters" => ["post-question", "voters"], @@ -680,6 +687,7 @@ "owner-blocked" => ["owner", "blocked"], "owner-hidden" => ["owner", "hidden"], "owner-updated" => ["owner", "updated"], + "owner-gsid" => ["owner", "gsid"], "owner-contact-type" => ["owner", "contact-type"], "causer-id" => ["post-thread", "causer-id"], "causer-uri-id" => ["causer", "uri-id"], @@ -692,6 +700,7 @@ "causer-network" => ["causer", "network"], "causer-blocked" => ["causer", "blocked"], "causer-hidden" => ["causer", "hidden"], + "causer-gsid" => ["causer", "gsid"], "causer-contact-type" => ["causer", "contact-type"], "question-id" => ["post-question", "id"], "question-multiple" => ["post-question", "multiple"], @@ -804,7 +813,7 @@ "contact-type" => ["ownercontact", "contact-type"], ], "query" => "FROM `post-user` - INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-thread-user`.`contact-id` STRAIGHT_JOIN `contact` AS `authorcontact` ON `authorcontact`.`id` = `post-thread-user`.`author-id` STRAIGHT_JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `post-thread-user`.`owner-id` @@ -843,7 +852,8 @@ AND (`post-thread-user`.`hidden` IS NULL OR NOT `post-thread-user`.`hidden`) AND NOT `authorcontact`.`blocked` AND NOT `ownercontact`.`blocked` AND (`author`.`blocked` IS NULL OR NOT `author`.`blocked`) - AND (`owner`.`blocked` IS NULL OR NOT `owner`.`blocked`)" + AND (`owner`.`blocked` IS NULL OR NOT `owner`.`blocked`) + AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = `post-thread-user`.`uid` AND `gsid` IN (`authorcontact`.`gsid`, `ownercontact`.`gsid`) AND `ignored`)" ], "owner-view" => [ "fields" => [ diff --git a/static/routes.config.php b/static/routes.config.php index 71595e5a8..36ba2f249 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -639,6 +639,10 @@ return [ ], '/settings' => [ + '/server' => [ + '[/]' => [Module\Settings\Server\Index::class, [R::GET, R::POST]], + '/{gsid:\d+}/{action}' => [Module\Settings\Server\Action::class, [R::GET, R::POST]], + ], '[/]' => [Module\Settings\Account::class, [R::GET, R::POST]], '/account' => [ '[/]' => [Module\Settings\Account::class, [R::GET, R::POST]], diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 2d5faec2d..b9c94b038 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2023.09-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-11 01:11+0200\n" +"POT-Creation-Date: 2023-08-20 14:31-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -281,7 +281,7 @@ msgstr "" msgid "Your message:" msgstr "" -#: mod/message.php:199 mod/message.php:354 src/Content/Conversation.php:361 +#: mod/message.php:199 mod/message.php:354 src/Content/Conversation.php:366 #: src/Module/Post/Edit.php:131 msgid "Upload photo" msgstr "" @@ -292,9 +292,9 @@ msgid "Insert web link" msgstr "" #: mod/message.php:201 mod/message.php:357 mod/photos.php:1301 -#: src/Content/Conversation.php:392 src/Content/Conversation.php:1508 +#: src/Content/Conversation.php:397 src/Content/Conversation.php:1528 #: src/Module/Item/Compose.php:206 src/Module/Post/Edit.php:145 -#: src/Module/Profile/UnkMail.php:154 src/Object/Post.php:571 +#: src/Module/Profile/UnkMail.php:154 src/Object/Post.php:579 msgid "Please wait" msgstr "" @@ -302,7 +302,7 @@ msgstr "" #: mod/photos.php:824 mod/photos.php:1101 mod/photos.php:1142 #: mod/photos.php:1198 mod/photos.php:1278 #: src/Module/Calendar/Event/Form.php:250 src/Module/Contact/Advanced.php:132 -#: src/Module/Contact/Profile.php:339 +#: src/Module/Contact/Profile.php:352 #: src/Module/Debug/ActivityPubConversion.php:140 #: src/Module/Debug/Babel.php:313 src/Module/Debug/Localtime.php:64 #: src/Module/Debug/Probe.php:54 src/Module/Debug/WebFinger.php:51 @@ -315,7 +315,8 @@ msgstr "" #: src/Module/Moderation/Report/Create.php:211 #: src/Module/Moderation/Report/Create.php:263 #: src/Module/Profile/Profile.php:274 src/Module/Profile/UnkMail.php:155 -#: src/Module/Settings/Profile/Index.php:257 src/Object/Post.php:1087 +#: src/Module/Settings/Profile/Index.php:257 +#: src/Module/Settings/Server/Action.php:79 src/Object/Post.php:1096 #: view/theme/duepuntozero/config.php:85 view/theme/frio/config.php:171 #: view/theme/quattro/config.php:87 view/theme/vier/config.php:135 msgid "Submit" @@ -479,7 +480,7 @@ msgstr "" msgid "Do not show a status post for this upload" msgstr "" -#: mod/photos.php:736 mod/photos.php:1097 src/Content/Conversation.php:394 +#: mod/photos.php:736 mod/photos.php:1097 src/Content/Conversation.php:399 #: src/Module/Calendar/Event/Form.php:253 src/Module/Post/Edit.php:183 msgid "Permissions" msgstr "" @@ -492,7 +493,7 @@ msgstr "" msgid "Delete Album" msgstr "" -#: mod/photos.php:803 mod/photos.php:903 src/Content/Conversation.php:410 +#: mod/photos.php:803 mod/photos.php:903 src/Content/Conversation.php:415 #: src/Module/Contact/Follow.php:173 src/Module/Contact/Revoke.php:109 #: src/Module/Contact/Unfollow.php:126 #: src/Module/Media/Attachment/Browser.php:77 @@ -600,53 +601,54 @@ msgstr "" #: mod/photos.php:1139 mod/photos.php:1195 mod/photos.php:1275 #: src/Module/Contact.php:619 src/Module/Item/Compose.php:188 -#: src/Object/Post.php:1084 +#: src/Object/Post.php:1093 msgid "This is you" msgstr "" #: mod/photos.php:1141 mod/photos.php:1197 mod/photos.php:1277 -#: src/Object/Post.php:565 src/Object/Post.php:1086 +#: src/Object/Post.php:573 src/Object/Post.php:1095 msgid "Comment" msgstr "" #: mod/photos.php:1143 mod/photos.php:1199 mod/photos.php:1279 -#: src/Content/Conversation.php:407 src/Module/Calendar/Event/Form.php:248 +#: src/Content/Conversation.php:412 src/Module/Calendar/Event/Form.php:248 #: src/Module/Item/Compose.php:201 src/Module/Post/Edit.php:165 -#: src/Object/Post.php:1100 +#: src/Object/Post.php:1109 msgid "Preview" msgstr "" -#: mod/photos.php:1144 src/Content/Conversation.php:360 -#: src/Module/Post/Edit.php:130 src/Object/Post.php:1088 +#: mod/photos.php:1144 src/Content/Conversation.php:365 +#: src/Module/Post/Edit.php:130 src/Object/Post.php:1097 msgid "Loading..." msgstr "" -#: mod/photos.php:1236 src/Content/Conversation.php:1424 -#: src/Object/Post.php:260 +#: mod/photos.php:1236 src/Content/Conversation.php:1443 +#: src/Object/Post.php:262 msgid "Select" msgstr "" -#: mod/photos.php:1237 src/Content/Conversation.php:1425 +#: mod/photos.php:1237 src/Content/Conversation.php:1444 #: src/Module/Moderation/Users/Active.php:136 #: src/Module/Moderation/Users/Blocked.php:136 #: src/Module/Moderation/Users/Index.php:151 #: src/Module/Settings/Connectors.php:244 +#: src/Module/Settings/Server/Index.php:109 msgid "Delete" msgstr "" -#: mod/photos.php:1298 src/Object/Post.php:402 +#: mod/photos.php:1298 src/Object/Post.php:409 msgid "Like" msgstr "" -#: mod/photos.php:1299 src/Object/Post.php:402 +#: mod/photos.php:1299 src/Object/Post.php:409 msgid "I like this (toggle)" msgstr "" -#: mod/photos.php:1300 src/Object/Post.php:403 +#: mod/photos.php:1300 src/Object/Post.php:410 msgid "Dislike" msgstr "" -#: mod/photos.php:1302 src/Object/Post.php:403 +#: mod/photos.php:1302 src/Object/Post.php:410 msgid "I don't like this (toggle)" msgstr "" @@ -682,77 +684,88 @@ msgstr "" msgid "Collapse this author's posts?" msgstr "" -#: src/App/Page.php:253 -msgid "Like not successful" +#: src/App/Page.php:252 +msgid "Ignore this author's server?" msgstr "" -#: src/App/Page.php:254 -msgid "Dislike not successful" +#: src/App/Page.php:253 src/Module/Settings/Server/Action.php:61 +#: src/Module/Settings/Server/Index.php:108 +msgid "" +"You won't see any content from this server including reshares in your " +"Network page, the community pages and individual conversations." msgstr "" #: src/App/Page.php:255 -msgid "Sharing not successful" +msgid "Like not successful" msgstr "" #: src/App/Page.php:256 -msgid "Attendance unsuccessful" +msgid "Dislike not successful" msgstr "" #: src/App/Page.php:257 -msgid "Backend error" +msgid "Sharing not successful" msgstr "" #: src/App/Page.php:258 +msgid "Attendance unsuccessful" +msgstr "" + +#: src/App/Page.php:259 +msgid "Backend error" +msgstr "" + +#: src/App/Page.php:260 msgid "Network error" msgstr "" -#: src/App/Page.php:261 +#: src/App/Page.php:263 msgid "Drop files here to upload" msgstr "" -#: src/App/Page.php:262 +#: src/App/Page.php:264 msgid "Your browser does not support drag and drop file uploads." msgstr "" -#: src/App/Page.php:263 +#: src/App/Page.php:265 msgid "" "Please use the fallback form below to upload your files like in the olden " "days." msgstr "" -#: src/App/Page.php:264 +#: src/App/Page.php:266 msgid "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB." msgstr "" -#: src/App/Page.php:265 +#: src/App/Page.php:267 msgid "You can't upload files of this type." msgstr "" -#: src/App/Page.php:266 +#: src/App/Page.php:268 msgid "Server responded with {{statusCode}} code." msgstr "" -#: src/App/Page.php:267 +#: src/App/Page.php:269 msgid "Cancel upload" msgstr "" -#: src/App/Page.php:268 +#: src/App/Page.php:270 msgid "Upload canceled." msgstr "" -#: src/App/Page.php:269 +#: src/App/Page.php:271 msgid "Are you sure you want to cancel this upload?" msgstr "" -#: src/App/Page.php:270 +#: src/App/Page.php:272 msgid "Remove file" msgstr "" -#: src/App/Page.php:271 +#: src/App/Page.php:273 msgid "You can't upload any more files." msgstr "" -#: src/App/Page.php:349 +#: src/App/Page.php:351 msgid "toggle mobile" msgstr "" @@ -1127,65 +1140,65 @@ msgstr "" msgid "%s (via %s)" msgstr "" -#: src/Content/Conversation.php:219 +#: src/Content/Conversation.php:224 msgid "and" msgstr "" -#: src/Content/Conversation.php:222 +#: src/Content/Conversation.php:227 #, php-format msgid "and %d other people" msgstr "" -#: src/Content/Conversation.php:228 +#: src/Content/Conversation.php:233 #, php-format msgid "%2$s likes this." msgid_plural "%2$s like this." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:230 +#: src/Content/Conversation.php:235 #, php-format msgid "%2$s doesn't like this." msgid_plural "%2$s don't like this." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:232 +#: src/Content/Conversation.php:237 #, php-format msgid "%2$s attends." msgid_plural "%2$s attend." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:234 +#: src/Content/Conversation.php:239 #, php-format msgid "%2$s doesn't attend." msgid_plural "%2$s don't attend." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:236 +#: src/Content/Conversation.php:241 #, php-format msgid "%2$s attends maybe." msgid_plural "%2$s attend maybe." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:238 +#: src/Content/Conversation.php:243 #, php-format msgid "%2$s reshared this." msgid_plural "%2$s reshared this." msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:267 +#: src/Content/Conversation.php:272 #, php-format msgid " likes this" msgid_plural " like this" msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:270 +#: src/Content/Conversation.php:275 #, php-format msgid " doesn't like this" msgid_plural "" @@ -1193,304 +1206,304 @@ msgid_plural "" msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:273 +#: src/Content/Conversation.php:278 #, php-format msgid " attends" msgid_plural " attend" msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:276 +#: src/Content/Conversation.php:281 #, php-format msgid " doesn't attend" msgid_plural " don't attend" msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:279 +#: src/Content/Conversation.php:284 #, php-format msgid " attends maybe" msgid_plural " attend maybe" msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:282 +#: src/Content/Conversation.php:287 #, php-format msgid " reshared this" msgid_plural " reshared this" msgstr[0] "" msgstr[1] "" -#: src/Content/Conversation.php:329 +#: src/Content/Conversation.php:334 msgid "Visible to everybody" msgstr "" -#: src/Content/Conversation.php:330 src/Module/Item/Compose.php:200 -#: src/Object/Post.php:1099 +#: src/Content/Conversation.php:335 src/Module/Item/Compose.php:200 +#: src/Object/Post.php:1108 msgid "Please enter a image/video/audio/webpage URL:" msgstr "" -#: src/Content/Conversation.php:331 +#: src/Content/Conversation.php:336 msgid "Tag term:" msgstr "" -#: src/Content/Conversation.php:332 src/Module/Filer/SaveTag.php:73 +#: src/Content/Conversation.php:337 src/Module/Filer/SaveTag.php:73 msgid "Save to Folder:" msgstr "" -#: src/Content/Conversation.php:333 +#: src/Content/Conversation.php:338 msgid "Where are you right now?" msgstr "" -#: src/Content/Conversation.php:334 +#: src/Content/Conversation.php:339 msgid "Delete item(s)?" msgstr "" -#: src/Content/Conversation.php:346 src/Module/Item/Compose.php:175 +#: src/Content/Conversation.php:351 src/Module/Item/Compose.php:175 msgid "Created at" msgstr "" -#: src/Content/Conversation.php:356 +#: src/Content/Conversation.php:361 msgid "New Post" msgstr "" -#: src/Content/Conversation.php:359 +#: src/Content/Conversation.php:364 msgid "Share" msgstr "" -#: src/Content/Conversation.php:362 src/Module/Post/Edit.php:132 +#: src/Content/Conversation.php:367 src/Module/Post/Edit.php:132 msgid "upload photo" msgstr "" -#: src/Content/Conversation.php:363 src/Module/Post/Edit.php:133 +#: src/Content/Conversation.php:368 src/Module/Post/Edit.php:133 msgid "Attach file" msgstr "" -#: src/Content/Conversation.php:364 src/Module/Post/Edit.php:134 +#: src/Content/Conversation.php:369 src/Module/Post/Edit.php:134 msgid "attach file" msgstr "" -#: src/Content/Conversation.php:365 src/Module/Item/Compose.php:190 -#: src/Module/Post/Edit.php:171 src/Object/Post.php:1089 +#: src/Content/Conversation.php:370 src/Module/Item/Compose.php:190 +#: src/Module/Post/Edit.php:171 src/Object/Post.php:1098 msgid "Bold" msgstr "" -#: src/Content/Conversation.php:366 src/Module/Item/Compose.php:191 -#: src/Module/Post/Edit.php:172 src/Object/Post.php:1090 +#: src/Content/Conversation.php:371 src/Module/Item/Compose.php:191 +#: src/Module/Post/Edit.php:172 src/Object/Post.php:1099 msgid "Italic" msgstr "" -#: src/Content/Conversation.php:367 src/Module/Item/Compose.php:192 -#: src/Module/Post/Edit.php:173 src/Object/Post.php:1091 +#: src/Content/Conversation.php:372 src/Module/Item/Compose.php:192 +#: src/Module/Post/Edit.php:173 src/Object/Post.php:1100 msgid "Underline" msgstr "" -#: src/Content/Conversation.php:368 src/Module/Item/Compose.php:193 -#: src/Module/Post/Edit.php:174 src/Object/Post.php:1093 +#: src/Content/Conversation.php:373 src/Module/Item/Compose.php:193 +#: src/Module/Post/Edit.php:174 src/Object/Post.php:1102 msgid "Quote" msgstr "" -#: src/Content/Conversation.php:369 src/Module/Item/Compose.php:194 -#: src/Module/Post/Edit.php:175 src/Object/Post.php:1094 +#: src/Content/Conversation.php:374 src/Module/Item/Compose.php:194 +#: src/Module/Post/Edit.php:175 src/Object/Post.php:1103 msgid "Add emojis" msgstr "" -#: src/Content/Conversation.php:370 src/Module/Item/Compose.php:195 -#: src/Object/Post.php:1092 +#: src/Content/Conversation.php:375 src/Module/Item/Compose.php:195 +#: src/Object/Post.php:1101 msgid "Content Warning" msgstr "" -#: src/Content/Conversation.php:371 src/Module/Item/Compose.php:196 -#: src/Module/Post/Edit.php:176 src/Object/Post.php:1095 +#: src/Content/Conversation.php:376 src/Module/Item/Compose.php:196 +#: src/Module/Post/Edit.php:176 src/Object/Post.php:1104 msgid "Code" msgstr "" -#: src/Content/Conversation.php:372 src/Module/Item/Compose.php:197 -#: src/Object/Post.php:1096 +#: src/Content/Conversation.php:377 src/Module/Item/Compose.php:197 +#: src/Object/Post.php:1105 msgid "Image" msgstr "" -#: src/Content/Conversation.php:373 src/Module/Item/Compose.php:198 -#: src/Module/Post/Edit.php:177 src/Object/Post.php:1097 +#: src/Content/Conversation.php:378 src/Module/Item/Compose.php:198 +#: src/Module/Post/Edit.php:177 src/Object/Post.php:1106 msgid "Link" msgstr "" -#: src/Content/Conversation.php:374 src/Module/Item/Compose.php:199 -#: src/Module/Post/Edit.php:178 src/Object/Post.php:1098 +#: src/Content/Conversation.php:379 src/Module/Item/Compose.php:199 +#: src/Module/Post/Edit.php:178 src/Object/Post.php:1107 msgid "Link or Media" msgstr "" -#: src/Content/Conversation.php:375 +#: src/Content/Conversation.php:380 msgid "Video" msgstr "" -#: src/Content/Conversation.php:376 src/Module/Item/Compose.php:202 +#: src/Content/Conversation.php:381 src/Module/Item/Compose.php:202 #: src/Module/Post/Edit.php:141 msgid "Set your location" msgstr "" -#: src/Content/Conversation.php:377 src/Module/Post/Edit.php:142 +#: src/Content/Conversation.php:382 src/Module/Post/Edit.php:142 msgid "set location" msgstr "" -#: src/Content/Conversation.php:378 src/Module/Post/Edit.php:143 +#: src/Content/Conversation.php:383 src/Module/Post/Edit.php:143 msgid "Clear browser location" msgstr "" -#: src/Content/Conversation.php:379 src/Module/Post/Edit.php:144 +#: src/Content/Conversation.php:384 src/Module/Post/Edit.php:144 msgid "clear location" msgstr "" -#: src/Content/Conversation.php:381 src/Module/Item/Compose.php:207 +#: src/Content/Conversation.php:386 src/Module/Item/Compose.php:207 #: src/Module/Post/Edit.php:157 msgid "Set title" msgstr "" -#: src/Content/Conversation.php:383 src/Module/Item/Compose.php:208 +#: src/Content/Conversation.php:388 src/Module/Item/Compose.php:208 #: src/Module/Post/Edit.php:159 msgid "Categories (comma-separated list)" msgstr "" -#: src/Content/Conversation.php:388 src/Module/Item/Compose.php:224 +#: src/Content/Conversation.php:393 src/Module/Item/Compose.php:224 msgid "Scheduled at" msgstr "" -#: src/Content/Conversation.php:393 src/Module/Post/Edit.php:146 +#: src/Content/Conversation.php:398 src/Module/Post/Edit.php:146 msgid "Permission settings" msgstr "" -#: src/Content/Conversation.php:403 src/Module/Post/Edit.php:155 +#: src/Content/Conversation.php:408 src/Module/Post/Edit.php:155 msgid "Public post" msgstr "" -#: src/Content/Conversation.php:417 src/Content/Widget/VCard.php:120 +#: src/Content/Conversation.php:422 src/Content/Widget/VCard.php:120 #: src/Model/Profile.php:467 src/Module/Admin/Logs/View.php:92 #: src/Module/Post/Edit.php:181 msgid "Message" msgstr "" -#: src/Content/Conversation.php:418 src/Module/Post/Edit.php:182 +#: src/Content/Conversation.php:423 src/Module/Post/Edit.php:182 #: src/Module/Settings/TwoFactor/Trusted.php:140 msgid "Browser" msgstr "" -#: src/Content/Conversation.php:420 src/Module/Post/Edit.php:185 +#: src/Content/Conversation.php:425 src/Module/Post/Edit.php:185 msgid "Open Compose page" msgstr "" -#: src/Content/Conversation.php:569 +#: src/Content/Conversation.php:580 msgid "remove" msgstr "" -#: src/Content/Conversation.php:573 +#: src/Content/Conversation.php:584 msgid "Delete Selected Items" msgstr "" -#: src/Content/Conversation.php:728 src/Content/Conversation.php:731 -#: src/Content/Conversation.php:734 src/Content/Conversation.php:737 -#: src/Content/Conversation.php:740 +#: src/Content/Conversation.php:739 src/Content/Conversation.php:742 +#: src/Content/Conversation.php:745 src/Content/Conversation.php:748 +#: src/Content/Conversation.php:751 #, php-format msgid "You had been addressed (%s)." msgstr "" -#: src/Content/Conversation.php:743 +#: src/Content/Conversation.php:754 #, php-format msgid "You are following %s." msgstr "" -#: src/Content/Conversation.php:746 +#: src/Content/Conversation.php:757 msgid "You subscribed to one or more tags in this post." msgstr "" -#: src/Content/Conversation.php:765 +#: src/Content/Conversation.php:776 #, php-format msgid "%s reshared this." msgstr "" -#: src/Content/Conversation.php:767 +#: src/Content/Conversation.php:778 msgid "Reshared" msgstr "" -#: src/Content/Conversation.php:767 +#: src/Content/Conversation.php:778 #, php-format msgid "Reshared by %s <%s>" msgstr "" -#: src/Content/Conversation.php:770 +#: src/Content/Conversation.php:781 #, php-format msgid "%s is participating in this thread." msgstr "" -#: src/Content/Conversation.php:773 +#: src/Content/Conversation.php:784 msgid "Stored for general reasons" msgstr "" -#: src/Content/Conversation.php:776 +#: src/Content/Conversation.php:787 msgid "Global post" msgstr "" -#: src/Content/Conversation.php:779 +#: src/Content/Conversation.php:790 msgid "Sent via an relay server" msgstr "" -#: src/Content/Conversation.php:779 +#: src/Content/Conversation.php:790 #, php-format msgid "Sent via the relay server %s <%s>" msgstr "" -#: src/Content/Conversation.php:782 +#: src/Content/Conversation.php:793 msgid "Fetched" msgstr "" -#: src/Content/Conversation.php:782 +#: src/Content/Conversation.php:793 #, php-format msgid "Fetched because of %s <%s>" msgstr "" -#: src/Content/Conversation.php:785 +#: src/Content/Conversation.php:796 msgid "Stored because of a child post to complete this thread." msgstr "" -#: src/Content/Conversation.php:788 +#: src/Content/Conversation.php:799 msgid "Local delivery" msgstr "" -#: src/Content/Conversation.php:791 +#: src/Content/Conversation.php:802 msgid "Stored because of your activity (like, comment, star, ...)" msgstr "" -#: src/Content/Conversation.php:794 +#: src/Content/Conversation.php:805 msgid "Distributed" msgstr "" -#: src/Content/Conversation.php:797 +#: src/Content/Conversation.php:808 msgid "Pushed to us" msgstr "" -#: src/Content/Conversation.php:1452 src/Object/Post.php:248 +#: src/Content/Conversation.php:1471 src/Object/Post.php:249 msgid "Pinned item" msgstr "" -#: src/Content/Conversation.php:1468 src/Object/Post.php:515 -#: src/Object/Post.php:516 +#: src/Content/Conversation.php:1488 src/Object/Post.php:522 +#: src/Object/Post.php:523 #, php-format msgid "View %s's profile @ %s" msgstr "" -#: src/Content/Conversation.php:1481 src/Object/Post.php:503 +#: src/Content/Conversation.php:1501 src/Object/Post.php:510 msgid "Categories:" msgstr "" -#: src/Content/Conversation.php:1482 src/Object/Post.php:504 +#: src/Content/Conversation.php:1502 src/Object/Post.php:511 msgid "Filed under:" msgstr "" -#: src/Content/Conversation.php:1490 src/Object/Post.php:529 +#: src/Content/Conversation.php:1510 src/Object/Post.php:536 #, php-format msgid "%s from %s" msgstr "" -#: src/Content/Conversation.php:1506 +#: src/Content/Conversation.php:1526 msgid "View in context" msgstr "" @@ -1629,88 +1642,93 @@ msgstr "" msgid "Create new group" msgstr "" -#: src/Content/Item.php:329 src/Model/Item.php:2998 +#: src/Content/Item.php:330 src/Model/Item.php:2998 msgid "event" msgstr "" -#: src/Content/Item.php:332 src/Content/Item.php:342 +#: src/Content/Item.php:333 src/Content/Item.php:343 msgid "status" msgstr "" -#: src/Content/Item.php:338 src/Model/Item.php:3000 +#: src/Content/Item.php:339 src/Model/Item.php:3000 #: src/Module/Post/Tag/Add.php:123 msgid "photo" msgstr "" -#: src/Content/Item.php:352 src/Module/Post/Tag/Add.php:141 +#: src/Content/Item.php:353 src/Module/Post/Tag/Add.php:141 #, php-format msgid "%1$s tagged %2$s's %3$s with %4$s" msgstr "" -#: src/Content/Item.php:421 view/theme/frio/theme.php:262 +#: src/Content/Item.php:426 view/theme/frio/theme.php:262 msgid "Follow Thread" msgstr "" -#: src/Content/Item.php:422 src/Model/Contact.php:1210 +#: src/Content/Item.php:427 src/Model/Contact.php:1211 msgid "View Status" msgstr "" -#: src/Content/Item.php:423 src/Content/Item.php:443 src/Model/Contact.php:1159 -#: src/Model/Contact.php:1202 src/Model/Contact.php:1211 +#: src/Content/Item.php:428 src/Content/Item.php:449 src/Model/Contact.php:1160 +#: src/Model/Contact.php:1203 src/Model/Contact.php:1212 #: src/Module/Directory.php:157 src/Module/Settings/Profile/Index.php:259 msgid "View Profile" msgstr "" -#: src/Content/Item.php:424 src/Model/Contact.php:1212 +#: src/Content/Item.php:429 src/Model/Contact.php:1213 msgid "View Photos" msgstr "" -#: src/Content/Item.php:425 src/Model/Contact.php:1203 -#: src/Model/Contact.php:1213 +#: src/Content/Item.php:430 src/Model/Contact.php:1204 +#: src/Model/Contact.php:1214 msgid "Network Posts" msgstr "" -#: src/Content/Item.php:426 src/Model/Contact.php:1204 -#: src/Model/Contact.php:1214 +#: src/Content/Item.php:431 src/Model/Contact.php:1205 +#: src/Model/Contact.php:1215 msgid "View Contact" msgstr "" -#: src/Content/Item.php:427 src/Model/Contact.php:1215 +#: src/Content/Item.php:432 src/Model/Contact.php:1216 msgid "Send PM" msgstr "" -#: src/Content/Item.php:428 src/Module/Contact.php:468 -#: src/Module/Contact/Profile.php:477 +#: src/Content/Item.php:433 src/Module/Contact.php:468 +#: src/Module/Contact/Profile.php:492 #: src/Module/Moderation/Blocklist/Contact.php:116 #: src/Module/Moderation/Users/Active.php:137 #: src/Module/Moderation/Users/Index.php:152 msgid "Block" msgstr "" -#: src/Content/Item.php:429 src/Module/Contact.php:469 -#: src/Module/Contact/Profile.php:485 +#: src/Content/Item.php:434 src/Module/Contact.php:469 +#: src/Module/Contact/Profile.php:500 #: src/Module/Notifications/Introductions.php:134 #: src/Module/Notifications/Introductions.php:206 #: src/Module/Notifications/Notification.php:89 msgid "Ignore" msgstr "" -#: src/Content/Item.php:430 src/Module/Contact.php:470 -#: src/Module/Contact/Profile.php:493 +#: src/Content/Item.php:435 src/Module/Contact.php:470 +#: src/Module/Contact/Profile.php:508 msgid "Collapse" msgstr "" -#: src/Content/Item.php:434 src/Object/Post.php:484 +#: src/Content/Item.php:436 src/Object/Post.php:289 +#, php-format +msgid "Ignore %s's server" +msgstr "" + +#: src/Content/Item.php:440 src/Object/Post.php:491 msgid "Languages" msgstr "" -#: src/Content/Item.php:440 src/Content/Widget.php:80 -#: src/Model/Contact.php:1205 src/Model/Contact.php:1216 +#: src/Content/Item.php:446 src/Content/Widget.php:80 +#: src/Model/Contact.php:1206 src/Model/Contact.php:1217 #: src/Module/Contact/Follow.php:167 view/theme/vier/theme.php:195 msgid "Connect/Follow" msgstr "" -#: src/Content/Item.php:874 +#: src/Content/Item.php:880 msgid "Unable to fetch user." msgstr "" @@ -1758,7 +1776,7 @@ msgstr "" #: src/Content/Nav.php:228 src/Module/BaseProfile.php:49 #: src/Module/BaseSettings.php:100 src/Module/Contact.php:504 -#: src/Module/Contact/Profile.php:392 src/Module/Profile/Profile.php:268 +#: src/Module/Contact/Profile.php:407 src/Module/Profile/Profile.php:268 #: src/Module/Welcome.php:57 view/theme/frio/theme.php:230 msgid "Profile" msgstr "" @@ -1961,7 +1979,7 @@ msgid "Manage other pages" msgstr "" #: src/Content/Nav.php:325 src/Module/Admin/Addons/Details.php:114 -#: src/Module/Admin/Themes/Details.php:93 src/Module/BaseSettings.php:170 +#: src/Module/Admin/Themes/Details.php:93 src/Module/BaseSettings.php:177 #: src/Module/Welcome.php:52 view/theme/frio/theme.php:242 msgid "Settings" msgstr "" @@ -2077,7 +2095,7 @@ msgid "The end" msgstr "" #: src/Content/Text/HTML.php:859 src/Content/Widget/VCard.php:116 -#: src/Model/Profile.php:461 src/Module/Contact/Profile.php:437 +#: src/Model/Profile.php:461 src/Module/Contact/Profile.php:452 msgid "Follow" msgstr "" @@ -2212,7 +2230,7 @@ msgstr "" msgid "Organisations" msgstr "" -#: src/Content/Widget.php:536 src/Model/Contact.php:1680 +#: src/Content/Widget.php:536 src/Model/Contact.php:1681 msgid "News" msgstr "" @@ -2271,18 +2289,18 @@ msgid "More Trending Tags" msgstr "" #: src/Content/Widget/VCard.php:109 src/Model/Profile.php:376 -#: src/Module/Contact/Profile.php:381 src/Module/Profile/Profile.php:199 +#: src/Module/Contact/Profile.php:396 src/Module/Profile/Profile.php:199 msgid "XMPP:" msgstr "" #: src/Content/Widget/VCard.php:110 src/Model/Profile.php:377 -#: src/Module/Contact/Profile.php:383 src/Module/Profile/Profile.php:203 +#: src/Module/Contact/Profile.php:398 src/Module/Profile/Profile.php:203 msgid "Matrix:" msgstr "" #: src/Content/Widget/VCard.php:111 src/Model/Event.php:82 #: src/Model/Event.php:109 src/Model/Event.php:471 src/Model/Event.php:963 -#: src/Model/Profile.php:371 src/Module/Contact/Profile.php:379 +#: src/Model/Profile.php:371 src/Module/Contact/Profile.php:394 #: src/Module/Directory.php:147 src/Module/Notifications/Introductions.php:187 #: src/Module/Profile/Profile.php:221 msgid "Location:" @@ -2293,9 +2311,9 @@ msgstr "" msgid "Network:" msgstr "" -#: src/Content/Widget/VCard.php:118 src/Model/Contact.php:1206 -#: src/Model/Contact.php:1217 src/Model/Profile.php:463 -#: src/Module/Contact/Profile.php:429 +#: src/Content/Widget/VCard.php:118 src/Model/Contact.php:1207 +#: src/Model/Contact.php:1218 src/Model/Profile.php:463 +#: src/Module/Contact/Profile.php:444 msgid "Unfollow" msgstr "" @@ -2559,8 +2577,8 @@ msgstr "" #: src/Core/Installer.php:511 msgid "" -"The web installer needs to be able to create a file called \"local.config.php" -"\" in the \"config\" folder of your web server and it is unable to do so." +"The web installer needs to be able to create a file called \"local.config." +"php\" in the \"config\" folder of your web server and it is unable to do so." msgstr "" #: src/Core/Installer.php:512 @@ -3047,82 +3065,82 @@ msgstr "" msgid "Edit circles" msgstr "" -#: src/Model/Contact.php:1223 src/Module/Moderation/Users/Pending.php:102 +#: src/Model/Contact.php:1224 src/Module/Moderation/Users/Pending.php:102 #: src/Module/Notifications/Introductions.php:132 #: src/Module/Notifications/Introductions.php:204 msgid "Approve" msgstr "" -#: src/Model/Contact.php:1676 +#: src/Model/Contact.php:1677 msgid "Organisation" msgstr "" -#: src/Model/Contact.php:1684 +#: src/Model/Contact.php:1685 msgid "Group" msgstr "" -#: src/Model/Contact.php:2993 +#: src/Model/Contact.php:2988 msgid "Disallowed profile URL." msgstr "" -#: src/Model/Contact.php:2998 src/Module/Friendica.php:102 +#: src/Model/Contact.php:2993 src/Module/Friendica.php:101 msgid "Blocked domain" msgstr "" -#: src/Model/Contact.php:3003 +#: src/Model/Contact.php:2998 msgid "Connect URL missing." msgstr "" -#: src/Model/Contact.php:3012 +#: src/Model/Contact.php:3007 msgid "" "The contact could not be added. Please check the relevant network " "credentials in your Settings -> Social Networks page." msgstr "" -#: src/Model/Contact.php:3030 +#: src/Model/Contact.php:3025 #, php-format msgid "Expected network %s does not match actual network %s" msgstr "" -#: src/Model/Contact.php:3047 +#: src/Model/Contact.php:3042 msgid "The profile address specified does not provide adequate information." msgstr "" -#: src/Model/Contact.php:3049 +#: src/Model/Contact.php:3044 msgid "No compatible communication protocols or feeds were discovered." msgstr "" -#: src/Model/Contact.php:3052 +#: src/Model/Contact.php:3047 msgid "An author or name was not found." msgstr "" -#: src/Model/Contact.php:3055 +#: src/Model/Contact.php:3050 msgid "No browser URL could be matched to this address." msgstr "" -#: src/Model/Contact.php:3058 +#: src/Model/Contact.php:3053 msgid "" "Unable to match @-style Identity Address with a known protocol or email " "contact." msgstr "" -#: src/Model/Contact.php:3059 +#: src/Model/Contact.php:3054 msgid "Use mailto: in front of address to force email check." msgstr "" -#: src/Model/Contact.php:3065 +#: src/Model/Contact.php:3060 msgid "" "The profile address specified belongs to a network which has been disabled " "on this site." msgstr "" -#: src/Model/Contact.php:3070 +#: src/Model/Contact.php:3065 msgid "" "Limited profile. This person will be unable to receive direct/personal " "notifications from you." msgstr "" -#: src/Model/Contact.php:3136 +#: src/Model/Contact.php:3131 msgid "Unable to retrieve contact information." msgstr "" @@ -3327,7 +3345,7 @@ msgstr "" msgid "Homepage:" msgstr "" -#: src/Model/Profile.php:375 src/Module/Contact/Profile.php:385 +#: src/Model/Profile.php:375 src/Module/Contact/Profile.php:400 #: src/Module/Notifications/Introductions.php:189 msgid "About:" msgstr "" @@ -5039,7 +5057,7 @@ msgid "" "received." msgstr "" -#: src/Module/Admin/Site.php:513 src/Module/Contact/Profile.php:286 +#: src/Module/Admin/Site.php:513 src/Module/Contact/Profile.php:299 #: src/Module/Settings/TwoFactor/Index.php:125 msgid "Disabled" msgstr "" @@ -5185,9 +5203,9 @@ msgstr "" #: src/Module/Admin/Summary.php:98 msgid "" -"The last update failed. Please run \"php bin/console.php dbstructure update" -"\" from the command line and have a look at the errors that might appear. " -"(Some of the errors are possibly inside the logfile.)" +"The last update failed. Please run \"php bin/console.php dbstructure " +"update\" from the command line and have a look at the errors that might " +"appear. (Some of the errors are possibly inside the logfile.)" msgstr "" #: src/Module/Admin/Summary.php:102 @@ -5338,8 +5356,8 @@ msgstr "" #, php-format msgid "" "Show some informations regarding the needed information to operate the node " -"according e.g. to EU-GDPR." +"according e.g. to EU-GDPR." msgstr "" #: src/Module/Admin/Tos.php:81 @@ -5628,11 +5646,15 @@ msgstr "" msgid "Connected apps" msgstr "" -#: src/Module/BaseSettings.php:155 src/Module/Settings/UserExport.php:98 +#: src/Module/BaseSettings.php:155 +msgid "Remote servers" +msgstr "" + +#: src/Module/BaseSettings.php:162 src/Module/Settings/UserExport.php:98 msgid "Export personal data" msgstr "" -#: src/Module/BaseSettings.php:162 +#: src/Module/BaseSettings.php:169 msgid "Remove account" msgstr "" @@ -5778,8 +5800,8 @@ msgstr "" #: src/Module/Contact/Conversations.php:89 #: src/Module/Contact/Conversations.php:94 src/Module/Contact/Media.php:43 #: src/Module/Contact/Posts.php:78 src/Module/Contact/Posts.php:83 -#: src/Module/Contact/Posts.php:88 src/Module/Contact/Profile.php:142 -#: src/Module/Contact/Profile.php:147 src/Module/Contact/Profile.php:152 +#: src/Module/Contact/Posts.php:88 src/Module/Contact/Profile.php:150 +#: src/Module/Contact/Profile.php:155 src/Module/Contact/Profile.php:160 #: src/Module/Contact/Redir.php:94 src/Module/Contact/Redir.php:140 #: src/Module/FriendSuggest.php:71 src/Module/FriendSuggest.php:109 msgid "Contact not found." @@ -5888,7 +5910,7 @@ msgid "Only show blocked contacts" msgstr "" #: src/Module/Contact.php:369 src/Module/Contact.php:441 -#: src/Object/Post.php:362 +#: src/Module/Settings/Server/Index.php:107 src/Object/Post.php:369 msgid "Ignored" msgstr "" @@ -5937,18 +5959,18 @@ msgstr "" msgid "Update" msgstr "" -#: src/Module/Contact.php:468 src/Module/Contact/Profile.php:477 +#: src/Module/Contact.php:468 src/Module/Contact/Profile.php:492 #: src/Module/Moderation/Blocklist/Contact.php:117 #: src/Module/Moderation/Users/Blocked.php:138 #: src/Module/Moderation/Users/Index.php:154 msgid "Unblock" msgstr "" -#: src/Module/Contact.php:469 src/Module/Contact/Profile.php:485 +#: src/Module/Contact.php:469 src/Module/Contact/Profile.php:500 msgid "Unignore" msgstr "" -#: src/Module/Contact.php:470 src/Module/Contact/Profile.php:493 +#: src/Module/Contact.php:470 src/Module/Contact/Profile.php:508 msgid "Uncollapse" msgstr "" @@ -6000,7 +6022,7 @@ msgstr "" msgid "Pending incoming contact request" msgstr "" -#: src/Module/Contact.php:627 src/Module/Contact/Profile.php:346 +#: src/Module/Contact.php:627 src/Module/Contact/Profile.php:359 #, php-format msgid "Visit %s's profile [%s]" msgstr "" @@ -6135,7 +6157,7 @@ msgstr "" msgid "Your Identity Address:" msgstr "" -#: src/Module/Contact/Follow.php:170 src/Module/Contact/Profile.php:375 +#: src/Module/Contact/Follow.php:170 src/Module/Contact/Profile.php:390 #: src/Module/Contact/Unfollow.php:129 #: src/Module/Moderation/Blocklist/Contact.php:133 #: src/Module/Notifications/Introductions.php:129 @@ -6143,7 +6165,7 @@ msgstr "" msgid "Profile URL" msgstr "" -#: src/Module/Contact/Follow.php:171 src/Module/Contact/Profile.php:387 +#: src/Module/Contact/Follow.php:171 src/Module/Contact/Profile.php:402 #: src/Module/Notifications/Introductions.php:191 #: src/Module/Profile/Profile.php:234 msgid "Tags:" @@ -6182,249 +6204,257 @@ msgstr "" msgid "Profile Match" msgstr "" -#: src/Module/Contact/Profile.php:128 +#: src/Module/Contact/Profile.php:136 msgid "Failed to update contact record." msgstr "" -#: src/Module/Contact/Profile.php:178 +#: src/Module/Contact/Profile.php:186 msgid "Contact has been unblocked" msgstr "" -#: src/Module/Contact/Profile.php:182 +#: src/Module/Contact/Profile.php:190 msgid "Contact has been blocked" msgstr "" -#: src/Module/Contact/Profile.php:194 +#: src/Module/Contact/Profile.php:202 msgid "Contact has been unignored" msgstr "" -#: src/Module/Contact/Profile.php:198 +#: src/Module/Contact/Profile.php:206 msgid "Contact has been ignored" msgstr "" -#: src/Module/Contact/Profile.php:210 +#: src/Module/Contact/Profile.php:218 msgid "Contact has been uncollapsed" msgstr "" -#: src/Module/Contact/Profile.php:214 +#: src/Module/Contact/Profile.php:222 msgid "Contact has been collapsed" msgstr "" -#: src/Module/Contact/Profile.php:242 +#: src/Module/Contact/Profile.php:250 #, php-format msgid "You are mutual friends with %s" msgstr "" -#: src/Module/Contact/Profile.php:243 +#: src/Module/Contact/Profile.php:251 #, php-format msgid "You are sharing with %s" msgstr "" -#: src/Module/Contact/Profile.php:244 +#: src/Module/Contact/Profile.php:252 #, php-format msgid "%s is sharing with you" msgstr "" -#: src/Module/Contact/Profile.php:260 +#: src/Module/Contact/Profile.php:268 msgid "Private communications are not available for this contact." msgstr "" -#: src/Module/Contact/Profile.php:262 +#: src/Module/Contact/Profile.php:272 +msgid "This contact is on a server you ignored." +msgstr "" + +#: src/Module/Contact/Profile.php:275 msgid "Never" msgstr "" -#: src/Module/Contact/Profile.php:265 +#: src/Module/Contact/Profile.php:278 msgid "(Update was not successful)" msgstr "" -#: src/Module/Contact/Profile.php:265 +#: src/Module/Contact/Profile.php:278 msgid "(Update was successful)" msgstr "" -#: src/Module/Contact/Profile.php:267 src/Module/Contact/Profile.php:448 +#: src/Module/Contact/Profile.php:280 src/Module/Contact/Profile.php:463 msgid "Suggest friends" msgstr "" -#: src/Module/Contact/Profile.php:271 +#: src/Module/Contact/Profile.php:284 #, php-format msgid "Network type: %s" msgstr "" -#: src/Module/Contact/Profile.php:276 +#: src/Module/Contact/Profile.php:289 msgid "Communications lost with this contact!" msgstr "" -#: src/Module/Contact/Profile.php:282 +#: src/Module/Contact/Profile.php:295 msgid "Fetch further information for feeds" msgstr "" -#: src/Module/Contact/Profile.php:284 +#: src/Module/Contact/Profile.php:297 msgid "" "Fetch information like preview pictures, title and teaser from the feed " "item. You can activate this if the feed doesn't contain much text. Keywords " "are taken from the meta header in the feed item and are posted as hash tags." msgstr "" -#: src/Module/Contact/Profile.php:287 +#: src/Module/Contact/Profile.php:300 msgid "Fetch information" msgstr "" -#: src/Module/Contact/Profile.php:288 +#: src/Module/Contact/Profile.php:301 msgid "Fetch keywords" msgstr "" -#: src/Module/Contact/Profile.php:289 +#: src/Module/Contact/Profile.php:302 msgid "Fetch information and keywords" msgstr "" -#: src/Module/Contact/Profile.php:299 src/Module/Contact/Profile.php:304 -#: src/Module/Contact/Profile.php:309 src/Module/Contact/Profile.php:315 +#: src/Module/Contact/Profile.php:312 src/Module/Contact/Profile.php:317 +#: src/Module/Contact/Profile.php:322 src/Module/Contact/Profile.php:328 msgid "No mirroring" msgstr "" -#: src/Module/Contact/Profile.php:300 src/Module/Contact/Profile.php:310 -#: src/Module/Contact/Profile.php:316 +#: src/Module/Contact/Profile.php:313 src/Module/Contact/Profile.php:323 +#: src/Module/Contact/Profile.php:329 msgid "Mirror as my own posting" msgstr "" -#: src/Module/Contact/Profile.php:305 src/Module/Contact/Profile.php:311 +#: src/Module/Contact/Profile.php:318 src/Module/Contact/Profile.php:324 msgid "Native reshare" msgstr "" -#: src/Module/Contact/Profile.php:328 +#: src/Module/Contact/Profile.php:341 msgid "Contact Information / Notes" msgstr "" -#: src/Module/Contact/Profile.php:329 +#: src/Module/Contact/Profile.php:342 msgid "Contact Settings" msgstr "" -#: src/Module/Contact/Profile.php:337 +#: src/Module/Contact/Profile.php:350 msgid "Contact" msgstr "" -#: src/Module/Contact/Profile.php:341 +#: src/Module/Contact/Profile.php:354 msgid "Their personal note" msgstr "" -#: src/Module/Contact/Profile.php:343 +#: src/Module/Contact/Profile.php:356 msgid "Edit contact notes" msgstr "" -#: src/Module/Contact/Profile.php:347 +#: src/Module/Contact/Profile.php:360 msgid "Block/Unblock contact" msgstr "" -#: src/Module/Contact/Profile.php:348 +#: src/Module/Contact/Profile.php:361 #: src/Module/Moderation/Report/Create.php:293 msgid "Ignore contact" msgstr "" -#: src/Module/Contact/Profile.php:349 +#: src/Module/Contact/Profile.php:362 msgid "View conversations" msgstr "" -#: src/Module/Contact/Profile.php:354 +#: src/Module/Contact/Profile.php:367 msgid "Last update:" msgstr "" -#: src/Module/Contact/Profile.php:356 +#: src/Module/Contact/Profile.php:369 msgid "Update public posts" msgstr "" -#: src/Module/Contact/Profile.php:358 src/Module/Contact/Profile.php:458 +#: src/Module/Contact/Profile.php:371 src/Module/Contact/Profile.php:473 msgid "Update now" msgstr "" -#: src/Module/Contact/Profile.php:360 +#: src/Module/Contact/Profile.php:373 msgid "Awaiting connection acknowledge" msgstr "" -#: src/Module/Contact/Profile.php:361 +#: src/Module/Contact/Profile.php:374 msgid "Currently blocked" msgstr "" -#: src/Module/Contact/Profile.php:362 +#: src/Module/Contact/Profile.php:375 msgid "Currently ignored" msgstr "" -#: src/Module/Contact/Profile.php:363 +#: src/Module/Contact/Profile.php:376 msgid "Currently collapsed" msgstr "" -#: src/Module/Contact/Profile.php:364 +#: src/Module/Contact/Profile.php:377 msgid "Currently archived" msgstr "" -#: src/Module/Contact/Profile.php:367 +#: src/Module/Contact/Profile.php:380 +msgid "Manage remote servers" +msgstr "" + +#: src/Module/Contact/Profile.php:382 #: src/Module/Notifications/Introductions.php:192 msgid "Hide this contact from others" msgstr "" -#: src/Module/Contact/Profile.php:367 +#: src/Module/Contact/Profile.php:382 msgid "" "Replies/likes to your public posts may still be visible" msgstr "" -#: src/Module/Contact/Profile.php:368 +#: src/Module/Contact/Profile.php:383 msgid "Notification for new posts" msgstr "" -#: src/Module/Contact/Profile.php:368 +#: src/Module/Contact/Profile.php:383 msgid "Send a notification of every new post of this contact" msgstr "" -#: src/Module/Contact/Profile.php:370 +#: src/Module/Contact/Profile.php:385 msgid "Keyword Deny List" msgstr "" -#: src/Module/Contact/Profile.php:370 +#: src/Module/Contact/Profile.php:385 msgid "" "Comma separated list of keywords that should not be converted to hashtags, " "when \"Fetch information and keywords\" is selected" msgstr "" -#: src/Module/Contact/Profile.php:388 +#: src/Module/Contact/Profile.php:403 #: src/Module/Settings/TwoFactor/Index.php:139 msgid "Actions" msgstr "" -#: src/Module/Contact/Profile.php:390 +#: src/Module/Contact/Profile.php:405 #: src/Module/Settings/TwoFactor/Index.php:119 view/theme/frio/theme.php:229 msgid "Status" msgstr "" -#: src/Module/Contact/Profile.php:396 +#: src/Module/Contact/Profile.php:411 msgid "Mirror postings from this contact" msgstr "" -#: src/Module/Contact/Profile.php:398 +#: src/Module/Contact/Profile.php:413 msgid "" "Mark this contact as remote_self, this will cause friendica to repost new " "entries from this contact." msgstr "" -#: src/Module/Contact/Profile.php:468 +#: src/Module/Contact/Profile.php:483 msgid "Refetch contact data" msgstr "" -#: src/Module/Contact/Profile.php:479 +#: src/Module/Contact/Profile.php:494 msgid "Toggle Blocked status" msgstr "" -#: src/Module/Contact/Profile.php:487 +#: src/Module/Contact/Profile.php:502 msgid "Toggle Ignored status" msgstr "" -#: src/Module/Contact/Profile.php:495 +#: src/Module/Contact/Profile.php:510 msgid "Toggle Collapsed status" msgstr "" -#: src/Module/Contact/Profile.php:502 src/Module/Contact/Revoke.php:106 +#: src/Module/Contact/Profile.php:517 src/Module/Contact/Revoke.php:106 msgid "Revoke Follow" msgstr "" -#: src/Module/Contact/Profile.php:504 +#: src/Module/Contact/Profile.php:519 msgid "Revoke the follow from this contact" msgstr "" @@ -6572,7 +6602,7 @@ msgstr "" msgid "Posts that mention or involve you" msgstr "" -#: src/Module/Conversation/Network.php:289 src/Object/Post.php:374 +#: src/Module/Conversation/Network.php:289 src/Object/Post.php:381 msgid "Starred" msgstr "" @@ -6938,42 +6968,42 @@ msgstr "" msgid "Read about the Terms of Service of this node." msgstr "" -#: src/Module/Friendica.php:100 +#: src/Module/Friendica.php:99 msgid "On this server the following remote servers are blocked." msgstr "" -#: src/Module/Friendica.php:103 +#: src/Module/Friendica.php:102 #: src/Module/Moderation/Blocklist/Server/Index.php:87 #: src/Module/Moderation/Blocklist/Server/Index.php:111 msgid "Reason for the block" msgstr "" -#: src/Module/Friendica.php:105 +#: src/Module/Friendica.php:104 msgid "Download this list in CSV format" msgstr "" -#: src/Module/Friendica.php:119 +#: src/Module/Friendica.php:118 #, php-format msgid "" "This is Friendica, version %s that is running at the web location %s. The " "database version is %s, the post update version is %s." msgstr "" -#: src/Module/Friendica.php:124 +#: src/Module/Friendica.php:123 msgid "" "Please visit Friendi.ca to learn more " "about the Friendica project." msgstr "" -#: src/Module/Friendica.php:125 +#: src/Module/Friendica.php:124 msgid "Bug reports and issues: please visit" msgstr "" -#: src/Module/Friendica.php:125 +#: src/Module/Friendica.php:124 msgid "the bugtracker at github" msgstr "" -#: src/Module/Friendica.php:126 +#: src/Module/Friendica.php:125 msgid "" "Suggestions, praise, etc. - please email \"info\" at \"friendi - dot - ca" msgstr "" @@ -7288,10 +7318,6 @@ msgid "" "Theme Customization settings." msgstr "" -#: src/Module/Item/Display.php:136 src/Module/Update/Display.php:55 -msgid "The requested item doesn't exist or has been deleted." -msgstr "" - #: src/Module/Item/Feed.php:86 msgid "The feed for this item is unavailable." msgstr "" @@ -7550,6 +7576,8 @@ msgid "Matching known servers" msgstr "" #: src/Module/Moderation/Blocklist/Server/Add.php:130 +#: src/Module/Settings/Server/Action.php:76 +#: src/Module/Settings/Server/Index.php:106 msgid "Server Name" msgstr "" @@ -8520,21 +8548,21 @@ msgstr "" msgid "Attributed To: %s
" msgstr "" -#: src/Module/Photo.php:129 +#: src/Module/Photo.php:130 msgid "The Photo is not available." msgstr "" -#: src/Module/Photo.php:154 +#: src/Module/Photo.php:155 #, php-format msgid "The Photo with id %s is not available." msgstr "" -#: src/Module/Photo.php:191 +#: src/Module/Photo.php:192 #, php-format msgid "Invalid external resource with url %s." msgstr "" -#: src/Module/Photo.php:193 +#: src/Module/Photo.php:194 #, php-format msgid "Invalid photo with id %s." msgstr "" @@ -8640,8 +8668,8 @@ msgstr "" #: src/Module/Profile/Profile.php:158 #, php-format msgid "" -"You're currently viewing your profile as %s Cancel" +"You're currently viewing your profile as %s Cancel" msgstr "" #: src/Module/Profile/Profile.php:167 @@ -9189,8 +9217,8 @@ msgstr "" #: src/Module/Security/TwoFactor/Verify.php:100 #, php-format msgid "" -"If you do not have access to your authentication code you can use a two-factor recovery code." +"If you do not have access to your authentication code you can use a two-factor recovery code." msgstr "" #: src/Module/Security/TwoFactor/Verify.php:101 @@ -10387,6 +10415,42 @@ msgstr "" msgid "Please enter your password for verification:" msgstr "" +#: src/Module/Settings/Server/Action.php:60 +msgid "Do you want to ignore this server?" +msgstr "" + +#: src/Module/Settings/Server/Action.php:64 +msgid "Do you want to unignore this server?" +msgstr "" + +#: src/Module/Settings/Server/Action.php:74 +#: src/Module/Settings/Server/Index.php:104 +msgid "Remote server settings" +msgstr "" + +#: src/Module/Settings/Server/Action.php:77 +msgid "Server URL" +msgstr "" + +#: src/Module/Settings/Server/Index.php:78 +msgid "Settings saved" +msgstr "" + +#: src/Module/Settings/Server/Index.php:105 +msgid "" +"Here you can find all the remote servers you have taken individual " +"moderation actions against. For a list of servers your node has blocked, " +"please check out the Information page." +msgstr "" + +#: src/Module/Settings/Server/Index.php:110 +msgid "Delete all your settings for the remote server" +msgstr "" + +#: src/Module/Settings/Server/Index.php:111 +msgid "Save changes" +msgstr "" + #: src/Module/Settings/TwoFactor/AppSpecific.php:66 #: src/Module/Settings/TwoFactor/Recovery.php:64 #: src/Module/Settings/TwoFactor/Trusted.php:67 @@ -10668,8 +10732,8 @@ msgstr "" #: src/Module/Settings/TwoFactor/Verify.php:149 #, php-format msgid "" -"

Or you can open the following URL in your mobile device:

%s

" +"

Or you can open the following URL in your mobile device:

%s

" msgstr "" #: src/Module/Settings/TwoFactor/Verify.php:156 @@ -10707,22 +10771,41 @@ msgid "" "e.g. Mastodon." msgstr "" +#: src/Module/Special/DisplayNotFound.php:35 +msgid "The top-level post isn't visible." +msgstr "" + +#: src/Module/Special/DisplayNotFound.php:36 +msgid "The top-level post was deleted." +msgstr "" + #: src/Module/Special/DisplayNotFound.php:37 -msgid "Not Found" +msgid "" +"This node has blocked the top-level author or the author of the shared post." msgstr "" #: src/Module/Special/DisplayNotFound.php:38 msgid "" -"

Unfortunately, the requested conversation isn't available to you.

\n" -"

Possible reasons include:

\n" -"" +"You have ignored or blocked the top-level author or the author of the shared " +"post." +msgstr "" + +#: src/Module/Special/DisplayNotFound.php:39 +msgid "" +"You have ignored the top-level author's server or the shared post author's " +"server." +msgstr "" + +#: src/Module/Special/DisplayNotFound.php:45 +msgid "Conversation Not Found" +msgstr "" + +#: src/Module/Special/DisplayNotFound.php:46 +msgid "Unfortunately, the requested conversation isn't available to you." +msgstr "" + +#: src/Module/Special/DisplayNotFound.php:47 +msgid "Possible reasons include:" msgstr "" #: src/Module/Special/HTTPException.php:78 @@ -10759,9 +10842,9 @@ msgstr "" msgid "" "At any point in time a logged in user can export their account data from the " "account settings. If the user wants " -"to delete their account they can do so at " -"%1$s/settings/removeme. The deletion of the account will be permanent. " -"Deletion of the data will also be requested from the nodes of the " +"to delete their account they can do so at %1$s/settings/removeme. The deletion of the account will be " +"permanent. Deletion of the data will also be requested from the nodes of the " "communication partners." msgstr "" @@ -10777,6 +10860,10 @@ msgstr "" msgid "Parameter uri_id is missing." msgstr "" +#: src/Module/Update/Display.php:55 +msgid "The requested item doesn't exist or has been deleted." +msgstr "" + #: src/Module/User/Import.php:103 msgid "User imports on closed servers can only be done by an administrator." msgstr "" @@ -11487,258 +11574,258 @@ msgstr "" msgid "%s posted an update." msgstr "" -#: src/Object/Post.php:139 +#: src/Object/Post.php:140 msgid "Private Message" msgstr "" -#: src/Object/Post.php:143 +#: src/Object/Post.php:144 msgid "Public Message" msgstr "" -#: src/Object/Post.php:147 +#: src/Object/Post.php:148 msgid "Unlisted Message" msgstr "" -#: src/Object/Post.php:182 +#: src/Object/Post.php:183 msgid "This entry was edited" msgstr "" -#: src/Object/Post.php:210 +#: src/Object/Post.php:211 msgid "Connector Message" msgstr "" -#: src/Object/Post.php:226 src/Object/Post.php:228 +#: src/Object/Post.php:227 src/Object/Post.php:229 msgid "Edit" msgstr "" -#: src/Object/Post.php:261 +#: src/Object/Post.php:263 msgid "Delete globally" msgstr "" -#: src/Object/Post.php:261 +#: src/Object/Post.php:263 msgid "Remove locally" msgstr "" -#: src/Object/Post.php:268 +#: src/Object/Post.php:270 #, php-format msgid "Block %s" msgstr "" -#: src/Object/Post.php:273 +#: src/Object/Post.php:275 #, php-format msgid "Ignore %s" msgstr "" -#: src/Object/Post.php:278 +#: src/Object/Post.php:280 #, php-format msgid "Collapse %s" msgstr "" -#: src/Object/Post.php:282 +#: src/Object/Post.php:284 msgid "Report post" msgstr "" -#: src/Object/Post.php:287 +#: src/Object/Post.php:294 msgid "Save to folder" msgstr "" -#: src/Object/Post.php:327 +#: src/Object/Post.php:334 msgid "I will attend" msgstr "" -#: src/Object/Post.php:327 +#: src/Object/Post.php:334 msgid "I will not attend" msgstr "" -#: src/Object/Post.php:327 +#: src/Object/Post.php:334 msgid "I might attend" msgstr "" -#: src/Object/Post.php:357 +#: src/Object/Post.php:364 msgid "Ignore thread" msgstr "" -#: src/Object/Post.php:358 +#: src/Object/Post.php:365 msgid "Unignore thread" msgstr "" -#: src/Object/Post.php:359 +#: src/Object/Post.php:366 msgid "Toggle ignore status" msgstr "" -#: src/Object/Post.php:369 +#: src/Object/Post.php:376 msgid "Add star" msgstr "" -#: src/Object/Post.php:370 +#: src/Object/Post.php:377 msgid "Remove star" msgstr "" -#: src/Object/Post.php:371 +#: src/Object/Post.php:378 msgid "Toggle star status" msgstr "" -#: src/Object/Post.php:382 +#: src/Object/Post.php:389 msgid "Pin" msgstr "" -#: src/Object/Post.php:383 +#: src/Object/Post.php:390 msgid "Unpin" msgstr "" -#: src/Object/Post.php:384 +#: src/Object/Post.php:391 msgid "Toggle pin status" msgstr "" -#: src/Object/Post.php:387 +#: src/Object/Post.php:394 msgid "Pinned" msgstr "" -#: src/Object/Post.php:392 +#: src/Object/Post.php:399 msgid "Add tag" msgstr "" -#: src/Object/Post.php:405 +#: src/Object/Post.php:412 msgid "Quote share this" msgstr "" -#: src/Object/Post.php:405 +#: src/Object/Post.php:412 msgid "Quote Share" msgstr "" -#: src/Object/Post.php:408 +#: src/Object/Post.php:415 msgid "Reshare this" msgstr "" -#: src/Object/Post.php:408 +#: src/Object/Post.php:415 msgid "Reshare" msgstr "" -#: src/Object/Post.php:409 +#: src/Object/Post.php:416 msgid "Cancel your Reshare" msgstr "" -#: src/Object/Post.php:409 +#: src/Object/Post.php:416 msgid "Unshare" msgstr "" -#: src/Object/Post.php:460 +#: src/Object/Post.php:467 #, php-format msgid "%s (Received %s)" msgstr "" -#: src/Object/Post.php:466 +#: src/Object/Post.php:473 msgid "Comment this item on your system" msgstr "" -#: src/Object/Post.php:466 +#: src/Object/Post.php:473 msgid "Remote comment" msgstr "" -#: src/Object/Post.php:488 +#: src/Object/Post.php:495 msgid "Share via ..." msgstr "" -#: src/Object/Post.php:488 +#: src/Object/Post.php:495 msgid "Share via external services" msgstr "" -#: src/Object/Post.php:517 +#: src/Object/Post.php:524 msgid "to" msgstr "" -#: src/Object/Post.php:518 +#: src/Object/Post.php:525 msgid "via" msgstr "" -#: src/Object/Post.php:519 +#: src/Object/Post.php:526 msgid "Wall-to-Wall" msgstr "" -#: src/Object/Post.php:520 +#: src/Object/Post.php:527 msgid "via Wall-To-Wall:" msgstr "" -#: src/Object/Post.php:566 +#: src/Object/Post.php:574 #, php-format msgid "Reply to %s" msgstr "" -#: src/Object/Post.php:569 +#: src/Object/Post.php:577 msgid "More" msgstr "" -#: src/Object/Post.php:587 +#: src/Object/Post.php:596 msgid "Notifier task is pending" msgstr "" -#: src/Object/Post.php:588 +#: src/Object/Post.php:597 msgid "Delivery to remote servers is pending" msgstr "" -#: src/Object/Post.php:589 +#: src/Object/Post.php:598 msgid "Delivery to remote servers is underway" msgstr "" -#: src/Object/Post.php:590 +#: src/Object/Post.php:599 msgid "Delivery to remote servers is mostly done" msgstr "" -#: src/Object/Post.php:591 +#: src/Object/Post.php:600 msgid "Delivery to remote servers is done" msgstr "" -#: src/Object/Post.php:611 +#: src/Object/Post.php:620 #, php-format msgid "%d comment" msgid_plural "%d comments" msgstr[0] "" msgstr[1] "" -#: src/Object/Post.php:612 +#: src/Object/Post.php:621 msgid "Show more" msgstr "" -#: src/Object/Post.php:613 +#: src/Object/Post.php:622 msgid "Show fewer" msgstr "" -#: src/Object/Post.php:649 +#: src/Object/Post.php:658 #, php-format msgid "Reshared by: %s" msgstr "" -#: src/Object/Post.php:654 +#: src/Object/Post.php:663 #, php-format msgid "Viewed by: %s" msgstr "" -#: src/Object/Post.php:659 +#: src/Object/Post.php:668 #, php-format msgid "Liked by: %s" msgstr "" -#: src/Object/Post.php:664 +#: src/Object/Post.php:673 #, php-format msgid "Disliked by: %s" msgstr "" -#: src/Object/Post.php:669 +#: src/Object/Post.php:678 #, php-format msgid "Attended by: %s" msgstr "" -#: src/Object/Post.php:674 +#: src/Object/Post.php:683 #, php-format msgid "Maybe attended by: %s" msgstr "" -#: src/Object/Post.php:679 +#: src/Object/Post.php:688 #, php-format msgid "Not attended by: %s" msgstr "" -#: src/Object/Post.php:684 +#: src/Object/Post.php:693 #, php-format msgid "Reacted with %s by: %s" msgstr "" diff --git a/view/templates/admin/federation.tpl b/view/templates/admin/federation.tpl index dbee2ec3e..8f8d70cd2 100644 --- a/view/templates/admin/federation.tpl +++ b/view/templates/admin/federation.tpl @@ -57,7 +57,7 @@ {{if $c[0]['total'] > 0}} {{$c[0]['platform']}} - {{$c[0]['total']}} + {{$c[0]['total']}} {{$c[0]['network']}} diff --git a/view/templates/settings/server/action.tpl b/view/templates/settings/server/action.tpl new file mode 100644 index 000000000..2ead14e30 --- /dev/null +++ b/view/templates/settings/server/action.tpl @@ -0,0 +1,27 @@ +
+

{{$l10n.title}}

+ +
+ + + +

{{$l10n.action}}

+ + {{if $l10n.desc}} +

{{$l10n.desc}}

+ {{/if}} + + + + + + + + + + +
{{$l10n.siteName}}{{$GServer->siteName}}
{{$l10n.siteUrl}}{{$GServer->url}}
+ +

+
+
diff --git a/view/templates/settings/server/index.tpl b/view/templates/settings/server/index.tpl new file mode 100644 index 000000000..61df4c4bc --- /dev/null +++ b/view/templates/settings/server/index.tpl @@ -0,0 +1,45 @@ +
+

{{$l10n.title}} ({{$count}})

+ +

{{$l10n.desc nofilter}}

+ + {{$paginate nofilter}} + +
+ + +

+ + + + + + + + +{{foreach $servers as $index => $server}} + + + + + +{{/foreach}} + +
{{$l10n.siteName}}{{$l10n.ignored}} + + + {{$l10n.delete}} + + +
+ {{($server->gserver->siteName) ? $server->gserver->siteName : $server->gserver->url}} + + {{include file="field_checkbox.tpl" field=$ignoredCheckboxes[$index]}} + + {{include file="field_checkbox.tpl" field=$deleteCheckboxes[$index]}} +
+

+
+ + {{$paginate nofilter}} +
diff --git a/view/templates/special/displaynotfound.tpl b/view/templates/special/displaynotfound.tpl index 48e7b5166..a690f87c4 100644 --- a/view/templates/special/displaynotfound.tpl +++ b/view/templates/special/displaynotfound.tpl @@ -1,5 +1,11 @@
-

{{$title}}

- {{$message nofilter}} +

{{$l10n.title}}

+

{{$l10n.desc1}}

+

{{$l10n.desc2}}

+
    +{{foreach $l10n.reasons as $reason}} +
  • {{$reason}}
  • +{{/foreach}} +
diff --git a/view/theme/frio/js/textedit.js b/view/theme/frio/js/textedit.js index 94f1dd158..3a384bbb2 100644 --- a/view/theme/frio/js/textedit.js +++ b/view/theme/frio/js/textedit.js @@ -210,6 +210,10 @@ function confirmCollapse() { return confirm(aStr.collapseAuthor); } +function confirmIgnoreServer() { + return confirm(aStr.ignoreServer + "\n" + aStr.ignoreServerDesc); +} + /** * Hide and removes an item element from the DOM after the deletion url is * successful, restore it else. @@ -325,4 +329,34 @@ function collapseAuthor(url, elementId) { }); } } + + +/** + * Ignore author server + * + * @param {string} url The server ignore URL + * @param {string} elementId The DOM id of the item element + * @returns {undefined} + */ +function ignoreServer(url, elementId) { + if (confirmIgnoreServer()) { + $("body").css("cursor", "wait"); + + var $el = $(document.getElementById(elementId)); + + $el.fadeTo("fast", 0.33, function () { + $.post(url) + .then(function () { + $el.remove(); + }) + .fail(function () { + // @todo Show related error message + $el.fadeTo("fast", 1); + }) + .always(function () { + $("body").css("cursor", "auto"); + }); + }); + } +} // @license-end diff --git a/view/theme/frio/templates/contact_edit.tpl b/view/theme/frio/templates/contact_edit.tpl index 6b17da17f..56459df71 100644 --- a/view/theme/frio/templates/contact_edit.tpl +++ b/view/theme/frio/templates/contact_edit.tpl @@ -61,6 +61,7 @@ {{if $ignored}}
  • {{$ignored}}
  • {{/if}} {{if $collapsed}}
  • {{$collapsed}}
  • {{/if}} {{if $archived}}
  • {{$archived}}
  • {{/if}} + {{if $serverIgnored}}
  • {{$serverIgnored}} {{$manageServers}}
  • {{/if}} {{* End of contact-edit-status-wrapper *}} diff --git a/view/theme/frio/templates/js_strings.tpl b/view/theme/frio/templates/js_strings.tpl index f979355d7..8077ceb9e 100644 --- a/view/theme/frio/templates/js_strings.tpl +++ b/view/theme/frio/templates/js_strings.tpl @@ -3,10 +3,12 @@ They are loaded into the html so that js functions can use them *}}