]> git.mxchange.org Git - friendica.git/commitdiff
Use the post-counts table to display content (#13781)
authorMichael Vogel <icarus@dabo.de>
Sun, 31 Dec 2023 11:50:07 +0000 (12:50 +0100)
committerGitHub <noreply@github.com>
Sun, 31 Dec 2023 11:50:07 +0000 (12:50 +0100)
* Use the post-counts table to display content

* Use verb instead of vid

* Use verb

* Update counter on delete

12 files changed:
database.sql
src/Content/Conversation.php
src/Database/PostUpdate.php
src/Model/Item.php
src/Model/Post/Counts.php
src/Model/Verb.php
src/Module/Conversation/Network.php
src/Module/Conversation/Timeline.php
src/Object/Post.php
static/dbstructure.config.php
static/dbview.config.php
view/lang/C/messages.po

index 3c2fbb3150119249ce26b6b2e4c9f2645f9b8b55..87fbd84a6103ac2373f586adf52a205553dc37b1 100644 (file)
@@ -1,6 +1,6 @@
 -- ------------------------------------------
 -- Friendica 2024.03-dev (Yellow Archangel)
--- DB_UPDATE_VERSION 1543
+-- DB_UPDATE_VERSION 1544
 -- ------------------------------------------
 
 
@@ -2025,6 +2025,20 @@ CREATE VIEW `circle-member-view` AS SELECT
                        INNER JOIN `contact` ON `group_member`.`contact-id` = `contact`.`id`
                        INNER JOIN `group` ON `group_member`.`gid` = `group`.`id`;
 
+--
+-- VIEW post-counts-view
+--
+DROP VIEW IF EXISTS `post-counts-view`;
+CREATE VIEW `post-counts-view` AS SELECT 
+       `post-counts`.`uri-id` AS `uri-id`,
+       `post-counts`.`vid` AS `vid`,
+       `verb`.`name` AS `verb`,
+       `post-counts`.`reaction` AS `reaction`,
+       `post-counts`.`parent-uri-id` AS `parent-uri-id`,
+       `post-counts`.`count` AS `count`
+       FROM `post-counts`
+                       INNER JOIN `verb` ON `verb`.`id` = `post-counts`.`vid`;
+
 --
 -- VIEW post-timeline-view
 --
index 303850d9d9a4b54315b0084832f98be155e24351..453fe7a6636a0fd9db45e163e1d28251b90faa16 100644 (file)
@@ -96,8 +96,6 @@ class Conversation
        private $session;
        /** @var Repository\UserGServer */
        private $userGServer;
-       /** @var Array */
-       private $blockList;
 
        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)
        {
@@ -868,6 +866,7 @@ class Conversation
 
                $emojis      = $this->getEmojis($uriids);
                $quoteshares = $this->getQuoteShares($uriids);
+               $counts      = $this->getCounts($uriids);
 
                if (!$this->config->get('system', 'legacy_activities')) {
                        $condition = DBA::mergeConditions($condition, ["(`gravity` != ? OR `origin`)", ItemModel::GRAVITY_ACTIVITY]);
@@ -875,7 +874,7 @@ class Conversation
 
                $condition = DBA::mergeConditions(
                        $condition,
-                       ["`uid` IN (0, ?) AND (NOT `vid` IN (?, ?, ?) OR `vid` IS NULL)", $uid, Verb::getID(Activity::FOLLOW), Verb::getID(Activity::VIEW), Verb::getID(Activity::READ)]
+                       ["`uid` IN (0, ?) AND (NOT `verb` IN (?, ?, ?) OR `verb` IS NULL)", $uid, Activity::FOLLOW, Activity::VIEW, Activity::READ]
                );
 
                $condition = DBA::mergeConditions($condition, ["(`uid` != ? OR `private` != ?)", 0, ItemModel::PRIVATE]);
@@ -992,6 +991,7 @@ class Conversation
 
                foreach ($items as $key => $row) {
                        $items[$key]['emojis']      = $emojis[$key] ?? [];
+                       $items[$key]['counts']      = $counts[$key] ?? 0;
                        $items[$key]['quoteshares'] = $quoteshares[$key] ?? [];
 
                        $always_display = in_array($mode, [self::MODE_CONTACTS, self::MODE_CONTACT_POSTS]);
@@ -1025,6 +1025,16 @@ class Conversation
         */
        private function getEmojis(array $uriids): array
        {
+               $emojis = [];
+
+               foreach (Post\Counts::get(['parent-uri-id' => $uriids]) as $count) {
+                       $emojis[$count['uri-id']][$count['reaction']]['emoji'] = $count['reaction'];
+                       $emojis[$count['uri-id']][$count['reaction']]['verb']  = Verb::getByID($count['vid']);
+                       $emojis[$count['uri-id']][$count['reaction']]['total'] = $count['count'];
+                       $emojis[$count['uri-id']][$count['reaction']]['title'] = [];
+               }
+
+               // @todo The following code should be removed, once that we display activity authors on demand 
                $activity_emoji = [
                        Activity::LIKE        => '👍',
                        Activity::DISLIKE     => '👎',
@@ -1033,42 +1043,49 @@ class Conversation
                        Activity::ATTENDNO    => '❌',
                        Activity::ANNOUNCE    => '♻',
                        Activity::VIEW        => '📺',
+                       Activity::READ        => '📖',
                ];
 
-               $index_list = array_values($activity_emoji);
-               $verbs      = array_merge(array_keys($activity_emoji), [Activity::EMOJIREACT, Activity::POST]);
-
+               $verbs     = array_merge(array_keys($activity_emoji), [Activity::EMOJIREACT, Activity::POST]);
                $condition = DBA::mergeConditions(['parent-uri-id' => $uriids, 'gravity' => [ItemModel::GRAVITY_ACTIVITY, ItemModel::GRAVITY_COMMENT], 'verb' => $verbs], ["NOT `deleted`"]);
                $separator = chr(255) . chr(255) . chr(255);
 
-               $sql = "SELECT `thr-parent-id`, `body`, `verb`, `gravity`, COUNT(*) AS `total`, GROUP_CONCAT(REPLACE(`author-name`, '" . $separator . "', ' ') SEPARATOR '" . $separator . "' LIMIT 50) AS `title` FROM `post-view` WHERE " . array_shift($condition) . " GROUP BY `thr-parent-id`, `verb`, `body`, `gravity`";
-
-               $emojis = [];
+               $sql = "SELECT `parent-uri-id`, `thr-parent-id`, `body`, `verb`, `gravity`, GROUP_CONCAT(REPLACE(`author-name`, '" . $separator . "', ' ') SEPARATOR '" . $separator . "' LIMIT 50) AS `title` FROM `post-view` WHERE " . array_shift($condition) . " GROUP BY `parent-uri-id`, `thr-parent-id`, `verb`, `body`, `gravity`";
 
                $rows = DBA::p($sql, $condition);
                while ($row = DBA::fetch($rows)) {
                        if ($row['gravity'] == ItemModel::GRAVITY_ACTIVITY) {
-                               $row['verb'] = $row['body'] ? Activity::EMOJIREACT : $row['verb'];
-                               $emoji       = $row['body'] ?: $activity_emoji[$row['verb']];
+                               $emoji = $row['body'] ?: $activity_emoji[$row['verb']];
                        } else {
                                $emoji = '';
                        }
 
-                       if (!isset($index_list[$emoji])) {
-                               $index_list[] = $emoji;
+                       if (isset($emojis[$row['thr-parent-id']][$emoji]['title'])) {
+                               $emojis[$row['thr-parent-id']][$emoji]['title'] = array_unique(array_merge($emojis[$row['thr-parent-id']][$emoji]['title'] ?? [], explode($separator, $row['title'])));
                        }
-                       $index = array_search($emoji, $index_list);
-
-                       $emojis[$row['thr-parent-id']][$index]['emoji'] = $emoji;
-                       $emojis[$row['thr-parent-id']][$index]['verb']  = $row['verb'];
-                       $emojis[$row['thr-parent-id']][$index]['total'] = ($emojis[$row['thr-parent-id']][$index]['total'] ?? 0) + $row['total'];
-                       $emojis[$row['thr-parent-id']][$index]['title'] = array_unique(array_merge($emojis[$row['thr-parent-id']][$index]['title'] ?? [], explode($separator, $row['title'])));
                }
                DBA::close($rows);
 
                return $emojis;
        }
 
+       /**
+        * Fetch comment counts from the conversation
+        *
+        * @param array $uriids
+        * @return array
+        */
+       private function getCounts(array $uriids): array
+       {
+               $counts = [];
+
+               foreach (Post\Counts::get(['parent-uri-id' => $uriids, 'verb' => Activity::POST]) as $count) {
+                       $counts[$count['parent-uri-id']] = ($counts[$count['parent-uri-id']] ?? 0) + $count['count'];
+               }
+
+               return $counts;
+       }
+
        /**
         * Fetch quote shares from the conversation
         *
index ee8c060fa14798b0375ff48a7c7fcadb4686e35d..1434031eaf607f8b3f5ed03fefba409bba2cfd8b 100644 (file)
@@ -52,7 +52,7 @@ class PostUpdate
        // Needed for the helper function to read from the legacy term table
        const OBJECT_TYPE_POST  = 1;
 
-       const VERSION = 1543;
+       const VERSION = 1544;
 
        /**
         * Calls the post update functions
@@ -125,7 +125,7 @@ class PostUpdate
                if (!self::update1507()) {
                        return false;
                }
-               if (!self::update1543()) {
+               if (!self::update1544()) {
                        return false;
                }
                return true;
@@ -1315,20 +1315,24 @@ class PostUpdate
         * @throws \Friendica\Network\HTTPException\InternalServerErrorException
         * @throws \ImagickException
         */
-       private static function update1543()
+       private static function update1544()
        {
                // Was the script completed?
-               if (DI::keyValue()->get('post_update_version') >= 1543) {
+               if (DI::keyValue()->get('post_update_version') >= 1544) {
                        return true;
                }
 
-               $id = DI::keyValue()->get('post_update_version_1543_id') ?? 0;
+               $id = (int)(DI::keyValue()->get('post_update_version_1544_id') ?? 0);
+               if ($id == 0) {
+                       $post = Post::selectFirstPost(['uri-id'], [], ['order' => ['uri-id' => true]]);
+                       $id = (int)($post['uri-id'] ?? 0);
+               }
 
                Logger::info('Start', ['uri-id' => $id]);
 
                $rows = 0;
 
-               $posts = Post::selectPosts(['uri-id', 'parent-uri-id'], ["`uri-id` > ? AND `gravity` IN (?, ?)", $id, Item::GRAVITY_COMMENT, Item::GRAVITY_PARENT], ['order' => ['uri-id'], 'limit' => 1000]);
+               $posts = Post::selectPosts(['uri-id', 'parent-uri-id'], ["`uri-id` < ? AND `gravity` IN (?, ?)", $id, Item::GRAVITY_COMMENT, Item::GRAVITY_PARENT], ['order' => ['uri-id' => true], 'limit' => 1000]);
 
                if (DBA::errorNo() != 0) {
                        Logger::error('Database error', ['no' => DBA::errorNo(), 'message' => DBA::errorMessage()]);
@@ -1342,12 +1346,12 @@ class PostUpdate
                }
                DBA::close($posts);
 
-               DI::keyValue()->set('post_update_version_1543_id', $id);
+               DI::keyValue()->set('post_update_version_1544_id', $id);
 
                Logger::info('Processed', ['rows' => $rows, 'last' => $id]);
 
                if ($rows <= 100) {
-                       DI::keyValue()->set('post_update_version', 1543);
+                       DI::keyValue()->set('post_update_version', 1544);
                        Logger::info('Done');
                        return true;
                }
index b52f065b045e4abf40c5b58511496cf3ba4f9acb..3a613d618034398a92d6a7248f7c32470ee365cc 100644 (file)
@@ -338,7 +338,7 @@ class Item
                // locate item to be deleted
                $fields = [
                        'id', 'uri', 'uri-id', 'uid', 'parent', 'parent-uri-id', 'origin',
-                       'deleted', 'resource-id', 'event-id',
+                       'thr-parent-id', 'deleted', 'resource-id', 'event-id', 'vid', 'body',
                        'verb', 'object-type', 'object', 'target', 'contact-id', 'psid', 'gravity'
                ];
                $item = Post::selectFirst($fields, ['id' => $item_id]);
@@ -418,6 +418,10 @@ class Item
                DI::notify()->deleteForItem($item['uri-id']);
                DI::notification()->deleteForItem($item['uri-id']);
 
+               if (in_array($item['gravity'], [self::GRAVITY_ACTIVITY, self::GRAVITY_COMMENT])) {
+                       Post\Counts::update($item['thr-parent-id'], $item['parent-uri-id'], $item['vid'], $item['verb'], $item['body']);
+               }
+
                Logger::info('Item has been marked for deletion.', ['id' => $item_id]);
 
                return true;
@@ -1427,16 +1431,15 @@ class Item
                        Worker::add(['priority' => $priority, 'dont_fork' => true], 'Notifier', $notify_type, (int)$posted_item['uri-id'], (int)$posted_item['uid']);
                }
 
-               // Fill the cache with the rendered content.
-               if (in_array($posted_item['gravity'], [self::GRAVITY_PARENT, self::GRAVITY_COMMENT]) && ($posted_item['uid'] == 0)) {
-                       self::updateDisplayCache($posted_item['uri-id']);
-               }
-
-               if (in_array($posted_item['gravity'], [self::GRAVITY_ACTIVITY, self::GRAVITY_COMMENT]) && ($posted_item['uid'] == 0)) {
-                       Post\Counts::update($posted_item['thr-parent-id'], $posted_item['parent-uri-id'], $posted_item['vid'], $posted_item['verb'], $posted_item['body']);
-               }
-
                if ($inserted) {
+                       // Fill the cache with the rendered content.
+                       if (in_array($posted_item['gravity'], [self::GRAVITY_PARENT, self::GRAVITY_COMMENT])) {
+                               self::updateDisplayCache($posted_item['uri-id']);
+                       }
+
+                       if (in_array($posted_item['gravity'], [self::GRAVITY_ACTIVITY, self::GRAVITY_COMMENT])) {
+                               Post\Counts::update($posted_item['thr-parent-id'], $posted_item['parent-uri-id'], $posted_item['vid'], $posted_item['verb'], $posted_item['body']);
+                       }
                        Post\Engagement::storeFromItem($posted_item);
                }
 
index 2d6f671d7d510ea0151ae7f22d2bd9531c732a42..865b3bdb4c78212f187a0563ffdaee207e5c93e5 100644 (file)
@@ -38,11 +38,20 @@ class Counts
         */
        public static function update(int $uri_id, int $parent_uri_id, int $vid, string $verb, string $body = null)
        {
-               $condition = ['thr-parent-id' => $uri_id, 'vid' => $vid];
+               if (!in_array($verb, [Activity::POST, Activity::LIKE, Activity::DISLIKE,
+                       Activity::ATTEND, Activity::ATTENDMAYBE, Activity::ATTENDNO,
+                       Activity::EMOJIREACT, Activity::ANNOUNCE, Activity::VIEW, Activity::READ])) {
+                       return true;
+               }
+       
+               $condition = ['thr-parent-id' => $uri_id, 'vid' => $vid, 'deleted' => false];
 
                if ($body == $verb) {
                        $condition['body'] = null;
                        $body              = '';
+               } elseif ($verb == Activity::POST) {
+                       $condition['gravity'] = Item::GRAVITY_COMMENT;
+                       $body                 = '';
                } elseif (($verb != Activity::POST) && (mb_strlen($body) == 1) && Smilies::isEmojiPost($body)) {
                        $condition['body'] = $body;
                } else {
@@ -58,6 +67,7 @@ class Counts
                ];
 
                if ($fields['count'] == 0) {
+                       DBA::delete('post-counts', ['uri-id' => $uri_id, 'vid' => $vid, 'reaction' => $body]);
                        return true;
                }
 
@@ -76,14 +86,41 @@ class Counts
        }
 
        /**
-        * Retrieves counts of the given uri-id
+        * Retrieves counts of the given condition
         *
-        * @param int $uriId
+        * @param array $condition
         *
         * @return array
         */
-       public static function getByURIId(int $uriId): array
+       public static function get(array $condition): array
        {
-               return DBA::selectToArray('post-counts', [], ['uri-id' => $uriId]);
+               $counts = [];
+
+               $activity_emoji = [
+                       Activity::LIKE        => '👍',
+                       Activity::DISLIKE     => '👎',
+                       Activity::ATTEND      => '✔️',
+                       Activity::ATTENDMAYBE => '❓',
+                       Activity::ATTENDNO    => '❌',
+                       Activity::ANNOUNCE    => '♻',
+                       Activity::VIEW        => '📺',
+                       Activity::READ        => '📖',
+               ];
+
+               $verbs = array_merge(array_keys($activity_emoji), [Activity::EMOJIREACT, Activity::POST]);
+
+               $condition  = DBA::mergeConditions($condition, ['verb' => $verbs]);
+               $countquery = DBA::select('post-counts-view', [], $condition);
+               while ($count = DBA::fetch($countquery)) {
+                       if (!empty($count['reaction'])) {
+                               $count['verb'] = Activity::EMOJIREACT;
+                               $count['vid']  = Verb::getID($count['verb']);
+                       } elseif (!empty($activity_emoji[$count['verb']])) {
+                               $count['reaction'] = $activity_emoji[$count['verb']];
+                       }
+                       $counts[] = $count;
+               }
+               DBA::close($counts);
+               return $counts;
        }
 }
index 488715b28797ef59ee7519d6fd1cfebcffc7f7e8..72759834ec0d8cfcb9a5c43c2ed604dfa2959fc1 100644 (file)
@@ -26,6 +26,8 @@ use Friendica\Database\DBA;
 
 class Verb
 {
+       static $verbs = [];
+
        /**
         * Insert a verb record and return its id
         *
@@ -40,14 +42,23 @@ class Verb
                        return 0;
                }
 
+               $id = array_search($verb, self::$verbs);
+               if ($id !== false) {
+                       return $id;
+               }
+
                $verb_record = DBA::selectFirst('verb', ['id'], ['name' => $verb]);
                if (DBA::isResult($verb_record)) {
+                       self::$verbs[$verb_record['id']] = $verb;
                        return $verb_record['id'];
                }
 
                DBA::insert('verb', ['name' => $verb], Database::INSERT_IGNORE);
 
-               return DBA::lastInsertId();
+               $id = DBA::lastInsertId();
+               self::$verbs[$id] = $verb;
+               return $id;
+
        }
 
        /**
@@ -62,11 +73,17 @@ class Verb
                        return '';
                }
 
+               if (!empty(self::$verbs[$id])) {
+                       return self::$verbs[$id];
+               }
+
                $verb_record = DBA::selectFirst('verb', ['name'], ['id' => $id]);
                if (!DBA::isResult($verb_record)) {
                        return '';
                }
 
+               self::$verbs[$id] = $verb_record['name'];
+
                return $verb_record['name'];
        }
 }
index b98e9d36523a4d80c51b985f07d287adea71081c..89c9ccb1973ddb626eb813a38221822d44c50dac 100644 (file)
@@ -435,8 +435,8 @@ class Network extends Timeline
                        $conditionStrings = DBA::mergeConditions($conditionStrings, ["`contact-id` IN (SELECT `contact-id` FROM `group_member` WHERE `gid` = ?)", $this->circleId]);
                } elseif ($this->groupContactId) {
                        $conditionStrings = DBA::mergeConditions($conditionStrings,
-                               ["((`contact-id` = ?) OR `uri-id` IN (SELECT `parent-uri-id` FROM `post-user-view` WHERE (`contact-id` = ? AND `gravity` = ? AND `vid` = ? AND `uid` = ?)))",
-                               $this->groupContactId, $this->groupContactId, Item::GRAVITY_ACTIVITY, Verb::getID(Activity::ANNOUNCE), $this->session->getLocalUserId()]);
+                               ["((`contact-id` = ?) OR `uri-id` IN (SELECT `parent-uri-id` FROM `post-user-view` WHERE (`contact-id` = ? AND `gravity` = ? AND `verb` = ? AND `uid` = ?)))",
+                               $this->groupContactId, $this->groupContactId, Item::GRAVITY_ACTIVITY, Activity::ANNOUNCE, $this->session->getLocalUserId()]);
                }
 
                // Currently only the order modes "received" and "commented" are in use
index 1e49970e65b5e94577d4932bfd4e0359a5885019..9001a43871d7c1576bb73adbcd0d21cfaa6233f9 100644 (file)
@@ -41,7 +41,9 @@ use Friendica\Database\DBA;
 use Friendica\Model\Item;
 use Friendica\Model\Post;
 use Friendica\Model\Post\Engagement;
+use Friendica\Model\Verb;
 use Friendica\Module\Response;
+use Friendica\Protocol\Activity;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Profiler;
 use Psr\Log\LoggerInterface;
@@ -626,6 +628,8 @@ class Timeline extends BaseModule
                $result = Post::selectThreadForUser($this->session->getLocalUserId() ?: 0, ['uri-id', 'received', 'author-id', 'author-gsid'], $condition, $params);
 
                while ($item = $this->database->fetch($result)) {
+                       $item['comments'] = 0;
+
                        $items[$item['uri-id']] = $item;
                }
                $this->database->close($result);
@@ -634,6 +638,12 @@ class Timeline extends BaseModule
                        return [];
                }
 
+               $uriids = array_keys($items);
+               
+               foreach (Post\Counts::get(['parent-uri-id' => $uriids, 'verb' => Activity::POST]) as $count) {
+                       $items[$count['parent-uri-id']]['comments'] += $count['count'];
+               }
+
                // Previous page case: once we get the relevant items closest to min_id, we need to restore the expected display order
                if (empty($this->itemUriId) && isset($this->minId) && !isset($this->maxId)) {
                        $items = array_reverse($items);
index d52a05dddcf990aa76b029aa4c9584bb1c6959a2..0176e49ad7c3c3d4f88ccf6a4606b93f94845966 100644 (file)
@@ -201,7 +201,7 @@ class Post
                $indent = '';
                $shiny = '';
                $osparkle = '';
-               $total_children = $this->countDescendants();
+               $total_children = $item['counts'] ?? $this->countDescendants();
 
                $conv = $this->getThread();
 
@@ -697,6 +697,11 @@ class Post
                                        $icon  = ['fa' => 'fa-eye', 'icon' => 'icon-eye-open'];
                                        break;
 
+                               case Activity::READ:
+                                       $title = DI::l10n()->t('Read by: %s', $actors);
+                                       $icon  = ['fa' => 'fa-book', 'icon' => 'icon-book'];
+                                       break;
+
                                case Activity::LIKE:
                                        $title = DI::l10n()->t('Liked by: %s', $actors);
                                        $icon  = ['fa' => 'fa-thumbs-up', 'icon' => 'icon-thumbs-up'];
index d3963e205bd2e299a77ecdc28ab660452e321f85..1a3ef8aa87c8d62a082d5c793fd4a5992e163947 100644 (file)
@@ -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', 1543);
+       define('DB_UPDATE_VERSION', 1544);
 }
 
 return [
index b4d10de83c426843b62aaaabcb26dd14d69b937b..91661a43ef167e57195482c77406e318aef65b59 100644 (file)
                        INNER JOIN `contact` ON `group_member`.`contact-id` = `contact`.`id`
                        INNER JOIN `group` ON `group_member`.`gid` = `group`.`id`"
        ],
+       "post-counts-view" => [
+               "fields" => [
+                       "uri-id" => ["post-counts", "uri-id"],
+                       "vid" => ["post-counts", "vid"],
+                       "verb" => ["verb", "name"],
+                       "reaction" => ["post-counts", "reaction"],
+                       "parent-uri-id" => ["post-counts", "parent-uri-id"],
+                       "count" => ["post-counts", "count"],
+               ],
+               "query" => "FROM `post-counts`
+                       INNER JOIN `verb` ON `verb`.`id` = `post-counts`.`vid`"
+       ],
        "post-timeline-view" => [
                "fields" => [
                        "uid" => ["post-user", "uid"],
index bcd02c885bf6d4411f5cb2eb817ffff577faa9fe..a812ef31fb69dd9eb4490375504dbef113a44853 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: 2024.03-dev\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-12-25 10:16+0000\n"
+"POT-Creation-Date: 2023-12-30 21:51+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -293,7 +293,7 @@ msgid "Insert web link"
 msgstr ""
 
 #: mod/message.php:201 mod/message.php:357 mod/photos.php:1301
-#: src/Content/Conversation.php:401 src/Content/Conversation.php:1604
+#: src/Content/Conversation.php:401 src/Content/Conversation.php:1589
 #: src/Module/Item/Compose.php:206 src/Module/Post/Edit.php:145
 #: src/Module/Profile/UnkMail.php:154 src/Object/Post.php:609
 msgid "Please wait"
@@ -318,7 +318,7 @@ msgstr ""
 #: src/Module/Profile/Profile.php:274 src/Module/Profile/UnkMail.php:155
 #: src/Module/Settings/Profile/Index.php:257
 #: src/Module/Settings/Server/Action.php:79 src/Module/User/Delegation.php:189
-#: src/Object/Post.php:1149 view/theme/duepuntozero/config.php:85
+#: src/Object/Post.php:1154 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"
@@ -603,34 +603,34 @@ msgstr ""
 
 #: mod/photos.php:1139 mod/photos.php:1195 mod/photos.php:1275
 #: src/Module/Contact.php:618 src/Module/Item/Compose.php:188
-#: src/Object/Post.php:1146
+#: src/Object/Post.php:1151
 msgid "This is you"
 msgstr ""
 
 #: mod/photos.php:1141 mod/photos.php:1197 mod/photos.php:1277
 #: src/Module/Moderation/Reports.php:95 src/Object/Post.php:603
-#: src/Object/Post.php:1148
+#: src/Object/Post.php:1153
 msgid "Comment"
 msgstr ""
 
 #: mod/photos.php:1143 mod/photos.php:1199 mod/photos.php:1279
 #: src/Content/Conversation.php:416 src/Module/Calendar/Event/Form.php:248
 #: src/Module/Item/Compose.php:201 src/Module/Post/Edit.php:165
-#: src/Object/Post.php:1162
+#: src/Object/Post.php:1167
 msgid "Preview"
 msgstr ""
 
 #: mod/photos.php:1144 src/Content/Conversation.php:369
-#: src/Module/Post/Edit.php:130 src/Object/Post.php:1150
+#: src/Module/Post/Edit.php:130 src/Object/Post.php:1155
 msgid "Loading..."
 msgstr ""
 
-#: mod/photos.php:1236 src/Content/Conversation.php:1519
+#: mod/photos.php:1236 src/Content/Conversation.php:1504
 #: src/Object/Post.php:261
 msgid "Select"
 msgstr ""
 
-#: mod/photos.php:1237 src/Content/Conversation.php:1520
+#: mod/photos.php:1237 src/Content/Conversation.php:1505
 #: src/Module/Moderation/Users/Active.php:136
 #: src/Module/Moderation/Users/Blocked.php:136
 #: src/Module/Moderation/Users/Index.php:151
@@ -1244,7 +1244,7 @@ msgid "Visible to <strong>everybody</strong>"
 msgstr ""
 
 #: src/Content/Conversation.php:339 src/Module/Item/Compose.php:200
-#: src/Object/Post.php:1161
+#: src/Object/Post.php:1166
 msgid "Please enter a image/video/audio/webpage URL:"
 msgstr ""
 
@@ -1289,52 +1289,52 @@ msgid "attach file"
 msgstr ""
 
 #: src/Content/Conversation.php:374 src/Module/Item/Compose.php:190
-#: src/Module/Post/Edit.php:171 src/Object/Post.php:1151
+#: src/Module/Post/Edit.php:171 src/Object/Post.php:1156
 msgid "Bold"
 msgstr ""
 
 #: src/Content/Conversation.php:375 src/Module/Item/Compose.php:191
-#: src/Module/Post/Edit.php:172 src/Object/Post.php:1152
+#: src/Module/Post/Edit.php:172 src/Object/Post.php:1157
 msgid "Italic"
 msgstr ""
 
 #: src/Content/Conversation.php:376 src/Module/Item/Compose.php:192
-#: src/Module/Post/Edit.php:173 src/Object/Post.php:1153
+#: src/Module/Post/Edit.php:173 src/Object/Post.php:1158
 msgid "Underline"
 msgstr ""
 
 #: src/Content/Conversation.php:377 src/Module/Item/Compose.php:193
-#: src/Module/Post/Edit.php:174 src/Object/Post.php:1155
+#: src/Module/Post/Edit.php:174 src/Object/Post.php:1160
 msgid "Quote"
 msgstr ""
 
 #: src/Content/Conversation.php:378 src/Module/Item/Compose.php:194
-#: src/Module/Post/Edit.php:175 src/Object/Post.php:1156
+#: src/Module/Post/Edit.php:175 src/Object/Post.php:1161
 msgid "Add emojis"
 msgstr ""
 
 #: src/Content/Conversation.php:379 src/Module/Item/Compose.php:195
-#: src/Object/Post.php:1154
+#: src/Object/Post.php:1159
 msgid "Content Warning"
 msgstr ""
 
 #: src/Content/Conversation.php:380 src/Module/Item/Compose.php:196
-#: src/Module/Post/Edit.php:176 src/Object/Post.php:1157
+#: src/Module/Post/Edit.php:176 src/Object/Post.php:1162
 msgid "Code"
 msgstr ""
 
 #: src/Content/Conversation.php:381 src/Module/Item/Compose.php:197
-#: src/Object/Post.php:1158
+#: src/Object/Post.php:1163
 msgid "Image"
 msgstr ""
 
 #: src/Content/Conversation.php:382 src/Module/Item/Compose.php:198
-#: src/Module/Post/Edit.php:177 src/Object/Post.php:1159
+#: src/Module/Post/Edit.php:177 src/Object/Post.php:1164
 msgid "Link"
 msgstr ""
 
 #: src/Content/Conversation.php:383 src/Module/Item/Compose.php:199
-#: src/Module/Post/Edit.php:178 src/Object/Post.php:1160
+#: src/Module/Post/Edit.php:178 src/Object/Post.php:1165
 msgid "Link or Media"
 msgstr ""
 
@@ -1404,116 +1404,116 @@ msgstr ""
 msgid "Delete Selected Items"
 msgstr ""
 
-#: src/Content/Conversation.php:756 src/Content/Conversation.php:759
-#: src/Content/Conversation.php:762 src/Content/Conversation.php:765
-#: src/Content/Conversation.php:768
+#: src/Content/Conversation.php:729 src/Content/Conversation.php:732
+#: src/Content/Conversation.php:735 src/Content/Conversation.php:738
+#: src/Content/Conversation.php:741
 #, php-format
 msgid "You had been addressed (%s)."
 msgstr ""
 
-#: src/Content/Conversation.php:771
+#: src/Content/Conversation.php:744
 #, php-format
 msgid "You are following %s."
 msgstr ""
 
-#: src/Content/Conversation.php:776
+#: src/Content/Conversation.php:749
 #, php-format
 msgid "You subscribed to %s."
 msgstr ""
 
-#: src/Content/Conversation.php:778
+#: src/Content/Conversation.php:751
 msgid "You subscribed to one or more tags in this post."
 msgstr ""
 
-#: src/Content/Conversation.php:798
+#: src/Content/Conversation.php:771
 #, php-format
 msgid "%s reshared this."
 msgstr ""
 
-#: src/Content/Conversation.php:800
+#: src/Content/Conversation.php:773
 msgid "Reshared"
 msgstr ""
 
-#: src/Content/Conversation.php:800
+#: src/Content/Conversation.php:773
 #, php-format
 msgid "Reshared by %s <%s>"
 msgstr ""
 
-#: src/Content/Conversation.php:803
+#: src/Content/Conversation.php:776
 #, php-format
 msgid "%s is participating in this thread."
 msgstr ""
 
-#: src/Content/Conversation.php:806
+#: src/Content/Conversation.php:779
 msgid "Stored for general reasons"
 msgstr ""
 
-#: src/Content/Conversation.php:809
+#: src/Content/Conversation.php:782
 msgid "Global post"
 msgstr ""
 
-#: src/Content/Conversation.php:812
+#: src/Content/Conversation.php:785
 msgid "Sent via an relay server"
 msgstr ""
 
-#: src/Content/Conversation.php:812
+#: src/Content/Conversation.php:785
 #, php-format
 msgid "Sent via the relay server %s <%s>"
 msgstr ""
 
-#: src/Content/Conversation.php:815
+#: src/Content/Conversation.php:788
 msgid "Fetched"
 msgstr ""
 
-#: src/Content/Conversation.php:815
+#: src/Content/Conversation.php:788
 #, php-format
 msgid "Fetched because of %s <%s>"
 msgstr ""
 
-#: src/Content/Conversation.php:818
+#: src/Content/Conversation.php:791
 msgid "Stored because of a child post to complete this thread."
 msgstr ""
 
-#: src/Content/Conversation.php:821
+#: src/Content/Conversation.php:794
 msgid "Local delivery"
 msgstr ""
 
-#: src/Content/Conversation.php:824
+#: src/Content/Conversation.php:797
 msgid "Stored because of your activity (like, comment, star, ...)"
 msgstr ""
 
-#: src/Content/Conversation.php:827
+#: src/Content/Conversation.php:800
 msgid "Distributed"
 msgstr ""
 
-#: src/Content/Conversation.php:830
+#: src/Content/Conversation.php:803
 msgid "Pushed to us"
 msgstr ""
 
-#: src/Content/Conversation.php:1547 src/Object/Post.php:248
+#: src/Content/Conversation.php:1532 src/Object/Post.php:248
 msgid "Pinned item"
 msgstr ""
 
-#: src/Content/Conversation.php:1564 src/Object/Post.php:548
+#: src/Content/Conversation.php:1549 src/Object/Post.php:548
 #: src/Object/Post.php:549
 #, php-format
 msgid "View %s's profile @ %s"
 msgstr ""
 
-#: src/Content/Conversation.php:1577 src/Object/Post.php:536
+#: src/Content/Conversation.php:1562 src/Object/Post.php:536
 msgid "Categories:"
 msgstr ""
 
-#: src/Content/Conversation.php:1578 src/Object/Post.php:537
+#: src/Content/Conversation.php:1563 src/Object/Post.php:537
 msgid "Filed under:"
 msgstr ""
 
-#: src/Content/Conversation.php:1586 src/Object/Post.php:562
+#: src/Content/Conversation.php:1571 src/Object/Post.php:562
 #, php-format
 msgid "%s from %s"
 msgstr ""
 
-#: src/Content/Conversation.php:1602
+#: src/Content/Conversation.php:1587
 msgid "View in context"
 msgstr ""
 
@@ -1770,7 +1770,7 @@ msgstr ""
 msgid "Create new group"
 msgstr ""
 
-#: src/Content/Item.php:332 src/Model/Item.php:3159
+#: src/Content/Item.php:332 src/Model/Item.php:3162
 msgid "event"
 msgstr ""
 
@@ -1778,7 +1778,7 @@ msgstr ""
 msgid "status"
 msgstr ""
 
-#: src/Content/Item.php:341 src/Model/Item.php:3161
+#: src/Content/Item.php:341 src/Model/Item.php:3164
 #: src/Module/Post/Tag/Add.php:123
 msgid "photo"
 msgstr ""
@@ -2190,8 +2190,8 @@ msgid ""
 "<a href=\"%1$s\" target=\"_blank\" rel=\"noopener noreferrer\">%2$s</a> %3$s"
 msgstr ""
 
-#: src/Content/Text/BBCode.php:994 src/Model/Item.php:3892
-#: src/Model/Item.php:3898 src/Model/Item.php:3899
+#: src/Content/Text/BBCode.php:994 src/Model/Item.php:3895
+#: src/Model/Item.php:3901 src/Model/Item.php:3902
 msgid "Link to source"
 msgstr ""
 
@@ -3408,91 +3408,91 @@ msgstr ""
 msgid "Happy Birthday %s"
 msgstr ""
 
-#: src/Model/Item.php:2210
+#: src/Model/Item.php:2213
 #, php-format
 msgid "%s (%s - %s): %s"
 msgstr ""
 
-#: src/Model/Item.php:2212
+#: src/Model/Item.php:2215
 #, php-format
 msgid "%s (%s): %s"
 msgstr ""
 
-#: src/Model/Item.php:2215
+#: src/Model/Item.php:2218
 #, php-format
 msgid "Detected languages in this post:\\n%s"
 msgstr ""
 
-#: src/Model/Item.php:3163
+#: src/Model/Item.php:3166
 msgid "activity"
 msgstr ""
 
-#: src/Model/Item.php:3165
+#: src/Model/Item.php:3168
 msgid "comment"
 msgstr ""
 
-#: src/Model/Item.php:3168 src/Module/Post/Tag/Add.php:123
+#: src/Model/Item.php:3171 src/Module/Post/Tag/Add.php:123
 msgid "post"
 msgstr ""
 
-#: src/Model/Item.php:3338
+#: src/Model/Item.php:3341
 #, php-format
 msgid "%s is blocked"
 msgstr ""
 
-#: src/Model/Item.php:3340
+#: src/Model/Item.php:3343
 #, php-format
 msgid "%s is ignored"
 msgstr ""
 
-#: src/Model/Item.php:3342
+#: src/Model/Item.php:3345
 #, php-format
 msgid "Content from %s is collapsed"
 msgstr ""
 
-#: src/Model/Item.php:3346
+#: src/Model/Item.php:3349
 #, php-format
 msgid "Content warning: %s"
 msgstr ""
 
-#: src/Model/Item.php:3799
+#: src/Model/Item.php:3802
 msgid "bytes"
 msgstr ""
 
-#: src/Model/Item.php:3830
+#: src/Model/Item.php:3833
 #, php-format
 msgid "%2$s (%3$d%%, %1$d vote)"
 msgid_plural "%2$s (%3$d%%, %1$d votes)"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Model/Item.php:3832
+#: src/Model/Item.php:3835
 #, php-format
 msgid "%2$s (%1$d vote)"
 msgid_plural "%2$s (%1$d votes)"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Model/Item.php:3837
+#: src/Model/Item.php:3840
 #, php-format
 msgid "%d voter. Poll end: %s"
 msgid_plural "%d voters. Poll end: %s"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Model/Item.php:3839
+#: src/Model/Item.php:3842
 #, php-format
 msgid "%d voter."
 msgid_plural "%d voters."
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/Model/Item.php:3841
+#: src/Model/Item.php:3844
 #, php-format
 msgid "Poll end: %s"
 msgstr ""
 
-#: src/Model/Item.php:3875 src/Model/Item.php:3876
+#: src/Model/Item.php:3878 src/Model/Item.php:3879
 msgid "View on separate page"
 msgstr ""
 
@@ -7019,15 +7019,15 @@ msgstr ""
 msgid "Network feed not available."
 msgstr ""
 
-#: src/Module/Conversation/Timeline.php:166
+#: src/Module/Conversation/Timeline.php:168
 msgid "Own Contacts"
 msgstr ""
 
-#: src/Module/Conversation/Timeline.php:170
+#: src/Module/Conversation/Timeline.php:172
 msgid "Include"
 msgstr ""
 
-#: src/Module/Conversation/Timeline.php:171
+#: src/Module/Conversation/Timeline.php:173
 msgid "Hide"
 msgstr ""
 
@@ -12415,40 +12415,45 @@ msgstr ""
 
 #: src/Object/Post.php:701
 #, php-format
-msgid "Liked by: %s"
+msgid "Read by: %s"
 msgstr ""
 
 #: src/Object/Post.php:706
 #, php-format
-msgid "Disliked by: %s"
+msgid "Liked by: %s"
 msgstr ""
 
 #: src/Object/Post.php:711
 #, php-format
-msgid "Attended by: %s"
+msgid "Disliked by: %s"
 msgstr ""
 
 #: src/Object/Post.php:716
 #, php-format
-msgid "Maybe attended by: %s"
+msgid "Attended by: %s"
 msgstr ""
 
 #: src/Object/Post.php:721
 #, php-format
-msgid "Not attended by: %s"
+msgid "Maybe attended by: %s"
 msgstr ""
 
 #: src/Object/Post.php:726
 #, php-format
-msgid "Commented by: %s"
+msgid "Not attended by: %s"
 msgstr ""
 
 #: src/Object/Post.php:731
 #, php-format
+msgid "Commented by: %s"
+msgstr ""
+
+#: src/Object/Post.php:736
+#, php-format
 msgid "Reacted with %s by: %s"
 msgstr ""
 
-#: src/Object/Post.php:754
+#: src/Object/Post.php:759
 #, php-format
 msgid "Quote shared by: %s"
 msgstr ""