Merge branch '5.5' into 6.0
authorAlexander Ebert <ebert@woltlab.com>
Tue, 26 Sep 2023 10:05:15 +0000 (12:05 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Tue, 26 Sep 2023 10:05:15 +0000 (12:05 +0200)
126 files changed:
.github/workflows/codestyle.yml
.github/workflows/d-ts.yml [new file with mode: 0644]
.github/workflows/javascript.yml
.github/workflows/php.yml
.github/workflows/typescript.yml
.php-cs-fixer.dist.php
.phpcs.xml
fileDelete.xml
files/acp/database/update_com.woltlab.wcf.conversation_5.5_step1.php [deleted file]
files/acp/database/update_com.woltlab.wcf.conversation_5.5_step2.php [deleted file]
files/acp/update_com.woltlab.wcf.conversation_5.5_cleanup_orphaned_attachments.php [deleted file]
files/js/WCF.Conversation.js
files/js/WCF.Conversation.min.js
files/js/WCF.Conversation.tiny.min.js
files/js/WoltLabSuite.Core.Conversation.min.js
files/js/WoltLabSuite.Core.Conversation.tiny.min.js
files/js/WoltLabSuite/Core/Conversation/Ui/MarkAllAsRead.js [new file with mode: 0644]
files/js/WoltLabSuite/Core/Conversation/Ui/MarkAsRead.js [new file with mode: 0644]
files/js/WoltLabSuite/Core/Conversation/Ui/Message/Quote.js
files/js/WoltLabSuite/Core/Conversation/Ui/Object/Action/RemoveParticipant.js
files/js/WoltLabSuite/Core/Conversation/Ui/Participant/Add.js
files/js/WoltLabSuite/Core/Conversation/Ui/Subject/Editor.js
files/js/WoltLabSuite/Core/Conversation/Ui/User/Menu/Data/Conversation.js
files/lib/bootstrap/com.woltlab.wcf.conversation.php [new file with mode: 0644]
files/lib/data/conversation/Conversation.class.php
files/lib/data/conversation/ConversationAction.class.php
files/lib/data/conversation/ConversationEditor.class.php
files/lib/data/conversation/ConversationList.class.php
files/lib/data/conversation/ConversationParticipantList.class.php
files/lib/data/conversation/FeedConversation.class.php
files/lib/data/conversation/FeedConversationList.class.php
files/lib/data/conversation/UserConversationList.class.php
files/lib/data/conversation/ViewableConversation.class.php
files/lib/data/conversation/label/ConversationLabel.class.php
files/lib/data/conversation/label/ConversationLabelAction.class.php
files/lib/data/conversation/label/ConversationLabelEditor.class.php
files/lib/data/conversation/label/ConversationLabelList.class.php
files/lib/data/conversation/message/ConversationMessage.class.php
files/lib/data/conversation/message/ConversationMessageAction.class.php
files/lib/data/conversation/message/ConversationMessageEditor.class.php
files/lib/data/conversation/message/ConversationMessageList.class.php
files/lib/data/conversation/message/SearchResultConversationMessage.class.php
files/lib/data/conversation/message/SearchResultConversationMessageList.class.php
files/lib/data/conversation/message/SimplifiedViewableConversationMessageList.class.php
files/lib/data/conversation/message/ViewableConversationMessage.class.php
files/lib/data/conversation/message/ViewableConversationMessageList.class.php
files/lib/data/modification/log/ConversationLogModificationLogList.class.php
files/lib/data/modification/log/ViewableConversationModificationLog.class.php
files/lib/form/ConversationAddForm.class.php
files/lib/form/ConversationDraftEditForm.class.php
files/lib/page/ConversationFeedPage.class.php
files/lib/page/ConversationListPage.class.php
files/lib/page/ConversationPage.class.php
files/lib/system/attachment/ConversationMessageAttachmentObjectType.class.php
files/lib/system/cache/runtime/ConversationRuntimeCache.class.php
files/lib/system/cache/runtime/UserConversationRuntimeCache.class.php
files/lib/system/clipboard/action/ConversationClipboardAction.class.php
files/lib/system/conversation/ConversationHandler.class.php
files/lib/system/event/listener/ConversationPruneIpAddressesCronjobListener.class.php
files/lib/system/event/listener/ConversationUserActionRenameListener.class.php
files/lib/system/event/listener/ConversationUserMergeListener.class.php
files/lib/system/event/listener/UserGroupAddCanBeAddedAsConversationParticipantListener.class.php
files/lib/system/importer/ConversationAttachmentImporter.class.php
files/lib/system/importer/ConversationImporter.class.php
files/lib/system/importer/ConversationLabelImporter.class.php
files/lib/system/importer/ConversationMessageImporter.class.php
files/lib/system/importer/ConversationUserImporter.class.php
files/lib/system/log/modification/ConversationModificationLogHandler.class.php
files/lib/system/message/quote/ConversationMessageQuoteHandler.class.php
files/lib/system/moderation/queue/report/ConversationMessageModerationQueueReportHandler.class.php
files/lib/system/page/handler/ConversationListPageHandler.class.php
files/lib/system/page/handler/DefaultConversationRelatedPageHandler.class.php
files/lib/system/page/handler/TConversationOnlineLocationPageHandler.class.php
files/lib/system/search/ConversationMessageSearch.class.php
files/lib/system/stat/ConversationMessageStatDailyHandler.class.php
files/lib/system/stat/ConversationStatDailyHandler.class.php
files/lib/system/user/content/provider/ConversationMessageUserContentProvider.class.php
files/lib/system/user/content/provider/ConversationUserContentProvider.class.php
files/lib/system/user/notification/event/ConversationMessageUserNotificationEvent.class.php
files/lib/system/user/notification/event/ConversationUserNotificationEvent.class.php
files/lib/system/user/notification/event/TTestableConversationRelatedUserNotificationEvent.class.php
files/lib/system/user/notification/object/ConversationMessageUserNotificationObject.class.php
files/lib/system/user/notification/object/ConversationUserNotificationObject.class.php
files/lib/system/user/notification/object/type/ConversationMessageNotificationObjectType.class.php
files/lib/system/user/notification/object/type/ConversationNotificationObjectType.class.php
files/lib/system/worker/ConversationMessageRebuildDataWorker.class.php
files/lib/system/worker/ConversationMessageSearchIndexRebuildDataWorker.class.php
files/lib/system/worker/ConversationRebuildDataWorker.class.php
files/style/conversation.scss
language/de.xml
language/en.xml
objectType.xml
package-lock.json
package.json
package.xml
templateDelete.xml
templateListener.xml
templates/__mobileMenuConversation.tpl [deleted file]
templates/__searchAreaConversationSettings.tpl
templates/__userInformationStartConversation.tpl
templates/__userPanelConversationDropdown.tpl
templates/conversation.tpl
templates/conversationAdd.tpl
templates/conversationAddParticipants.tpl
templates/conversationLabelAssignment.tpl
templates/conversationLabelManagement.tpl
templates/conversationLeave.tpl
templates/conversationList.tpl
templates/conversationListUserPanel.tpl [deleted file]
templates/conversationMessageInlineEditor.tpl
templates/conversationMessageList.tpl
templates/conversationMessageListLog.tpl
templates/conversationMessagePreview.tpl
templates/conversationQuickReply.tpl
templates/email_notification_conversation.tpl
templates/email_notification_conversationMessage.tpl
templates/moderationConversationMessage.tpl
templates/searchConversationMessage.tpl
ts/WoltLabSuite/Core/Conversation/Ui/MarkAllAsRead.ts [new file with mode: 0644]
ts/WoltLabSuite/Core/Conversation/Ui/MarkAsRead.ts [new file with mode: 0644]
ts/WoltLabSuite/Core/Conversation/Ui/Message/Quote.ts
ts/WoltLabSuite/Core/Conversation/Ui/Object/Action/RemoveParticipant.ts
ts/WoltLabSuite/Core/Conversation/Ui/Participant/Add.ts
ts/WoltLabSuite/Core/Conversation/Ui/Subject/Editor.ts
ts/WoltLabSuite/Core/Conversation/Ui/User/Menu/Data/Conversation.ts
tsconfig.json

index d3788d0a4ea542d7316674d39d9ee8eac121f43e..2cfdd1b7e488bf2c4fbdb90057d13ab457e7a398 100644 (file)
@@ -15,14 +15,14 @@ jobs:
     runs-on: ubuntu-latest
     steps:
     - uses: actions/checkout@v4
-    - name: phpcs
-      uses: chekalsky/phpcs-action@e269c2f264f400adcda7c6b24c8550302350d495
     - name: Setup PHP with tools
       uses: shivammathur/setup-php@v2
       with:
-        php-version: '8.0'
+        php-version: '8.1'
         extensions: ctype, dom, exif, gd, gmp, hash, intl, json, libxml, mbstring, opcache, pcre, pdo, pdo_mysql, zlib
-        tools: php-cs-fixer
+        tools: cs2pr, phpcs, php-cs-fixer
+    - name: phpcs
+      run: phpcs -n -q --report=checkstyle | cs2pr
     - name: php-cs-fixer
       run: php-cs-fixer fix --dry-run --diff
   ts:
diff --git a/.github/workflows/d-ts.yml b/.github/workflows/d-ts.yml
new file mode 100644 (file)
index 0000000..2109cf1
--- /dev/null
@@ -0,0 +1,60 @@
+name: d.ts Exporter
+
+on:
+  workflow_dispatch:
+  schedule:
+  - cron: '37 15 * * 4'
+
+jobs:
+  export:
+    name: "Export (${{ matrix.branch }})"
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        branch:
+        - '6.0'
+        - 'master'
+    steps:
+    - uses: actions/checkout@v4
+      with:
+        ref: ${{ matrix.branch }}
+    - name: Determine commit
+      id: determine-commit
+      run: |
+        echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
+    - name: Set up node.js
+      uses: actions/setup-node@v3
+      with:
+        node-version: "18"
+        cache: "npm"
+    - run: npm install
+    - uses: actions/checkout@v4
+      with:
+        repository: WoltLab/d.ts
+        ssh-key: ${{ secrets.WOLTLAB_D_TS_DEPLOY_KEY }}
+        path: d.ts
+        ref: ${{ matrix.branch }}
+    - run: npx tsc --declaration --emitDeclarationOnly --outdir ./d.ts/
+    - name: Prepare git
+      run: |
+        git config --global user.name "WoltLab GmbH"
+        git config --global user.email "woltlab@woltlab.com"
+    - name: Push the update
+      run: |
+        set -x
+        cd d.ts/
+        git add .
+
+        if git diff --cached --quiet; then
+          exit 0
+        fi
+
+        git commit -m "Update ${{ github.repository }} definitions
+
+        Generated using:
+
+            npx tsc --declaration --emitDeclarationOnly --outdir ./d.ts/
+
+        from ${{ github.repository }}@${{ steps.determine-commit.outputs.sha }}"
+        git push
index 95fd0c9f2fb5252be161d315de1a46b74ef5ef4e..d80af02d711809ed53c57bf88838f92e5dd02563 100644 (file)
@@ -7,6 +7,7 @@ on:
     - "5.3"
     - "5.4"
     - "5.5"
+    - "6.0"
     - master
   pull_request:
 
index 64c79eaa535194293970f756dd968da1d6367c43..ebe58e621df7b8f55edb71dd12c2f05484b3acd1 100644 (file)
@@ -7,8 +7,13 @@ on:
     - "5.3"
     - "5.4"
     - "5.5"
+    - "6.0"
     - master
+    paths:
+    - '*.php'
   pull_request:
+    paths:
+    - '*.php'
 
 permissions:
   contents: read
@@ -21,11 +26,9 @@ jobs:
       fail-fast: false
       matrix:
         php:
-        - '7.2'
-        - '7.3'
-        - '7.4'
-        - '8.0'
         - '8.1'
+        - '8.2'
+        - '8.3'
     steps:
     - name: Set up PHP
       uses: shivammathur/setup-php@v2
index ea8a8e2e248a0fbc450f7c23eabdb03af28b9e08..3a2b63d86b1931a787519235191ed04392f4ddcf 100644 (file)
@@ -5,6 +5,7 @@ on:
     branches:
     - "5.4"
     - "5.5"
+    - "6.0"
     - master
   pull_request:
 
index 0e683164c4461382aabd37ed79a83ee378bd32ed..60d7da8b007a90ea716844c2b5aaf33f32b138a2 100644 (file)
@@ -6,8 +6,8 @@ $finder = PhpCsFixer\Finder::create()
 return (new PhpCsFixer\Config())
     ->setRiskyAllowed(true)
     ->setRules([
-        '@PSR1' => true,
-        '@PSR2' => true,
+        '@PER-CS2.0' => true,
+        'single_line_empty_body' => false,
 
         'array_push' => true,
         'backtick_to_shell_exec' => true,
@@ -25,23 +25,18 @@ return (new PhpCsFixer\Config())
 
         'non_printable_character' => ['use_escape_sequences_in_strings' => true],
 
-        'lowercase_static_reference' => true,
         'magic_constant_casing' => true,
         'magic_method_casing' => true,
         'native_function_casing' => true,
         'native_function_type_declaration_casing' => true,
 
         'cast_spaces' => ['space' => 'none'],
-        'lowercase_cast' => true,
         'no_unset_cast' => true,
-        'short_scalar_cast' => true,
 
         'class_attributes_separation' => true,
-        'no_blank_lines_after_class_opening' => true,
         'no_null_property_initialization' => true,
         'self_accessor' => true,
         'single_class_element_per_statement' => true,
-        'single_trait_insert_per_statement' => true,
 
         'no_empty_comment' => true,
         'single_line_comment_style' => ['comment_types' => ['hash']],
@@ -60,15 +55,12 @@ return (new PhpCsFixer\Config())
         'native_function_invocation' => ['include' => ['@internal']],
         'no_unreachable_default_argument_value' => true,
         'nullable_type_declaration_for_default_null_value' => true,
-        'return_type_declaration' => true,
         'static_lambda' => true,
 
         'fully_qualified_strict_types' => true,
-        'no_leading_import_slash' => true,
         'no_unused_imports' => true,
         'ordered_imports' => true,
 
-        'declare_equal_normalize' => true,
         'dir_constant' => true,
         'explicit_indirect_variable' => true,
         'function_to_constant' => true,
@@ -79,7 +71,6 @@ return (new PhpCsFixer\Config())
 
         'clean_namespace' => true,
         'no_leading_namespace_whitespace' => true,
-        'single_blank_line_before_namespace' => true,
 
         'no_homoglyph_names' => true,
 
@@ -91,7 +82,6 @@ return (new PhpCsFixer\Config())
         'operator_linebreak' => true,
         'standardize_increment' => true,
         'standardize_not_equals' => true,
-        'ternary_operator_spaces' => true,
         'ternary_to_elvis_operator' => true,
         'ternary_to_null_coalescing' => true,
         'unary_operator_spaces' => true,
@@ -112,7 +102,6 @@ return (new PhpCsFixer\Config())
 
         'array_indentation' => true,
         'blank_line_before_statement' => ['statements' => ['return', 'exit']],
-        'compact_nullable_typehint' => true,
         'method_chaining_indentation' => true,
         'no_extra_blank_lines' => ['tokens' => ['case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'switch', 'throw', 'use']],
         'no_spaces_around_offset' => true,
index 52e8202fe279642a7decddde57d3f349c11ecd47..c721282fb692ddc880a55f2fa5203ad1f42ead3a 100644 (file)
@@ -1,5 +1,8 @@
 <?xml version="1.0"?>
-<ruleset>
+<ruleset
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/squizlabs/PHP_CodeSniffer/master/phpcs.xsd"
+>
        <file>files/</file>
        <exclude-pattern>*/vendor/*</exclude-pattern>
        <arg name="extensions" value="php" />
index 89aa061cc86dfd3532a88f167bbc383ec52bde83..2be00043cd62a2a48025f5911fad64a34cd153da 100644 (file)
@@ -1,12 +1,15 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/2019/fileDelete.xsd">
        <delete>
+               <file>acp/database/update_com.woltlab.wcf.conversation_5.5_step1.php</file>
+               <file>acp/database/update_com.woltlab.wcf.conversation_5.5_step2.php</file>
                <file>acp/install_com.woltlab.wcf.conversation.php</file>
                <file>acp/install_com.woltlab.wcf.conversation_2.0.0.php</file>
                <file>acp/update_com.woltlab.wcf.conversation_3.0_dropColumns.php</file>
                <file>acp/update_com.woltlab.wcf.conversation_3.1_addColumn.php</file>
                <file>acp/update_com.woltlab.wcf.conversation_5.2.php</file>
                <file>acp/update_com.woltlab.wcf.conversation_5.4_deleteLanguageItems.php</file>
+               <file>acp/update_com.woltlab.wcf.conversation_5.5_cleanup_orphaned_attachments.php</file>
                <file>js/WoltLab/Conversation/UI/Participant/Add.js</file>
                <file>js/WoltLab/Conversation/Ui/Participant/Add.js</file>
                <file>js/require.build.min.js</file>
diff --git a/files/acp/database/update_com.woltlab.wcf.conversation_5.5_step1.php b/files/acp/database/update_com.woltlab.wcf.conversation_5.5_step1.php
deleted file mode 100644 (file)
index 650db8d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php
-
-/**
- * @author  Tim Duesterhus
- * @copyright   2001-2020 WoltLab GmbH
- * @license WoltLab License <http://www.woltlab.com/license-agreement.html>
- */
-
-// Reuse the install script to create the indices with the correct names.
-
-return require(__DIR__ . '/install_com.woltlab.wcf.conversation.php');
diff --git a/files/acp/database/update_com.woltlab.wcf.conversation_5.5_step2.php b/files/acp/database/update_com.woltlab.wcf.conversation_5.5_step2.php
deleted file mode 100644 (file)
index 3ecc7ec..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-/**
- * @author  Tim Duesterhus
- * @copyright   2001-2021 WoltLab GmbH
- * @license WoltLab License <http://www.woltlab.com/license-agreement.html>
- */
-
-use wcf\system\database\table\index\DatabaseTableIndex;
-use wcf\system\database\table\index\DatabaseTablePrimaryIndex;
-use wcf\system\database\table\PartialDatabaseTable;
-
-// 1) Generate a blueprint to fill in the generated index names.
-
-$blueprint = [
-    PartialDatabaseTable::create('wcf1_conversation')
-        ->indices([
-            // DatabaseTablePrimaryIndex::create()
-            //    ->columns(['conversationID']),
-            DatabaseTableIndex::create()
-                ->columns(['userID', 'isDraft']),
-        ]),
-    PartialDatabaseTable::create('wcf1_conversation_to_user')
-        ->indices([
-            DatabaseTableIndex::create()
-                ->columns(['participantID', 'conversationID'])
-                ->type(DatabaseTableIndex::UNIQUE_TYPE),
-            // DatabaseTableIndex::create()
-            //    ->columns(['participantID', 'hideConversation']),
-        ]),
-    PartialDatabaseTable::create('wcf1_conversation_message')
-        ->indices([
-            // DatabaseTablePrimaryIndex::create()
-            //    ->columns(['messageID']),
-            DatabaseTableIndex::create()
-                ->columns(['conversationID', 'userID']),
-            DatabaseTableIndex::create()
-                ->columns(['ipAddress']),
-        ]),
-    PartialDatabaseTable::create('wcf1_conversation_label')
-        ->indices([
-            // DatabaseTablePrimaryIndex::create()
-            //    ->columns(['labelID']),
-        ]),
-    PartialDatabaseTable::create('wcf1_conversation_label_to_object')
-        ->indices([
-            DatabaseTableIndex::create()
-                ->columns(['labelID', 'conversationID'])
-                ->type(DatabaseTableIndex::UNIQUE_TYPE),
-        ]),
-];
-
-// 2) Use this blueprint to recreate the index objects with ->generatedName() set to false.
-// Simply dropping the indices with ->generatedName() set to true does not work, because it will
-// also remove named indices as the fact that a name was generated does not persist to the database.
-
-$data = [];
-foreach ($blueprint as $blueprintTable) {
-    $data[] = PartialDatabaseTable::create($blueprintTable->getName())
-        ->indices(\array_map(static function ($index) {
-            \assert($index instanceof DatabaseTableIndex);
-
-            return DatabaseTableIndex::create($index->getName())
-                ->columns($index->getColumns())
-                ->type($index->getType())
-                ->drop();
-        }, $blueprintTable->getIndices()));
-}
-
-return $data;
diff --git a/files/acp/update_com.woltlab.wcf.conversation_5.5_cleanup_orphaned_attachments.php b/files/acp/update_com.woltlab.wcf.conversation_5.5_cleanup_orphaned_attachments.php
deleted file mode 100644 (file)
index 7dc5759..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-/**
- * Deletes orphaned attachments.
- *
- * @author  Tim Duesterhus
- * @copyright   2001-2022 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core
- */
-
-use wcf\data\attachment\AttachmentAction;
-use wcf\data\object\type\ObjectTypeCache;
-use wcf\system\package\SplitNodeException;
-use wcf\system\WCF;
-
-$objectType = ObjectTypeCache::getInstance()
-    ->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'com.woltlab.wcf.conversation.message');
-
-$sql = "SELECT  attachmentID
-        FROM    wcf1_attachment
-        WHERE   objectTypeID = ?
-            AND objectID NOT IN (
-                SELECT  messageID
-                FROM    wcf1_conversation_message
-            )";
-$statement = WCF::getDB()->prepare($sql, 100);
-$statement->execute([$objectType->objectTypeID]);
-$attachmentIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
-
-if (empty($attachmentIDs)) {
-    return;
-}
-
-(new AttachmentAction($attachmentIDs, 'delete'))->executeAction();
-
-// If we reached this location we processed at least one attachment.
-// If this was the final attachment the next iteration will abort this
-// script early, thus not splitting the node.
-throw new SplitNodeException();
index deba6192193a6f874a82f02f92b0ca56e12dca66..78c989d5be0d1389914bc84f0c993f7cde7d5f12 100644 (file)
@@ -146,7 +146,11 @@ WCF.Conversation.EditorHandler = Class.extend({
                
                switch (key) {
                        case 'close':
-                               $('<li><span class="icon icon16 fa-lock jsTooltip jsIconLock" title="' + WCF.Language.get('wcf.global.state.closed') + '" /></li>').prependTo($conversation.find('.statusIcons'));
+                               $(`<li>
+                                       <span class="jsTooltip jsIconLock" title="${WCF.Language.get('wcf.global.state.closed')}">
+                                               <fa-icon size="16" name="lock"></fa-icon>
+                                       </span>
+                               </li>`).prependTo($conversation.find('.statusIcons'));
                                
                                this._attributes[conversationID].isClosed = 1;
                        break;
@@ -245,7 +249,10 @@ WCF.Conversation.EditorHandlerConversation = WCF.Conversation.EditorHandler.exte
                
                switch (key) {
                        case 'close':
-                               $('<li><span class="icon icon16 fa-lock jsIconLock" /> ' + WCF.Language.get('wcf.global.state.closed') + '</li>').appendTo(container);
+                               $(`<li>
+                                       <fa-icon size="16" name="lock"></fa-icon>
+                                       ${WCF.Language.get('wcf.global.state.closed')}
+                               </li>`).appendTo(container);
                                
                                this._attributes[conversationID].isClosed = 1;
                        break;
@@ -259,7 +266,10 @@ WCF.Conversation.EditorHandlerConversation = WCF.Conversation.EditorHandler.exte
                                        var availableLabels = this.getAvailableLabels();
                                        
                                        if (!labelList.length) {
-                                               labelList = $('<li><span class="icon icon16 fa-tags"></span> <ul class="labelList"></ul></li>').prependTo(container);
+                                               labelList = $(`<li>
+                                                       <fa-icon size="16" name="tags"></fa-icon>
+                                                       <ul class="labelList"></ul>
+                                               </li>`).prependTo(container);
                                                labelList = labelList.children('ul');
                                        }
                                        
@@ -681,59 +691,6 @@ WCF.Conversation.Leave = Class.extend({
        }
 });
 
-/**
- * Provides methods to remove participants from conversations.
- * 
- * @see        WCF.Action.Delete
- * @deprecated 5.4 Handled via `WoltLabSuite/Core/Ui/Object/Action`.
- */
-WCF.Conversation.RemoveParticipant = WCF.Action.Delete.extend({
-       /**
-        * conversation id
-        * @var integer
-        */
-       _conversationID: 0,
-       
-       /**
-        * @see WCF.Action.Delete.init()
-        */
-       init: function(conversationID) {
-               this._conversationID = conversationID;
-               this._super('wcf\\data\\conversation\\ConversationAction', '.jsParticipant');
-       },
-       
-       /**
-        * @see WCF.Action.Delete._sendRequest()
-        */
-       _sendRequest: function(object) {
-               this.proxy.setOption('data', {
-                       actionName: 'removeParticipant',
-                       className: this._className,
-                       objectIDs: [ this._conversationID ],
-                       parameters: {
-                               userID: $(object).data('objectID')
-                       }
-               });
-               
-               this.proxy.sendRequest();
-       },
-       
-       /**
-        * @see WCF.Action.Delete._success()
-        */
-       _success: function(data, textStatus, jqXHR) {
-               var $userID = data.returnValues.userID;
-               
-               for (var $index in this._containers) {
-                       var $container = $('#' + this._containers[$index]);
-                       if ($container.find('.jsDeleteButton').data('objectID') == $userID) {
-                               $container.find('.userLink').addClass('conversationLeft');
-                               $container.find('.jsDeleteButton').remove();
-                       }
-               }
-       }
-});
-
 /**
  * Namespace for label-related classes.
  */
@@ -1183,169 +1140,6 @@ WCF.Conversation.Label.Manager = Class.extend({
        }
 });
 
-/**
- * Provides a flexible conversation preview.
- * 
- * @see        WCF.Popover
- * @deprecated  5.3     handled via `WoltLabSuite/Core/Controller/Popover`
- */
-WCF.Conversation.Preview = WCF.Popover.extend({
-       /**
-        * action proxy
-        * @var WCF.Action.Proxy
-        */
-       _proxy: null,
-       
-       /**
-        * @see WCF.Popover.init()
-        */
-       init: function() {
-               this._super('.conversationLink');
-               
-               // init proxy
-               this._proxy = new WCF.Action.Proxy({
-                       showLoadingOverlay: false
-               });
-               
-               WCF.DOMNodeInsertedHandler.addCallback('WCF.Conversation.Preview', $.proxy(this._initContainers, this));
-       },
-       
-       /**
-        * @see WCF.Popover._loadContent()
-        */
-       _loadContent: function() {
-               var $link = $('#' + this._activeElementID);
-               
-               this._proxy.setOption('data', {
-                       actionName: 'getMessagePreview',
-                       className: 'wcf\\data\\conversation\\ConversationAction',
-                       objectIDs: [ $link.data('conversationID') ]
-               });
-               
-               var $elementID = this._activeElementID;
-               var self = this;
-               this._proxy.setOption('success', function(data, textStatus, jqXHR) {
-                       self._insertContent($elementID, data.returnValues.template, true);
-               });
-               this._proxy.sendRequest();
-       }
-});
-
-/**
- * Marks one conversation as read.
- */
-WCF.Conversation.MarkAsRead = Class.extend({
-       /**
-        * action proxy
-        * @var WCF.Action.Proxy
-        */
-       _proxy: null,
-       
-       /**
-        * Initializes the mark as read for conversations.
-        */
-       init: function() {
-               this._proxy = new WCF.Action.Proxy({
-                       success: $.proxy(this._success, this)
-               });
-               
-               $(document).on('dblclick', '.conversationList .new .columnAvatar', $.proxy(this._dblclick, this));
-       },
-       
-       /**
-        * Handles double clicks on avatar.
-        * 
-        * @param       object          event
-        */
-       _dblclick: function(event) {
-               this._proxy.setOption('data', {
-                       actionName: 'markAsRead',
-                       className: 'wcf\\data\\conversation\\ConversationAction',
-                       objectIDs: [ $(event.currentTarget).parents('ol:eq(0)').data('conversationID') ]
-               });
-               this._proxy.sendRequest();
-       },
-       
-       /**
-        * Handles successful AJAX requests.
-        * 
-        * @param       object          data
-        * @param       string          textStatus
-        * @param       jQuery          jqXHR
-        */
-       _success: function(data, textStatus, jqXHR) {
-               $('.conversationList .new').each(function(index, element) {
-                       var $element = $(element);
-                       if (WCF.inArray($element.data('conversationID'), data.objectIDs)) {
-                               // remove new class
-                               $element.removeClass('new');
-                               
-                               // hide arrows
-                               $element.find('.firstNewPost').parent().remove();
-                               
-                               // remove event
-                               $element.find('.columnAvatar').off('dblclick');
-                       }
-               });
-       }
-});
-
-/**
- * Marks all conversations as read.
- */
-WCF.Conversation.MarkAllAsRead = Class.extend({
-       /**
-        * action proxy
-        * @var WCF.Action.Proxy
-        */
-       _proxy: null,
-       
-       /**
-        * Initializes the WCF.Conversation.MarkAllAsRead class.
-        */
-       init: function() {
-               this._proxy = new WCF.Action.Proxy({
-                       success: $.proxy(this._success, this)
-               });
-               
-               $('.markAllAsReadButton').click($.proxy(this._click, this));
-       },
-       
-       /**
-        * Handles clicks.
-        * 
-        * @param       object          event
-        */
-       _click: function(event) {
-               event.preventDefault();
-               
-               this._proxy.setOption('data', {
-                       actionName: 'markAllAsRead',
-                       className: 'wcf\\data\\conversation\\ConversationAction'
-               });
-               this._proxy.sendRequest();
-       },
-       
-       /**
-        * Marks all conversations as read.
-        * 
-        * @param       object          data
-        * @param       string          textStatus
-        * @param       jQuery          jqXHR
-        */
-       _success: function(data, textStatus, jqXHR) {
-               // fix dropdown
-               WCF.System.Event.fireEvent('com.woltlab.wcf.conversation.userPanel', 'reset');
-               
-               // fix conversation list
-               var $conversationList = $('.conversationList');
-               $conversationList.find('.new').removeClass('new');
-               $conversationList.find('.columnAvatar').off('dblclick');
-
-               new WCF.System.Notification().show();
-       }
-});
-
 /**
  * Namespace for conversation messages.
  */
@@ -1371,17 +1165,3 @@ WCF.Conversation.Message.InlineEditor = WCF.Message.InlineEditor.extend({
                return 'wcf\\data\\conversation\\message\\ConversationMessageAction';
        }
 });
-
-/**
- * @deprecated 5.5, use `WoltLabSuite/Core/Conversation/Ui/Message/Quote` instead
- */
-WCF.Conversation.Message.QuoteHandler = WCF.Message.Quote.Handler.extend({
-       /**
-        * @see WCF.Message.QuoteManager.init()
-        */
-       init: function(quoteManager) {
-               require(["WoltLabSuite/Core/Conversation/Ui/Message/Quote"], ({ UiConversationMessageQuote }) => {
-                       new UiConversationMessageQuote(quoteManager);
-               });
-       }
-});
index c9611599753df6f7ec8ac83c95bd2fd606b8de5d..7c3254f0e0ed50a4714b595ca5a2c690b2b63654 100755 (executable)
@@ -1 +1 @@
-WCF.Conversation={},WCF.Conversation.EditorHandler=Class.extend({_attributes:{},_conversations:{},_permissions:{},init:function(availableLabels){this._conversations={};var self=this;$(".conversation").each((function(index,conversation){var $labelIDs,$conversation=$(conversation),$conversationID=$conversation.data("conversationID");self._conversations[$conversationID]||(self._conversations[$conversationID]=$conversation,$labelIDs=eval($conversation.data("labelIDs")),self._attributes[$conversationID]={isClosed:!!$conversation.data("isClosed"),labelIDs:$labelIDs},self._permissions[$conversationID]={canAddParticipants:!!$conversation.data("canAddParticipants"),canCloseConversation:!!$conversation.data("canCloseConversation")})}))},getPermission:function(e,a){return void 0!==this._permissions[e][a]&&!!this._permissions[e][a]},getValue:function(e,a){switch(a){case"labelIDs":return void 0===this._attributes[e].labelIDs&&(this._attributes[e].labelIDs=[]),this._attributes[e].labelIDs;case"isClosed":return!!this._attributes[e].isClosed}},countAvailableLabels:function(){return this.getAvailableLabels().length},getAvailableLabels:function(){var e=[];return WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu").children("li").each((function(a,t){var n,s=$(t);if(s.hasClass("dropdownDivider"))return!1;n=s.find("span"),e.push({cssClassName:n.data("cssClassName"),labelID:n.data("labelID"),label:n.text()})})),e},update:function(e,a,t){var n,s,i,o,l,r;if(this._conversations[e]){switch(n=this._conversations[e],a){case"close":$('<li><span class="icon icon16 fa-lock jsTooltip jsIconLock" title="'+WCF.Language.get("wcf.global.state.closed")+'" /></li>').prependTo(n.find(".statusIcons")),this._attributes[e].isClosed=1;break;case"labelIDs":if(s={},WCF.Dropdown.getDropdownMenu("conversationLabelFilter").find("li > a > span").each((function(e,a){var t=$(a);s[t.data("labelID")]={cssClassName:t.data("cssClassName"),label:t.text(),url:t.parent().attr("href")}})),i=n.find(".columnSubject > .labelList"),t.length)for(i.length||(i=$('<ul class="labelList" />').prependTo(n.find(".columnSubject"))),i.empty(),o=0,l=t.length;o<l;o++)r=s[t[o]],$('<li><a href="'+r.url+'" class="badge label'+(r.cssClassName?" "+r.cssClassName:"")+'">'+WCF.String.escapeHTML(r.label)+"</a></li>").appendTo(i);else i.length&&i.remove();break;case"open":n.find(".statusIcons li").each((function(e,a){var t=$(a);if(t.children("span.jsIconLock").length)return t.remove(),!1})),this._attributes[e].isClosed=0}WCF.Clipboard.reload()}else console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'")}}),WCF.Conversation.EditorHandlerConversation=WCF.Conversation.EditorHandler.extend({_availableLabels:null,init:function(e){this._availableLabels=e||[],this._super()},getAvailableLabels:function(){return this._availableLabels},update:function(e,a,t){var n,s,i,o;if(this._conversations[e])switch(n=$(".contentHeaderTitle > .contentHeaderMetaData"),a){case"close":$('<li><span class="icon icon16 fa-lock jsIconLock" /> '+WCF.Language.get("wcf.global.state.closed")+"</li>").appendTo(n),this._attributes[e].isClosed=1;break;case"labelIDs":s=n.find(".labelList"),t.length?(i=this.getAvailableLabels(),s.length||(s=(s=$('<li><span class="icon icon16 fa-tags"></span> <ul class="labelList"></ul></li>').prependTo(n)).children("ul")),o="",t.forEach((function(e){i.forEach((function(a){a.labelID==e&&(o+='<li><span class="label badge'+(a.cssClassName?" "+a.cssClassName:"")+'">'+a.label+"</span></li>")}))})),s[0].innerHTML=o):s.parent().remove();break;case"open":n.find(".jsIconLock").parent().remove(),this._attributes[e].isClosed=0}else console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'")}}),WCF.Conversation.Clipboard=Class.extend({_editorHandler:null,init:function(e){this._editorHandler=e,WCF.System.Event.addListener("com.woltlab.wcf.clipboard","com.woltlab.wcf.conversation.conversation",function(e){null===e.responseData?this._execute(e.data.actionName,e.data.parameters):this._evaluateResponse(e.data.actionName,e.responseData)}.bind(this))},_execute:function(e,a){"com.woltlab.wcf.conversation.conversation.assignLabel"===e&&new WCF.Conversation.Label.Editor(this._editorHandler,null,a.objectIDs)},_evaluateResponse:function(e,a){var t,n;switch(e){case"com.woltlab.wcf.conversation.conversation.leave":case"com.woltlab.wcf.conversation.conversation.leavePermanently":case"com.woltlab.wcf.conversation.conversation.markAsRead":case"com.woltlab.wcf.conversation.conversation.restore":window.location.reload();break;case"com.woltlab.wcf.conversation.conversation.close":case"com.woltlab.wcf.conversation.conversation.open":for(t in a.returnValues.conversationData)a.returnValues.conversationData.hasOwnProperty(t)&&(n=a.returnValues.conversationData[t],this._editorHandler.update(t,n.isClosed?"close":"open",n))}}}),WCF.Conversation.InlineEditor=WCF.InlineEditor.extend({_editorHandler:null,_environment:"conversation",_setOptions:function(){this._options=[{label:WCF.Language.get("wcf.conversation.edit.subject"),optionName:"editSubject"},{label:WCF.Language.get("wcf.conversation.edit.close"),optionName:"close"},{label:WCF.Language.get("wcf.conversation.edit.open"),optionName:"open"},{label:WCF.Language.get("wcf.conversation.edit.assignLabel"),optionName:"assignLabel"},{optionName:"divider"},{label:WCF.Language.get("wcf.conversation.edit.addParticipants"),optionName:"addParticipants"},{label:WCF.Language.get("wcf.conversation.edit.leave"),optionName:"leave"},{label:WCF.Language.get("wcf.global.button.edit"),optionName:"edit",isQuickOption:!0}]},setEditorHandler:function(e,a){this._editorHandler=e,this._environment="list"==a?"list":"conversation"},_getTriggerElement:function(e){return e.find(".jsConversationInlineEditor")},_validate:function(e,a){var t=$("#"+e).data("conversationID");switch(a){case"addParticipants":return this._editorHandler.getPermission(t,"canAddParticipants");case"assignLabel":return!!this._editorHandler.countAvailableLabels();case"editSubject":return!!this._editorHandler.getPermission(t,"canCloseConversation");case"close":case"open":return!!this._editorHandler.getPermission(t,"canCloseConversation")&&("close"===a?!this._editorHandler.getValue(t,"isClosed"):this._editorHandler.getValue(t,"isClosed"));case"leave":return!0;case"edit":return!!$("#"+e).data("isDraft")}return!1},_execute:function(e,a){if(!this._validate(e,a))return!1;switch(a){case"addParticipants":require(["WoltLabSuite/Core/Conversation/Ui/Participant/Add"],(function(a){new a(elData(elById(e),"conversation-id"))}));break;case"assignLabel":new WCF.Conversation.Label.Editor(this._editorHandler,e);break;case"editSubject":require(["WoltLabSuite/Core/Conversation/Ui/Subject/Editor"],(function(a){a.beginEdit(elData(elById(e),"conversation-id"))}));break;case"close":case"open":this._updateConversation(e,a,{isClosed:"close"===a?1:0});break;case"leave":new WCF.Conversation.Leave([$("#"+e).data("conversationID")],this._environment);break;case"edit":window.location=this._getTriggerElement($("#"+e)).prop("href")}},_updateConversation:function(e,a,t){var n=this._elements[e].data("conversationID");switch(a){case"close":case"editSubject":case"open":this._updateData.push({elementID:e,optionName:a,data:t}),this._proxy.setOption("data",{actionName:a,className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[n]}),this._proxy.sendRequest()}},_updateState:function(){var e,a,t,n;for(e=0,a=this._updateData.length;e<a;e++)switch(t=this._updateData[e],n=this._elements[t.elementID].data("conversationID"),t.optionName){case"close":case"editSubject":case"open":this._editorHandler.update(n,t.optionName,t.data)}}}),WCF.Conversation.Leave=Class.extend({_conversationIDs:[],_dialog:null,_environment:"",_proxy:null,init:function(e,a){this._conversationIDs=e,this._dialog=null,this._environment=a,this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLeaveForm",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs}),this._proxy.sendRequest()},_success:function(e,a,t){switch(e.returnValues.actionName){case"getLeaveForm":this._showDialog(e);break;case"hideConversation":"conversation"===this._environment?window.location=e.returnValues.redirectURL:window.location.reload()}},_showDialog:function(e){null===this._dialog&&(this._dialog=$("#leaveDialog"),this._dialog.length||(this._dialog=$('<div id="leaveDialog" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.leave.title")}),this._dialog.wcfDialog("render"),this._dialog.find("#hideConversation").click($.proxy(this._click,this))},_click:function(){var e=this._dialog.find("input[type=radio]:checked");1===e.length&&(this._proxy.setOption("data",{actionName:"hideConversation",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs,parameters:{hideConversation:e.val()}}),this._proxy.sendRequest())}}),WCF.Conversation.RemoveParticipant=WCF.Action.Delete.extend({_conversationID:0,init:function(e){this._conversationID=e,this._super("wcf\\data\\conversation\\ConversationAction",".jsParticipant")},_sendRequest:function(e){this.proxy.setOption("data",{actionName:"removeParticipant",className:this._className,objectIDs:[this._conversationID],parameters:{userID:$(e).data("objectID")}}),this.proxy.sendRequest()},_success:function(e,a,t){var n,s,i=e.returnValues.userID;for(n in this._containers)(s=$("#"+this._containers[n])).find(".jsDeleteButton").data("objectID")==i&&(s.find(".userLink").addClass("conversationLeft"),s.find(".jsDeleteButton").remove())}}),WCF.Conversation.Label={},WCF.Conversation.Label.Editor=Class.extend({_conversationIDs:0,_dialog:null,_editorHandler:null,_notification:null,_proxy:null,init:function(e,a,t){this._conversationIDs=a?[$("#"+a).data("conversationID")]:t,this._dialog=null,this._editorHandler=e,this._notification=new WCF.System.Notification(WCF.Language.get("wcf.global.success.edit")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLabelForm",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs}}),this._proxy.sendRequest()},_success:function(e,a,t){switch(e.returnValues.actionName){case"assignLabel":this._assignLabels(e);break;case"getLabelForm":this._renderDialog(e)}},_renderDialog:function(e){null===this._dialog&&(this._dialog=$("#conversationLabelForm"),this._dialog.length||(this._dialog=$('<div id="conversationLabelForm" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.assignLabels")}),this._dialog.wcfDialog("render"),$("#assignLabels").click($.proxy(this._save,this))},_save:function(){var e=[];this._dialog.find("input").each((function(a,t){var n=$(t);n.is(":checked")&&e.push(n.data("labelID"))})),this._proxy.setOption("data",{actionName:"assignLabel",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs,labelIDs:e}}),this._proxy.sendRequest()},_assignLabels:function(e){for(var a=0,t=this._conversationIDs.length;a<t;a++)this._editorHandler.update(this._conversationIDs[a],"labelIDs",e.returnValues.labelIDs);this._dialog.wcfDialog("close"),this._notification.show()}}),WCF.Conversation.Label.Manager=Class.extend({_deletedLabelID:0,_dialog:null,_labels:null,_link:"",_notification:"",_proxy:null,_maxLabels:0,_labelCount:0,init:function(e){this._deletedLabelID=0,this._maxLabels=0,this._labelCount=0,this._link=e,this._labels=WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu"),$("#manageLabel").click($.proxy(this._click,this)),this._notification=new WCF.System.Notification(WCF.Language.get("wcf.conversation.label.management.addLabel.success")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)})},_click:function(){this._proxy.setOption("data",{actionName:"getLabelManagement",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_success:function(e,a,t){if(null===this._dialog&&(this._dialog=$('<div id="labelManagement" />').hide().appendTo(document.body)),e.returnValues&&e.returnValues.actionName)switch(e.returnValues.actionName){case"add":this._insertLabel(e);break;case"getLabelManagement":this._maxLabels=parseInt(e.returnValues.maxLabels),this._labelCount=parseInt(e.returnValues.labelCount),this._dialog.empty().html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.management")}),this._dialog.wcfDialog("render"),this._bindListener()}else if(this._deletedLabelID){var n=new RegExp("(\\?|&)labelID="+this._deletedLabelID);window.location=window.location.toString().replace(n,"")}else window.location.reload()},_insertLabel:function(e){var a=$('<li><a href="'+this._link+"&labelID="+e.returnValues.labelID+'"><span class="badge label'+(e.returnValues.cssClassName?" "+e.returnValues.cssClassName:"")+'">'+e.returnValues.label+"</span></a></li>");a.find("a > span").data("labelID",e.returnValues.labelID).data("cssClassName",e.returnValues.cssClassName),this._labels.append(a),this._notification.show(),this._labelCount++,this._labelCount>=this._maxLabels&&$("#conversationLabelManagementForm").hide()},_bindListener:function(){$("#labelName").on("keyup keydown keypress",$.proxy(this._updateLabels,this)),$.browser.mozilla&&$.browser.touch&&$("#labelName").on("input",$.proxy(this._updateLabels,this)),this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").hide(),this._dialog.wcfDialog("render")),$("#addLabel").disable().click($.proxy(this._addLabel,this)),$("#editLabel").disable(),this._dialog.find(".conversationLabelList a.label").click($.proxy(this._edit,this))},_edit:function(e){var a,t,n;this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").show(),this._dialog.wcfDialog("render")),a=$(e.currentTarget),t=WCF.Language.get("wcf.conversation.label.management.editLabel").replace(/#labelName#/,WCF.String.escapeHTML(a.text())),$("#conversationLabelManagementForm").data("labelID",a.data("labelID")).children(".sectionTitle").html(t),$("#labelName").val(a.text()).trigger("keyup"),n=a.data("cssClassName"),$("#labelManagementList input").each((function(e,a){var t=$(a);t.val()==n&&t.attr("checked","checked")})),$("#addLabel").hide(),$("#editLabel").show().click($.proxy(this._editLabel,this)),$("#deleteLabel").show().click($.proxy(this._deleteLabel,this))},_editLabel:function(){this._proxy.setOption("data",{actionName:"update",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")],parameters:{data:{cssClassName:$("#labelManagementList input:checked").val(),label:$("#labelName").val()}}}),this._proxy.sendRequest()},_deleteLabel:function(){var e=WCF.Language.get("wcf.conversation.label.management.deleteLabel.confirmMessage").replace(/#labelName#/,$("#labelName").val());WCF.System.Confirmation.show(e,$.proxy((function(e){"confirm"===e&&(this._proxy.setOption("data",{actionName:"delete",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")]}),this._proxy.sendRequest(),this._deletedLabelID=$("#conversationLabelManagementForm").data("labelID"))}),this),void 0,void 0,!0)},_updateLabels:function(){var e=$.trim($("#labelName").val());e?$("#addLabel, #editLabel").enable():($("#addLabel, #editLabel").disable(),e=WCF.Language.get("wcf.conversation.label.placeholder")),$("#labelManagementList").find("span.label").text(e)},_addLabel:function(){var e=$("#labelName").val(),a=$("#labelManagementList input:checked").val();this._proxy.setOption("data",{actionName:"add",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{data:{cssClassName:a,labelName:e}}}),this._proxy.sendRequest(),this._dialog.wcfDialog("close")}}),WCF.Conversation.Preview=WCF.Popover.extend({_proxy:null,init:function(){this._super(".conversationLink"),this._proxy=new WCF.Action.Proxy({showLoadingOverlay:!1}),WCF.DOMNodeInsertedHandler.addCallback("WCF.Conversation.Preview",$.proxy(this._initContainers,this))},_loadContent:function(){var e,a,t=$("#"+this._activeElementID);this._proxy.setOption("data",{actionName:"getMessagePreview",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[t.data("conversationID")]}),e=this._activeElementID,a=this,this._proxy.setOption("success",(function(t,n,s){a._insertContent(e,t.returnValues.template,!0)})),this._proxy.sendRequest()}}),WCF.Conversation.MarkAsRead=Class.extend({_proxy:null,init:function(){this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),$(document).on("dblclick",".conversationList .new .columnAvatar",$.proxy(this._dblclick,this))},_dblclick:function(e){this._proxy.setOption("data",{actionName:"markAsRead",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[$(e.currentTarget).parents("ol:eq(0)").data("conversationID")]}),this._proxy.sendRequest()},_success:function(e,a,t){$(".conversationList .new").each((function(a,t){var n=$(t);WCF.inArray(n.data("conversationID"),e.objectIDs)&&(n.removeClass("new"),n.find(".firstNewPost").parent().remove(),n.find(".columnAvatar").off("dblclick"))}))}}),WCF.Conversation.MarkAllAsRead=Class.extend({_proxy:null,init:function(){this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),$(".markAllAsReadButton").click($.proxy(this._click,this))},_click:function(e){e.preventDefault(),this._proxy.setOption("data",{actionName:"markAllAsRead",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_success:function(e,a,t){WCF.System.Event.fireEvent("com.woltlab.wcf.conversation.userPanel","reset");var n=$(".conversationList");n.find(".new").removeClass("new"),n.find(".columnAvatar").off("dblclick"),(new WCF.System.Notification).show()}}),WCF.Conversation.Message={},WCF.Conversation.Message.InlineEditor=WCF.Message.InlineEditor.extend({init:function(e,a){this._super(e,!0,a)},_getClassName:function(){return"wcf\\data\\conversation\\message\\ConversationMessageAction"}}),WCF.Conversation.Message.QuoteHandler=WCF.Message.Quote.Handler.extend({init:function(e){require(["WoltLabSuite/Core/Conversation/Ui/Message/Quote"],(({UiConversationMessageQuote:a})=>{new a(e)}))}});
\ No newline at end of file
+WCF.Conversation={},WCF.Conversation.EditorHandler=Class.extend({_attributes:{},_conversations:{},_permissions:{},init:function(availableLabels){this._conversations={};var self=this;$(".conversation").each((function(index,conversation){var $labelIDs,$conversation=$(conversation),$conversationID=$conversation.data("conversationID");self._conversations[$conversationID]||(self._conversations[$conversationID]=$conversation,$labelIDs=eval($conversation.data("labelIDs")),self._attributes[$conversationID]={isClosed:!!$conversation.data("isClosed"),labelIDs:$labelIDs},self._permissions[$conversationID]={canAddParticipants:!!$conversation.data("canAddParticipants"),canCloseConversation:!!$conversation.data("canCloseConversation")})}))},getPermission:function(e,a){return void 0!==this._permissions[e][a]&&!!this._permissions[e][a]},getValue:function(e,a){switch(a){case"labelIDs":return void 0===this._attributes[e].labelIDs&&(this._attributes[e].labelIDs=[]),this._attributes[e].labelIDs;case"isClosed":return!!this._attributes[e].isClosed}},countAvailableLabels:function(){return this.getAvailableLabels().length},getAvailableLabels:function(){var e=[];return WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu").children("li").each((function(a,t){var n,s=$(t);if(s.hasClass("dropdownDivider"))return!1;n=s.find("span"),e.push({cssClassName:n.data("cssClassName"),labelID:n.data("labelID"),label:n.text()})})),e},update:function(e,a,t){var n,s,i,o,l,r;if(this._conversations[e]){switch(n=this._conversations[e],a){case"close":$(`<li>\n\t\t\t\t\t<span class="jsTooltip jsIconLock" title="${WCF.Language.get("wcf.global.state.closed")}">\n\t\t\t\t\t\t<fa-icon size="16" name="lock"></fa-icon>\n\t\t\t\t\t</span>\n\t\t\t\t</li>`).prependTo(n.find(".statusIcons")),this._attributes[e].isClosed=1;break;case"labelIDs":if(s={},WCF.Dropdown.getDropdownMenu("conversationLabelFilter").find("li > a > span").each((function(e,a){var t=$(a);s[t.data("labelID")]={cssClassName:t.data("cssClassName"),label:t.text(),url:t.parent().attr("href")}})),i=n.find(".columnSubject > .labelList"),t.length)for(i.length||(i=$('<ul class="labelList" />').prependTo(n.find(".columnSubject"))),i.empty(),o=0,l=t.length;o<l;o++)r=s[t[o]],$('<li><a href="'+r.url+'" class="badge label'+(r.cssClassName?" "+r.cssClassName:"")+'">'+WCF.String.escapeHTML(r.label)+"</a></li>").appendTo(i);else i.length&&i.remove();break;case"open":n.find(".statusIcons li").each((function(e,a){var t=$(a);if(t.children("span.jsIconLock").length)return t.remove(),!1})),this._attributes[e].isClosed=0}WCF.Clipboard.reload()}else console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'")}}),WCF.Conversation.EditorHandlerConversation=WCF.Conversation.EditorHandler.extend({_availableLabels:null,init:function(e){this._availableLabels=e||[],this._super()},getAvailableLabels:function(){return this._availableLabels},update:function(e,a,t){var n,s,i,o;if(this._conversations[e])switch(n=$(".contentHeaderTitle > .contentHeaderMetaData"),a){case"close":$(`<li>\n\t\t\t\t\t<fa-icon size="16" name="lock"></fa-icon>\n\t\t\t\t\t${WCF.Language.get("wcf.global.state.closed")}\n\t\t\t\t</li>`).appendTo(n),this._attributes[e].isClosed=1;break;case"labelIDs":s=n.find(".labelList"),t.length?(i=this.getAvailableLabels(),s.length||(s=(s=$('<li>\n\t\t\t\t\t\t\t<fa-icon size="16" name="tags"></fa-icon>\n\t\t\t\t\t\t\t<ul class="labelList"></ul>\n\t\t\t\t\t\t</li>').prependTo(n)).children("ul")),o="",t.forEach((function(e){i.forEach((function(a){a.labelID==e&&(o+='<li><span class="label badge'+(a.cssClassName?" "+a.cssClassName:"")+'">'+a.label+"</span></li>")}))})),s[0].innerHTML=o):s.parent().remove();break;case"open":n.find(".jsIconLock").parent().remove(),this._attributes[e].isClosed=0}else console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'")}}),WCF.Conversation.Clipboard=Class.extend({_editorHandler:null,init:function(e){this._editorHandler=e,WCF.System.Event.addListener("com.woltlab.wcf.clipboard","com.woltlab.wcf.conversation.conversation",function(e){null===e.responseData?this._execute(e.data.actionName,e.data.parameters):this._evaluateResponse(e.data.actionName,e.responseData)}.bind(this))},_execute:function(e,a){"com.woltlab.wcf.conversation.conversation.assignLabel"===e&&new WCF.Conversation.Label.Editor(this._editorHandler,null,a.objectIDs)},_evaluateResponse:function(e,a){var t,n;switch(e){case"com.woltlab.wcf.conversation.conversation.leave":case"com.woltlab.wcf.conversation.conversation.leavePermanently":case"com.woltlab.wcf.conversation.conversation.markAsRead":case"com.woltlab.wcf.conversation.conversation.restore":window.location.reload();break;case"com.woltlab.wcf.conversation.conversation.close":case"com.woltlab.wcf.conversation.conversation.open":for(t in a.returnValues.conversationData)a.returnValues.conversationData.hasOwnProperty(t)&&(n=a.returnValues.conversationData[t],this._editorHandler.update(t,n.isClosed?"close":"open",n))}}}),WCF.Conversation.InlineEditor=WCF.InlineEditor.extend({_editorHandler:null,_environment:"conversation",_setOptions:function(){this._options=[{label:WCF.Language.get("wcf.conversation.edit.subject"),optionName:"editSubject"},{label:WCF.Language.get("wcf.conversation.edit.close"),optionName:"close"},{label:WCF.Language.get("wcf.conversation.edit.open"),optionName:"open"},{label:WCF.Language.get("wcf.conversation.edit.assignLabel"),optionName:"assignLabel"},{optionName:"divider"},{label:WCF.Language.get("wcf.conversation.edit.addParticipants"),optionName:"addParticipants"},{label:WCF.Language.get("wcf.conversation.edit.leave"),optionName:"leave"},{label:WCF.Language.get("wcf.global.button.edit"),optionName:"edit",isQuickOption:!0}]},setEditorHandler:function(e,a){this._editorHandler=e,this._environment="list"==a?"list":"conversation"},_getTriggerElement:function(e){return e.find(".jsConversationInlineEditor")},_validate:function(e,a){var t=$("#"+e).data("conversationID");switch(a){case"addParticipants":return this._editorHandler.getPermission(t,"canAddParticipants");case"assignLabel":return!!this._editorHandler.countAvailableLabels();case"editSubject":return!!this._editorHandler.getPermission(t,"canCloseConversation");case"close":case"open":return!!this._editorHandler.getPermission(t,"canCloseConversation")&&("close"===a?!this._editorHandler.getValue(t,"isClosed"):this._editorHandler.getValue(t,"isClosed"));case"leave":return!0;case"edit":return!!$("#"+e).data("isDraft")}return!1},_execute:function(e,a){if(!this._validate(e,a))return!1;switch(a){case"addParticipants":require(["WoltLabSuite/Core/Conversation/Ui/Participant/Add"],(function(a){new a(elData(elById(e),"conversation-id"))}));break;case"assignLabel":new WCF.Conversation.Label.Editor(this._editorHandler,e);break;case"editSubject":require(["WoltLabSuite/Core/Conversation/Ui/Subject/Editor"],(function(a){a.beginEdit(elData(elById(e),"conversation-id"))}));break;case"close":case"open":this._updateConversation(e,a,{isClosed:"close"===a?1:0});break;case"leave":new WCF.Conversation.Leave([$("#"+e).data("conversationID")],this._environment);break;case"edit":window.location=this._getTriggerElement($("#"+e)).prop("href")}},_updateConversation:function(e,a,t){var n=this._elements[e].data("conversationID");switch(a){case"close":case"editSubject":case"open":this._updateData.push({elementID:e,optionName:a,data:t}),this._proxy.setOption("data",{actionName:a,className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[n]}),this._proxy.sendRequest()}},_updateState:function(){var e,a,t,n;for(e=0,a=this._updateData.length;e<a;e++)switch(t=this._updateData[e],n=this._elements[t.elementID].data("conversationID"),t.optionName){case"close":case"editSubject":case"open":this._editorHandler.update(n,t.optionName,t.data)}}}),WCF.Conversation.Leave=Class.extend({_conversationIDs:[],_dialog:null,_environment:"",_proxy:null,init:function(e,a){this._conversationIDs=e,this._dialog=null,this._environment=a,this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLeaveForm",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs}),this._proxy.sendRequest()},_success:function(e,a,t){switch(e.returnValues.actionName){case"getLeaveForm":this._showDialog(e);break;case"hideConversation":"conversation"===this._environment?window.location=e.returnValues.redirectURL:window.location.reload()}},_showDialog:function(e){null===this._dialog&&(this._dialog=$("#leaveDialog"),this._dialog.length||(this._dialog=$('<div id="leaveDialog" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.leave.title")}),this._dialog.wcfDialog("render"),this._dialog.find("#hideConversation").click($.proxy(this._click,this))},_click:function(){var e=this._dialog.find("input[type=radio]:checked");1===e.length&&(this._proxy.setOption("data",{actionName:"hideConversation",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs,parameters:{hideConversation:e.val()}}),this._proxy.sendRequest())}}),WCF.Conversation.Label={},WCF.Conversation.Label.Editor=Class.extend({_conversationIDs:0,_dialog:null,_editorHandler:null,_notification:null,_proxy:null,init:function(e,a,t){this._conversationIDs=a?[$("#"+a).data("conversationID")]:t,this._dialog=null,this._editorHandler=e,this._notification=new WCF.System.Notification(WCF.Language.get("wcf.global.success.edit")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLabelForm",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs}}),this._proxy.sendRequest()},_success:function(e,a,t){switch(e.returnValues.actionName){case"assignLabel":this._assignLabels(e);break;case"getLabelForm":this._renderDialog(e)}},_renderDialog:function(e){null===this._dialog&&(this._dialog=$("#conversationLabelForm"),this._dialog.length||(this._dialog=$('<div id="conversationLabelForm" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.assignLabels")}),this._dialog.wcfDialog("render"),$("#assignLabels").click($.proxy(this._save,this))},_save:function(){var e=[];this._dialog.find("input").each((function(a,t){var n=$(t);n.is(":checked")&&e.push(n.data("labelID"))})),this._proxy.setOption("data",{actionName:"assignLabel",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs,labelIDs:e}}),this._proxy.sendRequest()},_assignLabels:function(e){for(var a=0,t=this._conversationIDs.length;a<t;a++)this._editorHandler.update(this._conversationIDs[a],"labelIDs",e.returnValues.labelIDs);this._dialog.wcfDialog("close"),this._notification.show()}}),WCF.Conversation.Label.Manager=Class.extend({_deletedLabelID:0,_dialog:null,_labels:null,_link:"",_notification:"",_proxy:null,_maxLabels:0,_labelCount:0,init:function(e){this._deletedLabelID=0,this._maxLabels=0,this._labelCount=0,this._link=e,this._labels=WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu"),$("#manageLabel").click($.proxy(this._click,this)),this._notification=new WCF.System.Notification(WCF.Language.get("wcf.conversation.label.management.addLabel.success")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)})},_click:function(){this._proxy.setOption("data",{actionName:"getLabelManagement",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_success:function(e,a,t){if(null===this._dialog&&(this._dialog=$('<div id="labelManagement" />').hide().appendTo(document.body)),e.returnValues&&e.returnValues.actionName)switch(e.returnValues.actionName){case"add":this._insertLabel(e);break;case"getLabelManagement":this._maxLabels=parseInt(e.returnValues.maxLabels),this._labelCount=parseInt(e.returnValues.labelCount),this._dialog.empty().html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.management")}),this._dialog.wcfDialog("render"),this._bindListener()}else if(this._deletedLabelID){var n=new RegExp("(\\?|&)labelID="+this._deletedLabelID);window.location=window.location.toString().replace(n,"")}else window.location.reload()},_insertLabel:function(e){var a=$('<li><a href="'+this._link+"&labelID="+e.returnValues.labelID+'"><span class="badge label'+(e.returnValues.cssClassName?" "+e.returnValues.cssClassName:"")+'">'+e.returnValues.label+"</span></a></li>");a.find("a > span").data("labelID",e.returnValues.labelID).data("cssClassName",e.returnValues.cssClassName),this._labels.append(a),this._notification.show(),this._labelCount++,this._labelCount>=this._maxLabels&&$("#conversationLabelManagementForm").hide()},_bindListener:function(){$("#labelName").on("keyup keydown keypress",$.proxy(this._updateLabels,this)),$.browser.mozilla&&$.browser.touch&&$("#labelName").on("input",$.proxy(this._updateLabels,this)),this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").hide(),this._dialog.wcfDialog("render")),$("#addLabel").disable().click($.proxy(this._addLabel,this)),$("#editLabel").disable(),this._dialog.find(".conversationLabelList a.label").click($.proxy(this._edit,this))},_edit:function(e){var a,t,n;this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").show(),this._dialog.wcfDialog("render")),a=$(e.currentTarget),t=WCF.Language.get("wcf.conversation.label.management.editLabel").replace(/#labelName#/,WCF.String.escapeHTML(a.text())),$("#conversationLabelManagementForm").data("labelID",a.data("labelID")).children(".sectionTitle").html(t),$("#labelName").val(a.text()).trigger("keyup"),n=a.data("cssClassName"),$("#labelManagementList input").each((function(e,a){var t=$(a);t.val()==n&&t.attr("checked","checked")})),$("#addLabel").hide(),$("#editLabel").show().click($.proxy(this._editLabel,this)),$("#deleteLabel").show().click($.proxy(this._deleteLabel,this))},_editLabel:function(){this._proxy.setOption("data",{actionName:"update",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")],parameters:{data:{cssClassName:$("#labelManagementList input:checked").val(),label:$("#labelName").val()}}}),this._proxy.sendRequest()},_deleteLabel:function(){var e=WCF.Language.get("wcf.conversation.label.management.deleteLabel.confirmMessage").replace(/#labelName#/,$("#labelName").val());WCF.System.Confirmation.show(e,$.proxy((function(e){"confirm"===e&&(this._proxy.setOption("data",{actionName:"delete",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")]}),this._proxy.sendRequest(),this._deletedLabelID=$("#conversationLabelManagementForm").data("labelID"))}),this),void 0,void 0,!0)},_updateLabels:function(){var e=$.trim($("#labelName").val());e?$("#addLabel, #editLabel").enable():($("#addLabel, #editLabel").disable(),e=WCF.Language.get("wcf.conversation.label.placeholder")),$("#labelManagementList").find("span.label").text(e)},_addLabel:function(){var e=$("#labelName").val(),a=$("#labelManagementList input:checked").val();this._proxy.setOption("data",{actionName:"add",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{data:{cssClassName:a,labelName:e}}}),this._proxy.sendRequest(),this._dialog.wcfDialog("close")}}),WCF.Conversation.Message={},WCF.Conversation.Message.InlineEditor=WCF.Message.InlineEditor.extend({init:function(e,a){this._super(e,!0,a)},_getClassName:function(){return"wcf\\data\\conversation\\message\\ConversationMessageAction"}});
\ No newline at end of file
index c9611599753df6f7ec8ac83c95bd2fd606b8de5d..7c3254f0e0ed50a4714b595ca5a2c690b2b63654 100644 (file)
@@ -1 +1 @@
-WCF.Conversation={},WCF.Conversation.EditorHandler=Class.extend({_attributes:{},_conversations:{},_permissions:{},init:function(availableLabels){this._conversations={};var self=this;$(".conversation").each((function(index,conversation){var $labelIDs,$conversation=$(conversation),$conversationID=$conversation.data("conversationID");self._conversations[$conversationID]||(self._conversations[$conversationID]=$conversation,$labelIDs=eval($conversation.data("labelIDs")),self._attributes[$conversationID]={isClosed:!!$conversation.data("isClosed"),labelIDs:$labelIDs},self._permissions[$conversationID]={canAddParticipants:!!$conversation.data("canAddParticipants"),canCloseConversation:!!$conversation.data("canCloseConversation")})}))},getPermission:function(e,a){return void 0!==this._permissions[e][a]&&!!this._permissions[e][a]},getValue:function(e,a){switch(a){case"labelIDs":return void 0===this._attributes[e].labelIDs&&(this._attributes[e].labelIDs=[]),this._attributes[e].labelIDs;case"isClosed":return!!this._attributes[e].isClosed}},countAvailableLabels:function(){return this.getAvailableLabels().length},getAvailableLabels:function(){var e=[];return WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu").children("li").each((function(a,t){var n,s=$(t);if(s.hasClass("dropdownDivider"))return!1;n=s.find("span"),e.push({cssClassName:n.data("cssClassName"),labelID:n.data("labelID"),label:n.text()})})),e},update:function(e,a,t){var n,s,i,o,l,r;if(this._conversations[e]){switch(n=this._conversations[e],a){case"close":$('<li><span class="icon icon16 fa-lock jsTooltip jsIconLock" title="'+WCF.Language.get("wcf.global.state.closed")+'" /></li>').prependTo(n.find(".statusIcons")),this._attributes[e].isClosed=1;break;case"labelIDs":if(s={},WCF.Dropdown.getDropdownMenu("conversationLabelFilter").find("li > a > span").each((function(e,a){var t=$(a);s[t.data("labelID")]={cssClassName:t.data("cssClassName"),label:t.text(),url:t.parent().attr("href")}})),i=n.find(".columnSubject > .labelList"),t.length)for(i.length||(i=$('<ul class="labelList" />').prependTo(n.find(".columnSubject"))),i.empty(),o=0,l=t.length;o<l;o++)r=s[t[o]],$('<li><a href="'+r.url+'" class="badge label'+(r.cssClassName?" "+r.cssClassName:"")+'">'+WCF.String.escapeHTML(r.label)+"</a></li>").appendTo(i);else i.length&&i.remove();break;case"open":n.find(".statusIcons li").each((function(e,a){var t=$(a);if(t.children("span.jsIconLock").length)return t.remove(),!1})),this._attributes[e].isClosed=0}WCF.Clipboard.reload()}else console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'")}}),WCF.Conversation.EditorHandlerConversation=WCF.Conversation.EditorHandler.extend({_availableLabels:null,init:function(e){this._availableLabels=e||[],this._super()},getAvailableLabels:function(){return this._availableLabels},update:function(e,a,t){var n,s,i,o;if(this._conversations[e])switch(n=$(".contentHeaderTitle > .contentHeaderMetaData"),a){case"close":$('<li><span class="icon icon16 fa-lock jsIconLock" /> '+WCF.Language.get("wcf.global.state.closed")+"</li>").appendTo(n),this._attributes[e].isClosed=1;break;case"labelIDs":s=n.find(".labelList"),t.length?(i=this.getAvailableLabels(),s.length||(s=(s=$('<li><span class="icon icon16 fa-tags"></span> <ul class="labelList"></ul></li>').prependTo(n)).children("ul")),o="",t.forEach((function(e){i.forEach((function(a){a.labelID==e&&(o+='<li><span class="label badge'+(a.cssClassName?" "+a.cssClassName:"")+'">'+a.label+"</span></li>")}))})),s[0].innerHTML=o):s.parent().remove();break;case"open":n.find(".jsIconLock").parent().remove(),this._attributes[e].isClosed=0}else console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'")}}),WCF.Conversation.Clipboard=Class.extend({_editorHandler:null,init:function(e){this._editorHandler=e,WCF.System.Event.addListener("com.woltlab.wcf.clipboard","com.woltlab.wcf.conversation.conversation",function(e){null===e.responseData?this._execute(e.data.actionName,e.data.parameters):this._evaluateResponse(e.data.actionName,e.responseData)}.bind(this))},_execute:function(e,a){"com.woltlab.wcf.conversation.conversation.assignLabel"===e&&new WCF.Conversation.Label.Editor(this._editorHandler,null,a.objectIDs)},_evaluateResponse:function(e,a){var t,n;switch(e){case"com.woltlab.wcf.conversation.conversation.leave":case"com.woltlab.wcf.conversation.conversation.leavePermanently":case"com.woltlab.wcf.conversation.conversation.markAsRead":case"com.woltlab.wcf.conversation.conversation.restore":window.location.reload();break;case"com.woltlab.wcf.conversation.conversation.close":case"com.woltlab.wcf.conversation.conversation.open":for(t in a.returnValues.conversationData)a.returnValues.conversationData.hasOwnProperty(t)&&(n=a.returnValues.conversationData[t],this._editorHandler.update(t,n.isClosed?"close":"open",n))}}}),WCF.Conversation.InlineEditor=WCF.InlineEditor.extend({_editorHandler:null,_environment:"conversation",_setOptions:function(){this._options=[{label:WCF.Language.get("wcf.conversation.edit.subject"),optionName:"editSubject"},{label:WCF.Language.get("wcf.conversation.edit.close"),optionName:"close"},{label:WCF.Language.get("wcf.conversation.edit.open"),optionName:"open"},{label:WCF.Language.get("wcf.conversation.edit.assignLabel"),optionName:"assignLabel"},{optionName:"divider"},{label:WCF.Language.get("wcf.conversation.edit.addParticipants"),optionName:"addParticipants"},{label:WCF.Language.get("wcf.conversation.edit.leave"),optionName:"leave"},{label:WCF.Language.get("wcf.global.button.edit"),optionName:"edit",isQuickOption:!0}]},setEditorHandler:function(e,a){this._editorHandler=e,this._environment="list"==a?"list":"conversation"},_getTriggerElement:function(e){return e.find(".jsConversationInlineEditor")},_validate:function(e,a){var t=$("#"+e).data("conversationID");switch(a){case"addParticipants":return this._editorHandler.getPermission(t,"canAddParticipants");case"assignLabel":return!!this._editorHandler.countAvailableLabels();case"editSubject":return!!this._editorHandler.getPermission(t,"canCloseConversation");case"close":case"open":return!!this._editorHandler.getPermission(t,"canCloseConversation")&&("close"===a?!this._editorHandler.getValue(t,"isClosed"):this._editorHandler.getValue(t,"isClosed"));case"leave":return!0;case"edit":return!!$("#"+e).data("isDraft")}return!1},_execute:function(e,a){if(!this._validate(e,a))return!1;switch(a){case"addParticipants":require(["WoltLabSuite/Core/Conversation/Ui/Participant/Add"],(function(a){new a(elData(elById(e),"conversation-id"))}));break;case"assignLabel":new WCF.Conversation.Label.Editor(this._editorHandler,e);break;case"editSubject":require(["WoltLabSuite/Core/Conversation/Ui/Subject/Editor"],(function(a){a.beginEdit(elData(elById(e),"conversation-id"))}));break;case"close":case"open":this._updateConversation(e,a,{isClosed:"close"===a?1:0});break;case"leave":new WCF.Conversation.Leave([$("#"+e).data("conversationID")],this._environment);break;case"edit":window.location=this._getTriggerElement($("#"+e)).prop("href")}},_updateConversation:function(e,a,t){var n=this._elements[e].data("conversationID");switch(a){case"close":case"editSubject":case"open":this._updateData.push({elementID:e,optionName:a,data:t}),this._proxy.setOption("data",{actionName:a,className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[n]}),this._proxy.sendRequest()}},_updateState:function(){var e,a,t,n;for(e=0,a=this._updateData.length;e<a;e++)switch(t=this._updateData[e],n=this._elements[t.elementID].data("conversationID"),t.optionName){case"close":case"editSubject":case"open":this._editorHandler.update(n,t.optionName,t.data)}}}),WCF.Conversation.Leave=Class.extend({_conversationIDs:[],_dialog:null,_environment:"",_proxy:null,init:function(e,a){this._conversationIDs=e,this._dialog=null,this._environment=a,this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLeaveForm",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs}),this._proxy.sendRequest()},_success:function(e,a,t){switch(e.returnValues.actionName){case"getLeaveForm":this._showDialog(e);break;case"hideConversation":"conversation"===this._environment?window.location=e.returnValues.redirectURL:window.location.reload()}},_showDialog:function(e){null===this._dialog&&(this._dialog=$("#leaveDialog"),this._dialog.length||(this._dialog=$('<div id="leaveDialog" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.leave.title")}),this._dialog.wcfDialog("render"),this._dialog.find("#hideConversation").click($.proxy(this._click,this))},_click:function(){var e=this._dialog.find("input[type=radio]:checked");1===e.length&&(this._proxy.setOption("data",{actionName:"hideConversation",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs,parameters:{hideConversation:e.val()}}),this._proxy.sendRequest())}}),WCF.Conversation.RemoveParticipant=WCF.Action.Delete.extend({_conversationID:0,init:function(e){this._conversationID=e,this._super("wcf\\data\\conversation\\ConversationAction",".jsParticipant")},_sendRequest:function(e){this.proxy.setOption("data",{actionName:"removeParticipant",className:this._className,objectIDs:[this._conversationID],parameters:{userID:$(e).data("objectID")}}),this.proxy.sendRequest()},_success:function(e,a,t){var n,s,i=e.returnValues.userID;for(n in this._containers)(s=$("#"+this._containers[n])).find(".jsDeleteButton").data("objectID")==i&&(s.find(".userLink").addClass("conversationLeft"),s.find(".jsDeleteButton").remove())}}),WCF.Conversation.Label={},WCF.Conversation.Label.Editor=Class.extend({_conversationIDs:0,_dialog:null,_editorHandler:null,_notification:null,_proxy:null,init:function(e,a,t){this._conversationIDs=a?[$("#"+a).data("conversationID")]:t,this._dialog=null,this._editorHandler=e,this._notification=new WCF.System.Notification(WCF.Language.get("wcf.global.success.edit")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLabelForm",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs}}),this._proxy.sendRequest()},_success:function(e,a,t){switch(e.returnValues.actionName){case"assignLabel":this._assignLabels(e);break;case"getLabelForm":this._renderDialog(e)}},_renderDialog:function(e){null===this._dialog&&(this._dialog=$("#conversationLabelForm"),this._dialog.length||(this._dialog=$('<div id="conversationLabelForm" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.assignLabels")}),this._dialog.wcfDialog("render"),$("#assignLabels").click($.proxy(this._save,this))},_save:function(){var e=[];this._dialog.find("input").each((function(a,t){var n=$(t);n.is(":checked")&&e.push(n.data("labelID"))})),this._proxy.setOption("data",{actionName:"assignLabel",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs,labelIDs:e}}),this._proxy.sendRequest()},_assignLabels:function(e){for(var a=0,t=this._conversationIDs.length;a<t;a++)this._editorHandler.update(this._conversationIDs[a],"labelIDs",e.returnValues.labelIDs);this._dialog.wcfDialog("close"),this._notification.show()}}),WCF.Conversation.Label.Manager=Class.extend({_deletedLabelID:0,_dialog:null,_labels:null,_link:"",_notification:"",_proxy:null,_maxLabels:0,_labelCount:0,init:function(e){this._deletedLabelID=0,this._maxLabels=0,this._labelCount=0,this._link=e,this._labels=WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu"),$("#manageLabel").click($.proxy(this._click,this)),this._notification=new WCF.System.Notification(WCF.Language.get("wcf.conversation.label.management.addLabel.success")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)})},_click:function(){this._proxy.setOption("data",{actionName:"getLabelManagement",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_success:function(e,a,t){if(null===this._dialog&&(this._dialog=$('<div id="labelManagement" />').hide().appendTo(document.body)),e.returnValues&&e.returnValues.actionName)switch(e.returnValues.actionName){case"add":this._insertLabel(e);break;case"getLabelManagement":this._maxLabels=parseInt(e.returnValues.maxLabels),this._labelCount=parseInt(e.returnValues.labelCount),this._dialog.empty().html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.management")}),this._dialog.wcfDialog("render"),this._bindListener()}else if(this._deletedLabelID){var n=new RegExp("(\\?|&)labelID="+this._deletedLabelID);window.location=window.location.toString().replace(n,"")}else window.location.reload()},_insertLabel:function(e){var a=$('<li><a href="'+this._link+"&labelID="+e.returnValues.labelID+'"><span class="badge label'+(e.returnValues.cssClassName?" "+e.returnValues.cssClassName:"")+'">'+e.returnValues.label+"</span></a></li>");a.find("a > span").data("labelID",e.returnValues.labelID).data("cssClassName",e.returnValues.cssClassName),this._labels.append(a),this._notification.show(),this._labelCount++,this._labelCount>=this._maxLabels&&$("#conversationLabelManagementForm").hide()},_bindListener:function(){$("#labelName").on("keyup keydown keypress",$.proxy(this._updateLabels,this)),$.browser.mozilla&&$.browser.touch&&$("#labelName").on("input",$.proxy(this._updateLabels,this)),this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").hide(),this._dialog.wcfDialog("render")),$("#addLabel").disable().click($.proxy(this._addLabel,this)),$("#editLabel").disable(),this._dialog.find(".conversationLabelList a.label").click($.proxy(this._edit,this))},_edit:function(e){var a,t,n;this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").show(),this._dialog.wcfDialog("render")),a=$(e.currentTarget),t=WCF.Language.get("wcf.conversation.label.management.editLabel").replace(/#labelName#/,WCF.String.escapeHTML(a.text())),$("#conversationLabelManagementForm").data("labelID",a.data("labelID")).children(".sectionTitle").html(t),$("#labelName").val(a.text()).trigger("keyup"),n=a.data("cssClassName"),$("#labelManagementList input").each((function(e,a){var t=$(a);t.val()==n&&t.attr("checked","checked")})),$("#addLabel").hide(),$("#editLabel").show().click($.proxy(this._editLabel,this)),$("#deleteLabel").show().click($.proxy(this._deleteLabel,this))},_editLabel:function(){this._proxy.setOption("data",{actionName:"update",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")],parameters:{data:{cssClassName:$("#labelManagementList input:checked").val(),label:$("#labelName").val()}}}),this._proxy.sendRequest()},_deleteLabel:function(){var e=WCF.Language.get("wcf.conversation.label.management.deleteLabel.confirmMessage").replace(/#labelName#/,$("#labelName").val());WCF.System.Confirmation.show(e,$.proxy((function(e){"confirm"===e&&(this._proxy.setOption("data",{actionName:"delete",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")]}),this._proxy.sendRequest(),this._deletedLabelID=$("#conversationLabelManagementForm").data("labelID"))}),this),void 0,void 0,!0)},_updateLabels:function(){var e=$.trim($("#labelName").val());e?$("#addLabel, #editLabel").enable():($("#addLabel, #editLabel").disable(),e=WCF.Language.get("wcf.conversation.label.placeholder")),$("#labelManagementList").find("span.label").text(e)},_addLabel:function(){var e=$("#labelName").val(),a=$("#labelManagementList input:checked").val();this._proxy.setOption("data",{actionName:"add",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{data:{cssClassName:a,labelName:e}}}),this._proxy.sendRequest(),this._dialog.wcfDialog("close")}}),WCF.Conversation.Preview=WCF.Popover.extend({_proxy:null,init:function(){this._super(".conversationLink"),this._proxy=new WCF.Action.Proxy({showLoadingOverlay:!1}),WCF.DOMNodeInsertedHandler.addCallback("WCF.Conversation.Preview",$.proxy(this._initContainers,this))},_loadContent:function(){var e,a,t=$("#"+this._activeElementID);this._proxy.setOption("data",{actionName:"getMessagePreview",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[t.data("conversationID")]}),e=this._activeElementID,a=this,this._proxy.setOption("success",(function(t,n,s){a._insertContent(e,t.returnValues.template,!0)})),this._proxy.sendRequest()}}),WCF.Conversation.MarkAsRead=Class.extend({_proxy:null,init:function(){this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),$(document).on("dblclick",".conversationList .new .columnAvatar",$.proxy(this._dblclick,this))},_dblclick:function(e){this._proxy.setOption("data",{actionName:"markAsRead",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[$(e.currentTarget).parents("ol:eq(0)").data("conversationID")]}),this._proxy.sendRequest()},_success:function(e,a,t){$(".conversationList .new").each((function(a,t){var n=$(t);WCF.inArray(n.data("conversationID"),e.objectIDs)&&(n.removeClass("new"),n.find(".firstNewPost").parent().remove(),n.find(".columnAvatar").off("dblclick"))}))}}),WCF.Conversation.MarkAllAsRead=Class.extend({_proxy:null,init:function(){this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),$(".markAllAsReadButton").click($.proxy(this._click,this))},_click:function(e){e.preventDefault(),this._proxy.setOption("data",{actionName:"markAllAsRead",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_success:function(e,a,t){WCF.System.Event.fireEvent("com.woltlab.wcf.conversation.userPanel","reset");var n=$(".conversationList");n.find(".new").removeClass("new"),n.find(".columnAvatar").off("dblclick"),(new WCF.System.Notification).show()}}),WCF.Conversation.Message={},WCF.Conversation.Message.InlineEditor=WCF.Message.InlineEditor.extend({init:function(e,a){this._super(e,!0,a)},_getClassName:function(){return"wcf\\data\\conversation\\message\\ConversationMessageAction"}}),WCF.Conversation.Message.QuoteHandler=WCF.Message.Quote.Handler.extend({init:function(e){require(["WoltLabSuite/Core/Conversation/Ui/Message/Quote"],(({UiConversationMessageQuote:a})=>{new a(e)}))}});
\ No newline at end of file
+WCF.Conversation={},WCF.Conversation.EditorHandler=Class.extend({_attributes:{},_conversations:{},_permissions:{},init:function(availableLabels){this._conversations={};var self=this;$(".conversation").each((function(index,conversation){var $labelIDs,$conversation=$(conversation),$conversationID=$conversation.data("conversationID");self._conversations[$conversationID]||(self._conversations[$conversationID]=$conversation,$labelIDs=eval($conversation.data("labelIDs")),self._attributes[$conversationID]={isClosed:!!$conversation.data("isClosed"),labelIDs:$labelIDs},self._permissions[$conversationID]={canAddParticipants:!!$conversation.data("canAddParticipants"),canCloseConversation:!!$conversation.data("canCloseConversation")})}))},getPermission:function(e,a){return void 0!==this._permissions[e][a]&&!!this._permissions[e][a]},getValue:function(e,a){switch(a){case"labelIDs":return void 0===this._attributes[e].labelIDs&&(this._attributes[e].labelIDs=[]),this._attributes[e].labelIDs;case"isClosed":return!!this._attributes[e].isClosed}},countAvailableLabels:function(){return this.getAvailableLabels().length},getAvailableLabels:function(){var e=[];return WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu").children("li").each((function(a,t){var n,s=$(t);if(s.hasClass("dropdownDivider"))return!1;n=s.find("span"),e.push({cssClassName:n.data("cssClassName"),labelID:n.data("labelID"),label:n.text()})})),e},update:function(e,a,t){var n,s,i,o,l,r;if(this._conversations[e]){switch(n=this._conversations[e],a){case"close":$(`<li>\n\t\t\t\t\t<span class="jsTooltip jsIconLock" title="${WCF.Language.get("wcf.global.state.closed")}">\n\t\t\t\t\t\t<fa-icon size="16" name="lock"></fa-icon>\n\t\t\t\t\t</span>\n\t\t\t\t</li>`).prependTo(n.find(".statusIcons")),this._attributes[e].isClosed=1;break;case"labelIDs":if(s={},WCF.Dropdown.getDropdownMenu("conversationLabelFilter").find("li > a > span").each((function(e,a){var t=$(a);s[t.data("labelID")]={cssClassName:t.data("cssClassName"),label:t.text(),url:t.parent().attr("href")}})),i=n.find(".columnSubject > .labelList"),t.length)for(i.length||(i=$('<ul class="labelList" />').prependTo(n.find(".columnSubject"))),i.empty(),o=0,l=t.length;o<l;o++)r=s[t[o]],$('<li><a href="'+r.url+'" class="badge label'+(r.cssClassName?" "+r.cssClassName:"")+'">'+WCF.String.escapeHTML(r.label)+"</a></li>").appendTo(i);else i.length&&i.remove();break;case"open":n.find(".statusIcons li").each((function(e,a){var t=$(a);if(t.children("span.jsIconLock").length)return t.remove(),!1})),this._attributes[e].isClosed=0}WCF.Clipboard.reload()}else console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'")}}),WCF.Conversation.EditorHandlerConversation=WCF.Conversation.EditorHandler.extend({_availableLabels:null,init:function(e){this._availableLabels=e||[],this._super()},getAvailableLabels:function(){return this._availableLabels},update:function(e,a,t){var n,s,i,o;if(this._conversations[e])switch(n=$(".contentHeaderTitle > .contentHeaderMetaData"),a){case"close":$(`<li>\n\t\t\t\t\t<fa-icon size="16" name="lock"></fa-icon>\n\t\t\t\t\t${WCF.Language.get("wcf.global.state.closed")}\n\t\t\t\t</li>`).appendTo(n),this._attributes[e].isClosed=1;break;case"labelIDs":s=n.find(".labelList"),t.length?(i=this.getAvailableLabels(),s.length||(s=(s=$('<li>\n\t\t\t\t\t\t\t<fa-icon size="16" name="tags"></fa-icon>\n\t\t\t\t\t\t\t<ul class="labelList"></ul>\n\t\t\t\t\t\t</li>').prependTo(n)).children("ul")),o="",t.forEach((function(e){i.forEach((function(a){a.labelID==e&&(o+='<li><span class="label badge'+(a.cssClassName?" "+a.cssClassName:"")+'">'+a.label+"</span></li>")}))})),s[0].innerHTML=o):s.parent().remove();break;case"open":n.find(".jsIconLock").parent().remove(),this._attributes[e].isClosed=0}else console.debug("[WCF.Conversation.EditorHandler] Unknown conversation id '"+e+"'")}}),WCF.Conversation.Clipboard=Class.extend({_editorHandler:null,init:function(e){this._editorHandler=e,WCF.System.Event.addListener("com.woltlab.wcf.clipboard","com.woltlab.wcf.conversation.conversation",function(e){null===e.responseData?this._execute(e.data.actionName,e.data.parameters):this._evaluateResponse(e.data.actionName,e.responseData)}.bind(this))},_execute:function(e,a){"com.woltlab.wcf.conversation.conversation.assignLabel"===e&&new WCF.Conversation.Label.Editor(this._editorHandler,null,a.objectIDs)},_evaluateResponse:function(e,a){var t,n;switch(e){case"com.woltlab.wcf.conversation.conversation.leave":case"com.woltlab.wcf.conversation.conversation.leavePermanently":case"com.woltlab.wcf.conversation.conversation.markAsRead":case"com.woltlab.wcf.conversation.conversation.restore":window.location.reload();break;case"com.woltlab.wcf.conversation.conversation.close":case"com.woltlab.wcf.conversation.conversation.open":for(t in a.returnValues.conversationData)a.returnValues.conversationData.hasOwnProperty(t)&&(n=a.returnValues.conversationData[t],this._editorHandler.update(t,n.isClosed?"close":"open",n))}}}),WCF.Conversation.InlineEditor=WCF.InlineEditor.extend({_editorHandler:null,_environment:"conversation",_setOptions:function(){this._options=[{label:WCF.Language.get("wcf.conversation.edit.subject"),optionName:"editSubject"},{label:WCF.Language.get("wcf.conversation.edit.close"),optionName:"close"},{label:WCF.Language.get("wcf.conversation.edit.open"),optionName:"open"},{label:WCF.Language.get("wcf.conversation.edit.assignLabel"),optionName:"assignLabel"},{optionName:"divider"},{label:WCF.Language.get("wcf.conversation.edit.addParticipants"),optionName:"addParticipants"},{label:WCF.Language.get("wcf.conversation.edit.leave"),optionName:"leave"},{label:WCF.Language.get("wcf.global.button.edit"),optionName:"edit",isQuickOption:!0}]},setEditorHandler:function(e,a){this._editorHandler=e,this._environment="list"==a?"list":"conversation"},_getTriggerElement:function(e){return e.find(".jsConversationInlineEditor")},_validate:function(e,a){var t=$("#"+e).data("conversationID");switch(a){case"addParticipants":return this._editorHandler.getPermission(t,"canAddParticipants");case"assignLabel":return!!this._editorHandler.countAvailableLabels();case"editSubject":return!!this._editorHandler.getPermission(t,"canCloseConversation");case"close":case"open":return!!this._editorHandler.getPermission(t,"canCloseConversation")&&("close"===a?!this._editorHandler.getValue(t,"isClosed"):this._editorHandler.getValue(t,"isClosed"));case"leave":return!0;case"edit":return!!$("#"+e).data("isDraft")}return!1},_execute:function(e,a){if(!this._validate(e,a))return!1;switch(a){case"addParticipants":require(["WoltLabSuite/Core/Conversation/Ui/Participant/Add"],(function(a){new a(elData(elById(e),"conversation-id"))}));break;case"assignLabel":new WCF.Conversation.Label.Editor(this._editorHandler,e);break;case"editSubject":require(["WoltLabSuite/Core/Conversation/Ui/Subject/Editor"],(function(a){a.beginEdit(elData(elById(e),"conversation-id"))}));break;case"close":case"open":this._updateConversation(e,a,{isClosed:"close"===a?1:0});break;case"leave":new WCF.Conversation.Leave([$("#"+e).data("conversationID")],this._environment);break;case"edit":window.location=this._getTriggerElement($("#"+e)).prop("href")}},_updateConversation:function(e,a,t){var n=this._elements[e].data("conversationID");switch(a){case"close":case"editSubject":case"open":this._updateData.push({elementID:e,optionName:a,data:t}),this._proxy.setOption("data",{actionName:a,className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[n]}),this._proxy.sendRequest()}},_updateState:function(){var e,a,t,n;for(e=0,a=this._updateData.length;e<a;e++)switch(t=this._updateData[e],n=this._elements[t.elementID].data("conversationID"),t.optionName){case"close":case"editSubject":case"open":this._editorHandler.update(n,t.optionName,t.data)}}}),WCF.Conversation.Leave=Class.extend({_conversationIDs:[],_dialog:null,_environment:"",_proxy:null,init:function(e,a){this._conversationIDs=e,this._dialog=null,this._environment=a,this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLeaveForm",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs}),this._proxy.sendRequest()},_success:function(e,a,t){switch(e.returnValues.actionName){case"getLeaveForm":this._showDialog(e);break;case"hideConversation":"conversation"===this._environment?window.location=e.returnValues.redirectURL:window.location.reload()}},_showDialog:function(e){null===this._dialog&&(this._dialog=$("#leaveDialog"),this._dialog.length||(this._dialog=$('<div id="leaveDialog" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.leave.title")}),this._dialog.wcfDialog("render"),this._dialog.find("#hideConversation").click($.proxy(this._click,this))},_click:function(){var e=this._dialog.find("input[type=radio]:checked");1===e.length&&(this._proxy.setOption("data",{actionName:"hideConversation",className:"wcf\\data\\conversation\\ConversationAction",objectIDs:this._conversationIDs,parameters:{hideConversation:e.val()}}),this._proxy.sendRequest())}}),WCF.Conversation.Label={},WCF.Conversation.Label.Editor=Class.extend({_conversationIDs:0,_dialog:null,_editorHandler:null,_notification:null,_proxy:null,init:function(e,a,t){this._conversationIDs=a?[$("#"+a).data("conversationID")]:t,this._dialog=null,this._editorHandler=e,this._notification=new WCF.System.Notification(WCF.Language.get("wcf.global.success.edit")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)}),this._loadDialog()},_loadDialog:function(){this._proxy.setOption("data",{actionName:"getLabelForm",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs}}),this._proxy.sendRequest()},_success:function(e,a,t){switch(e.returnValues.actionName){case"assignLabel":this._assignLabels(e);break;case"getLabelForm":this._renderDialog(e)}},_renderDialog:function(e){null===this._dialog&&(this._dialog=$("#conversationLabelForm"),this._dialog.length||(this._dialog=$('<div id="conversationLabelForm" />').hide().appendTo(document.body))),this._dialog.html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.assignLabels")}),this._dialog.wcfDialog("render"),$("#assignLabels").click($.proxy(this._save,this))},_save:function(){var e=[];this._dialog.find("input").each((function(a,t){var n=$(t);n.is(":checked")&&e.push(n.data("labelID"))})),this._proxy.setOption("data",{actionName:"assignLabel",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{conversationIDs:this._conversationIDs,labelIDs:e}}),this._proxy.sendRequest()},_assignLabels:function(e){for(var a=0,t=this._conversationIDs.length;a<t;a++)this._editorHandler.update(this._conversationIDs[a],"labelIDs",e.returnValues.labelIDs);this._dialog.wcfDialog("close"),this._notification.show()}}),WCF.Conversation.Label.Manager=Class.extend({_deletedLabelID:0,_dialog:null,_labels:null,_link:"",_notification:"",_proxy:null,_maxLabels:0,_labelCount:0,init:function(e){this._deletedLabelID=0,this._maxLabels=0,this._labelCount=0,this._link=e,this._labels=WCF.Dropdown.getDropdownMenu("conversationLabelFilter").children(".scrollableDropdownMenu"),$("#manageLabel").click($.proxy(this._click,this)),this._notification=new WCF.System.Notification(WCF.Language.get("wcf.conversation.label.management.addLabel.success")),this._proxy=new WCF.Action.Proxy({success:$.proxy(this._success,this)})},_click:function(){this._proxy.setOption("data",{actionName:"getLabelManagement",className:"wcf\\data\\conversation\\ConversationAction"}),this._proxy.sendRequest()},_success:function(e,a,t){if(null===this._dialog&&(this._dialog=$('<div id="labelManagement" />').hide().appendTo(document.body)),e.returnValues&&e.returnValues.actionName)switch(e.returnValues.actionName){case"add":this._insertLabel(e);break;case"getLabelManagement":this._maxLabels=parseInt(e.returnValues.maxLabels),this._labelCount=parseInt(e.returnValues.labelCount),this._dialog.empty().html(e.returnValues.template),this._dialog.wcfDialog({title:WCF.Language.get("wcf.conversation.label.management")}),this._dialog.wcfDialog("render"),this._bindListener()}else if(this._deletedLabelID){var n=new RegExp("(\\?|&)labelID="+this._deletedLabelID);window.location=window.location.toString().replace(n,"")}else window.location.reload()},_insertLabel:function(e){var a=$('<li><a href="'+this._link+"&labelID="+e.returnValues.labelID+'"><span class="badge label'+(e.returnValues.cssClassName?" "+e.returnValues.cssClassName:"")+'">'+e.returnValues.label+"</span></a></li>");a.find("a > span").data("labelID",e.returnValues.labelID).data("cssClassName",e.returnValues.cssClassName),this._labels.append(a),this._notification.show(),this._labelCount++,this._labelCount>=this._maxLabels&&$("#conversationLabelManagementForm").hide()},_bindListener:function(){$("#labelName").on("keyup keydown keypress",$.proxy(this._updateLabels,this)),$.browser.mozilla&&$.browser.touch&&$("#labelName").on("input",$.proxy(this._updateLabels,this)),this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").hide(),this._dialog.wcfDialog("render")),$("#addLabel").disable().click($.proxy(this._addLabel,this)),$("#editLabel").disable(),this._dialog.find(".conversationLabelList a.label").click($.proxy(this._edit,this))},_edit:function(e){var a,t,n;this._labelCount>=this._maxLabels&&($("#conversationLabelManagementForm").show(),this._dialog.wcfDialog("render")),a=$(e.currentTarget),t=WCF.Language.get("wcf.conversation.label.management.editLabel").replace(/#labelName#/,WCF.String.escapeHTML(a.text())),$("#conversationLabelManagementForm").data("labelID",a.data("labelID")).children(".sectionTitle").html(t),$("#labelName").val(a.text()).trigger("keyup"),n=a.data("cssClassName"),$("#labelManagementList input").each((function(e,a){var t=$(a);t.val()==n&&t.attr("checked","checked")})),$("#addLabel").hide(),$("#editLabel").show().click($.proxy(this._editLabel,this)),$("#deleteLabel").show().click($.proxy(this._deleteLabel,this))},_editLabel:function(){this._proxy.setOption("data",{actionName:"update",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")],parameters:{data:{cssClassName:$("#labelManagementList input:checked").val(),label:$("#labelName").val()}}}),this._proxy.sendRequest()},_deleteLabel:function(){var e=WCF.Language.get("wcf.conversation.label.management.deleteLabel.confirmMessage").replace(/#labelName#/,$("#labelName").val());WCF.System.Confirmation.show(e,$.proxy((function(e){"confirm"===e&&(this._proxy.setOption("data",{actionName:"delete",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",objectIDs:[$("#conversationLabelManagementForm").data("labelID")]}),this._proxy.sendRequest(),this._deletedLabelID=$("#conversationLabelManagementForm").data("labelID"))}),this),void 0,void 0,!0)},_updateLabels:function(){var e=$.trim($("#labelName").val());e?$("#addLabel, #editLabel").enable():($("#addLabel, #editLabel").disable(),e=WCF.Language.get("wcf.conversation.label.placeholder")),$("#labelManagementList").find("span.label").text(e)},_addLabel:function(){var e=$("#labelName").val(),a=$("#labelManagementList input:checked").val();this._proxy.setOption("data",{actionName:"add",className:"wcf\\data\\conversation\\label\\ConversationLabelAction",parameters:{data:{cssClassName:a,labelName:e}}}),this._proxy.sendRequest(),this._dialog.wcfDialog("close")}}),WCF.Conversation.Message={},WCF.Conversation.Message.InlineEditor=WCF.Message.InlineEditor.extend({init:function(e,a){this._super(e,!0,a)},_getClassName:function(){return"wcf\\data\\conversation\\message\\ConversationMessageAction"}});
\ No newline at end of file
index cd68f6764673ae0590c8d41fbf603de17340c2a9..91c567fc584930d1421cb5359a8b168d65c1e553 100644 (file)
@@ -1 +1 @@
-define("WoltLabSuite/Core/Conversation/Ui/Message/Quote",["require","exports","WoltLabSuite/Core/Ui/Message/Quote"],(function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.UiConversationMessageQuote=void 0;class o extends i.UiMessageQuote{constructor(t){super(t,"wcf\\data\\conversation\\message\\ConversationMessageAction","com.woltlab.wcf.conversation.message",".message",".messageBody",".messageBody > div > div.messageText",!0)}}e.UiConversationMessageQuote=o,e.default=o})),define("WoltLabSuite/Core/Conversation/Ui/Participant/Add",["require","exports","tslib","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Dom/Util","WoltLabSuite/Core/Ui/Dialog","WoltLabSuite/Core/Ui/Notification","WoltLabSuite/Core/Ui/ItemList/User","WoltLabSuite/Core/Language"],(function(t,e,i,o,n,s,a,r,u){"use strict";o=i.__importStar(o),n=i.__importDefault(n),s=i.__importDefault(s),a=i.__importStar(a),r=i.__importStar(r),u=i.__importStar(u);return class{constructor(t){this.conversationId=t,o.api(this,{actionName:"getAddParticipantsForm"})}_ajaxSetup(){return{data:{className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[this.conversationId]}}}_ajaxSuccess(t){switch(t.actionName){case"addParticipants":this.handleResponse(t);break;case"getAddParticipantsForm":this.render(t)}}handleResponse(t){"errorMessage"in t.returnValues?n.default.innerError(document.getElementById("participantsInput").closest(".inputItemList"),t.returnValues.errorMessage):("count"in t.returnValues&&a.show(t.returnValues.successMessage,(()=>{window.location.reload()})),s.default.close(this))}render(t){s.default.open(this,t.returnValues.template);const e=document.getElementById("addParticipants");e.disabled=!0,r.init("participantsInput",{callbackChange:(t,i)=>{e.disabled=0===i.length},excludedSearchValues:t.returnValues.excludedSearchValues,maxItems:t.returnValues.maxItems,includeUserGroups:t.returnValues.canAddGroupParticipants&&t.returnValues.restrictUserGroupIDs.length>0,restrictUserGroupIDs:t.returnValues.restrictUserGroupIDs,csvPerType:!0}),e.addEventListener("click",(()=>{this.submit()}))}submit(){const t=[],e=[];r.getValues("participantsInput").forEach((i=>{"group"===i.type?e.push(i.objectId):t.push(i.value)}));const i={participants:t,participantsGroupIDs:e,visibility:null},n=s.default.getDialog(this).content.querySelector('input[name="messageVisibility"]:checked, input[name="messageVisibility"][type="hidden"]');n&&(i.visibility=n.value),o.api(this,{actionName:"addParticipants",parameters:i})}_dialogSetup(){return{id:"conversationAddParticipants",options:{title:u.get("wcf.conversation.edit.addParticipants")},source:null}}}})),define("WoltLabSuite/Core/Conversation/Ui/Subject/Editor",["require","exports","tslib","WoltLabSuite/Core/Ui/Dialog","WoltLabSuite/Core/Dom/Util","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Language","WoltLabSuite/Core/Ui/Notification"],(function(t,e,i,o,n,s,a,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.beginEdit=void 0,o=i.__importDefault(o),n=i.__importDefault(n),s=i.__importStar(s),a=i.__importStar(a),r=i.__importStar(r);class u{constructor(t){this.objectId=t}show(){o.default.open(this)}saveEdit(t){t.preventDefault();const e=this.subject.value.trim();""===e?n.default.innerError(this.subject,a.get("wcf.global.form.error.empty")):(n.default.innerError(this.subject,""),s.api(this,{parameters:{subject:e},objectIDs:[this.objectId]}))}getCurrentValue(){return Array.from(document.querySelectorAll(`.jsConversationSubject[data-conversation-id="${this.objectId}"], .conversationLink[data-object-id="${this.objectId}"]`)).map((t=>t.textContent)).slice(-1)[0]}_ajaxSuccess(t){o.default.close(this),document.querySelectorAll(`.jsConversationSubject[data-conversation-id="${this.objectId}"], .conversationLink[data-object-id="${this.objectId}"]`).forEach((e=>{e.textContent=t.returnValues.subject})),r.show()}_dialogSetup(){return{id:"dialogConversationSubjectEditor",options:{onSetup:t=>{this.subject=document.getElementById("jsConversationSubject"),this.subject.addEventListener("keyup",(t=>{"Enter"===t.key&&this.saveEdit(t)})),t.querySelector(".jsButtonSave").addEventListener("click",(t=>{this.saveEdit(t)}))},onShow:()=>{this.subject.value=this.getCurrentValue()},title:a.get("wcf.conversation.edit.subject")},source:`\n        <dl>\n          <dt>\n            <label for="jsConversationSubject">${a.get("wcf.global.subject")}</label>\n          </dt>\n          <dd>\n            <input type="text" id="jsConversationSubject" class="long" maxlength="255">\n          </dd>\n        </dl>\n        <div class="formSubmit">\n          <button class="buttonPrimary jsButtonSave">${a.get("wcf.global.button.save")}</button>\n        </div>\n      `}}_ajaxSetup(){return{data:{actionName:"editSubject",className:"wcf\\data\\conversation\\ConversationAction"}}}}let c;e.beginEdit=function(t){c=new u(t),c.show()}})),define("WoltLabSuite/Core/Conversation/Ui/Object/Action/RemoveParticipant",["require","exports","tslib","WoltLabSuite/Core/Ui/Object/Action/Handler"],(function(t,e,i,o){"use strict";function n(t){t.objectElement.querySelector(".userLink").classList.add("conversationLeft"),t.objectElement.querySelector(".jsObjectAction[data-object-action='removeParticipant']").remove()}Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0,o=i.__importDefault(o),e.setup=function(){new o.default("removeParticipant",[],n)}})),define("WoltLabSuite/Core/Conversation/Ui/User/Menu/Data/Conversation",["require","exports","tslib","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Ui/User/Menu/View","WoltLabSuite/Core/Ui/User/Menu/Manager"],(function(t,e,i,o,n,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0,n=i.__importDefault(n);class a{constructor(t,e){this.counter=0,this.stale=!0,this.view=void 0,this.button=t,this.options=e;const i=t.querySelector(".badge");if(i){const t=parseInt(i.textContent.trim());t&&(this.counter=t)}}getPanelButton(){return this.button}getMenuButtons(){const t=[];return this.options.canStartConversation&&t.push({icon:'<span class="icon icon24 fa-plus"></span>',link:this.options.newConversationLink,name:"newConversation",title:this.options.newConversationTitle}),t}getIdentifier(){return"com.woltlab.wcf.conversation.conversations"}async getData(){const t=await(0,o.dboAction)("getConversations","wcf\\data\\conversation\\ConversationAction").disableLoadingIndicator().dispatch();return this.updateCounter(t.totalCount),this.stale=!1,t.items}getFooter(){return{link:this.options.showAllLink,title:this.options.showAllTitle}}getTitle(){return this.options.title}getView(){return void 0===this.view&&(this.view=new n.default(this)),this.view}getEmptyViewMessage(){return this.options.noItems}hasPlainTitle(){return!0}hasUnreadContent(){return this.counter>0}isStale(){if(this.stale)return!0;const t=this.getView().getItems().filter((t=>"true"===t.dataset.isUnread));return this.counter!==t.length}async markAsRead(t){const e=await(0,o.dboAction)("markAsRead","wcf\\data\\conversation\\ConversationAction").objectIds([t]).dispatch();this.updateCounter(e.totalCount)}async markAllAsRead(){await(0,o.dboAction)("markAllAsRead","wcf\\data\\conversation\\ConversationAction").dispatch(),this.updateCounter(0)}updateCounter(t){let e=this.button.querySelector(".badge");null===e&&t>0&&(e=document.createElement("span"),e.classList.add("badge","badgeUpdate"),this.button.querySelector("a").append(e)),e&&(0===t?e.remove():e.textContent=t.toString()),this.counter=t}}let r=!1;e.setup=function(t){if(!r){const e=document.getElementById("unreadConversations");if(null!==e){const i=new a(e,t);(0,s.registerProvider)(i)}r=!0}}}));
\ No newline at end of file
+define("WoltLabSuite/Core/Conversation/Ui/MarkAllAsRead",["require","exports","tslib","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Ui/Notification"],(function(t,e,o,i,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0,n=o.__importStar(n),e.setup=function(){document.querySelectorAll(".markAllAsReadButton").forEach((t=>{t.addEventListener("click",(t=>{t.preventDefault(),async function(){await(0,i.dboAction)("markAllAsRead","wcf\\data\\conversation\\ConversationAction").dispatch(),document.querySelectorAll(".conversationList .new").forEach((t=>{t.classList.remove("new")})),document.querySelector("#unreadConversations .badgeUpdate")?.remove(),n.show()}()}))}))}})),define("WoltLabSuite/Core/Conversation/Ui/MarkAsRead",["require","exports","WoltLabSuite/Core/Ajax"],(function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0;const i=new WeakSet;e.setup=function(){document.querySelectorAll(".conversationList .new .columnAvatar").forEach((t=>{i.has(t)||(i.add(t),t.addEventListener("dblclick",(e=>{e.preventDefault();const i=t.closest(".conversation");i.classList.contains("new")&&async function(t){const e=parseInt(t.dataset.conversationId,10);await(0,o.dboAction)("markAsRead","wcf\\data\\conversation\\ConversationAction").objectIds([e]).dispatch(),t.classList.remove("new"),t.querySelector(".columnAvatar p")?.removeAttribute("title")}(i)}),{once:!0}))}))}})),define("WoltLabSuite/Core/Conversation/Ui/Message/Quote",["require","exports","WoltLabSuite/Core/Ui/Message/Quote"],(function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.UiConversationMessageQuote=void 0;class i extends o.UiMessageQuote{constructor(t){super(t,"wcf\\data\\conversation\\message\\ConversationMessageAction","com.woltlab.wcf.conversation.message",".message",".messageBody",".messageBody > div > div.messageText",!0)}}e.UiConversationMessageQuote=i,e.default=i})),define("WoltLabSuite/Core/Conversation/Ui/Participant/Add",["require","exports","tslib","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Dom/Util","WoltLabSuite/Core/Ui/Dialog","WoltLabSuite/Core/Ui/Notification","WoltLabSuite/Core/Ui/ItemList/User","WoltLabSuite/Core/Language"],(function(t,e,o,i,n,a,s,r,c){"use strict";return i=o.__importStar(i),n=o.__importDefault(n),a=o.__importDefault(a),s=o.__importStar(s),r=o.__importStar(r),c=o.__importStar(c),class{conversationId;constructor(t){this.conversationId=t,i.api(this,{actionName:"getAddParticipantsForm"})}_ajaxSetup(){return{data:{className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[this.conversationId]}}}_ajaxSuccess(t){switch(t.actionName){case"addParticipants":this.handleResponse(t);break;case"getAddParticipantsForm":this.render(t)}}handleResponse(t){"errorMessage"in t.returnValues?n.default.innerError(document.getElementById("participantsInput").closest(".inputItemList"),t.returnValues.errorMessage):("count"in t.returnValues&&s.show(t.returnValues.successMessage,(()=>{window.location.reload()})),a.default.close(this))}render(t){a.default.open(this,t.returnValues.template);const e=document.getElementById("addParticipants");e.disabled=!0,r.init("participantsInput",{callbackChange:(t,o)=>{e.disabled=0===o.length},excludedSearchValues:t.returnValues.excludedSearchValues,maxItems:t.returnValues.maxItems,includeUserGroups:t.returnValues.canAddGroupParticipants&&t.returnValues.restrictUserGroupIDs.length>0,restrictUserGroupIDs:t.returnValues.restrictUserGroupIDs,csvPerType:!0}),e.addEventListener("click",(()=>{this.submit()}))}submit(){const t=[],e=[];r.getValues("participantsInput").forEach((o=>{"group"===o.type?e.push(o.objectId):t.push(o.value)}));const o={participants:t,participantsGroupIDs:e,visibility:null},n=a.default.getDialog(this).content.querySelector('input[name="messageVisibility"]:checked, input[name="messageVisibility"][type="hidden"]');n&&(o.visibility=n.value),i.api(this,{actionName:"addParticipants",parameters:o})}_dialogSetup(){return{id:"conversationAddParticipants",options:{title:c.get("wcf.conversation.edit.addParticipants")},source:null}}}})),define("WoltLabSuite/Core/Conversation/Ui/Subject/Editor",["require","exports","tslib","WoltLabSuite/Core/Ui/Dialog","WoltLabSuite/Core/Dom/Util","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Language","WoltLabSuite/Core/Ui/Notification"],(function(t,e,o,i,n,a,s,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.beginEdit=void 0,i=o.__importDefault(i),n=o.__importDefault(n),a=o.__importStar(a),s=o.__importStar(s),r=o.__importStar(r);class c{objectId;subject;constructor(t){this.objectId=t}show(){i.default.open(this)}saveEdit(t){t.preventDefault();const e=this.subject.value.trim();""===e?n.default.innerError(this.subject,s.get("wcf.global.form.error.empty")):(n.default.innerError(this.subject,""),a.api(this,{parameters:{subject:e},objectIDs:[this.objectId]}))}getCurrentValue(){return Array.from(document.querySelectorAll(`.jsConversationSubject[data-conversation-id="${this.objectId}"], .conversationLink[data-object-id="${this.objectId}"]`)).map((t=>t.textContent)).slice(-1)[0]}_ajaxSuccess(t){i.default.close(this),document.querySelectorAll(`.jsConversationSubject[data-conversation-id="${this.objectId}"], .conversationLink[data-object-id="${this.objectId}"]`).forEach((e=>{e.textContent=t.returnValues.subject})),r.show()}_dialogSetup(){return{id:"dialogConversationSubjectEditor",options:{onSetup:t=>{this.subject=document.getElementById("jsConversationSubject"),this.subject.addEventListener("keyup",(t=>{"Enter"===t.key&&this.saveEdit(t)})),t.querySelector(".jsButtonSave").addEventListener("click",(t=>{this.saveEdit(t)}))},onShow:()=>{this.subject.value=this.getCurrentValue()},title:s.get("wcf.conversation.edit.subject")},source:`\n        <dl>\n          <dt>\n            <label for="jsConversationSubject">${s.get("wcf.global.subject")}</label>\n          </dt>\n          <dd>\n            <input type="text" id="jsConversationSubject" class="long" maxlength="255">\n          </dd>\n        </dl>\n        <div class="formSubmit">\n          <button type="button" class="button buttonPrimary jsButtonSave">${s.get("wcf.global.button.save")}</button>\n        </div>\n      `}}_ajaxSetup(){return{data:{actionName:"editSubject",className:"wcf\\data\\conversation\\ConversationAction"}}}}let u;e.beginEdit=function(t){u=new c(t),u.show()}})),define("WoltLabSuite/Core/Conversation/Ui/Object/Action/RemoveParticipant",["require","exports","tslib","WoltLabSuite/Core/Ui/Object/Action/Handler"],(function(t,e,o,i){"use strict";function n(t){t.objectElement.querySelector(".userLink").classList.add("conversationLeft"),t.objectElement.querySelector(".jsObjectAction[data-object-action='removeParticipant']").remove()}Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0,i=o.__importDefault(i),e.setup=function(){new i.default("removeParticipant",[],n)}})),define("WoltLabSuite/Core/Conversation/Ui/User/Menu/Data/Conversation",["require","exports","tslib","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Ui/User/Menu/View","WoltLabSuite/Core/Ui/User/Menu/Manager"],(function(t,e,o,i,n,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0,n=o.__importDefault(n);class s{button;counter=0;options;stale=!0;view=void 0;constructor(t,e){this.button=t,this.options=e;const o=t.querySelector(".badge");if(o){const t=parseInt(o.textContent.trim());t&&(this.counter=t)}}getPanelButton(){return this.button}getMenuButtons(){const t=[];return this.options.canStartConversation&&t.push({icon:'<fa-icon size="24" name="plus"></fa-icon>',link:this.options.newConversationLink,name:"newConversation",title:this.options.newConversationTitle}),t}getIdentifier(){return"com.woltlab.wcf.conversation.conversations"}async getData(){const t=await(0,i.dboAction)("getConversations","wcf\\data\\conversation\\ConversationAction").disableLoadingIndicator().dispatch();return this.updateCounter(t.totalCount),this.stale=!1,t.items}getFooter(){return{link:this.options.showAllLink,title:this.options.showAllTitle}}getTitle(){return this.options.title}getView(){return void 0===this.view&&(this.view=new n.default(this)),this.view}getEmptyViewMessage(){return this.options.noItems}hasPlainTitle(){return!0}hasUnreadContent(){return this.counter>0}isStale(){if(this.stale)return!0;const t=this.getView().getItems().filter((t=>"true"===t.dataset.isUnread));return this.counter!==t.length}async markAsRead(t){const e=await(0,i.dboAction)("markAsRead","wcf\\data\\conversation\\ConversationAction").objectIds([t]).dispatch();this.updateCounter(e.totalCount)}async markAllAsRead(){await(0,i.dboAction)("markAllAsRead","wcf\\data\\conversation\\ConversationAction").dispatch(),this.updateCounter(0)}updateCounter(t){let e=this.button.querySelector(".badge");null===e&&t>0&&(e=document.createElement("span"),e.classList.add("badge","badgeUpdate"),this.button.querySelector("a").append(e)),e&&(0===t?e.remove():e.textContent=t.toString()),this.counter=t}}let r=!1;e.setup=function(t){if(!r){const e=document.getElementById("unreadConversations");if(null!==e){const o=new s(e,t);(0,a.registerProvider)(o)}r=!0}}}));
\ No newline at end of file
index cd68f6764673ae0590c8d41fbf603de17340c2a9..91c567fc584930d1421cb5359a8b168d65c1e553 100644 (file)
@@ -1 +1 @@
-define("WoltLabSuite/Core/Conversation/Ui/Message/Quote",["require","exports","WoltLabSuite/Core/Ui/Message/Quote"],(function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.UiConversationMessageQuote=void 0;class o extends i.UiMessageQuote{constructor(t){super(t,"wcf\\data\\conversation\\message\\ConversationMessageAction","com.woltlab.wcf.conversation.message",".message",".messageBody",".messageBody > div > div.messageText",!0)}}e.UiConversationMessageQuote=o,e.default=o})),define("WoltLabSuite/Core/Conversation/Ui/Participant/Add",["require","exports","tslib","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Dom/Util","WoltLabSuite/Core/Ui/Dialog","WoltLabSuite/Core/Ui/Notification","WoltLabSuite/Core/Ui/ItemList/User","WoltLabSuite/Core/Language"],(function(t,e,i,o,n,s,a,r,u){"use strict";o=i.__importStar(o),n=i.__importDefault(n),s=i.__importDefault(s),a=i.__importStar(a),r=i.__importStar(r),u=i.__importStar(u);return class{constructor(t){this.conversationId=t,o.api(this,{actionName:"getAddParticipantsForm"})}_ajaxSetup(){return{data:{className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[this.conversationId]}}}_ajaxSuccess(t){switch(t.actionName){case"addParticipants":this.handleResponse(t);break;case"getAddParticipantsForm":this.render(t)}}handleResponse(t){"errorMessage"in t.returnValues?n.default.innerError(document.getElementById("participantsInput").closest(".inputItemList"),t.returnValues.errorMessage):("count"in t.returnValues&&a.show(t.returnValues.successMessage,(()=>{window.location.reload()})),s.default.close(this))}render(t){s.default.open(this,t.returnValues.template);const e=document.getElementById("addParticipants");e.disabled=!0,r.init("participantsInput",{callbackChange:(t,i)=>{e.disabled=0===i.length},excludedSearchValues:t.returnValues.excludedSearchValues,maxItems:t.returnValues.maxItems,includeUserGroups:t.returnValues.canAddGroupParticipants&&t.returnValues.restrictUserGroupIDs.length>0,restrictUserGroupIDs:t.returnValues.restrictUserGroupIDs,csvPerType:!0}),e.addEventListener("click",(()=>{this.submit()}))}submit(){const t=[],e=[];r.getValues("participantsInput").forEach((i=>{"group"===i.type?e.push(i.objectId):t.push(i.value)}));const i={participants:t,participantsGroupIDs:e,visibility:null},n=s.default.getDialog(this).content.querySelector('input[name="messageVisibility"]:checked, input[name="messageVisibility"][type="hidden"]');n&&(i.visibility=n.value),o.api(this,{actionName:"addParticipants",parameters:i})}_dialogSetup(){return{id:"conversationAddParticipants",options:{title:u.get("wcf.conversation.edit.addParticipants")},source:null}}}})),define("WoltLabSuite/Core/Conversation/Ui/Subject/Editor",["require","exports","tslib","WoltLabSuite/Core/Ui/Dialog","WoltLabSuite/Core/Dom/Util","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Language","WoltLabSuite/Core/Ui/Notification"],(function(t,e,i,o,n,s,a,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.beginEdit=void 0,o=i.__importDefault(o),n=i.__importDefault(n),s=i.__importStar(s),a=i.__importStar(a),r=i.__importStar(r);class u{constructor(t){this.objectId=t}show(){o.default.open(this)}saveEdit(t){t.preventDefault();const e=this.subject.value.trim();""===e?n.default.innerError(this.subject,a.get("wcf.global.form.error.empty")):(n.default.innerError(this.subject,""),s.api(this,{parameters:{subject:e},objectIDs:[this.objectId]}))}getCurrentValue(){return Array.from(document.querySelectorAll(`.jsConversationSubject[data-conversation-id="${this.objectId}"], .conversationLink[data-object-id="${this.objectId}"]`)).map((t=>t.textContent)).slice(-1)[0]}_ajaxSuccess(t){o.default.close(this),document.querySelectorAll(`.jsConversationSubject[data-conversation-id="${this.objectId}"], .conversationLink[data-object-id="${this.objectId}"]`).forEach((e=>{e.textContent=t.returnValues.subject})),r.show()}_dialogSetup(){return{id:"dialogConversationSubjectEditor",options:{onSetup:t=>{this.subject=document.getElementById("jsConversationSubject"),this.subject.addEventListener("keyup",(t=>{"Enter"===t.key&&this.saveEdit(t)})),t.querySelector(".jsButtonSave").addEventListener("click",(t=>{this.saveEdit(t)}))},onShow:()=>{this.subject.value=this.getCurrentValue()},title:a.get("wcf.conversation.edit.subject")},source:`\n        <dl>\n          <dt>\n            <label for="jsConversationSubject">${a.get("wcf.global.subject")}</label>\n          </dt>\n          <dd>\n            <input type="text" id="jsConversationSubject" class="long" maxlength="255">\n          </dd>\n        </dl>\n        <div class="formSubmit">\n          <button class="buttonPrimary jsButtonSave">${a.get("wcf.global.button.save")}</button>\n        </div>\n      `}}_ajaxSetup(){return{data:{actionName:"editSubject",className:"wcf\\data\\conversation\\ConversationAction"}}}}let c;e.beginEdit=function(t){c=new u(t),c.show()}})),define("WoltLabSuite/Core/Conversation/Ui/Object/Action/RemoveParticipant",["require","exports","tslib","WoltLabSuite/Core/Ui/Object/Action/Handler"],(function(t,e,i,o){"use strict";function n(t){t.objectElement.querySelector(".userLink").classList.add("conversationLeft"),t.objectElement.querySelector(".jsObjectAction[data-object-action='removeParticipant']").remove()}Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0,o=i.__importDefault(o),e.setup=function(){new o.default("removeParticipant",[],n)}})),define("WoltLabSuite/Core/Conversation/Ui/User/Menu/Data/Conversation",["require","exports","tslib","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Ui/User/Menu/View","WoltLabSuite/Core/Ui/User/Menu/Manager"],(function(t,e,i,o,n,s){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0,n=i.__importDefault(n);class a{constructor(t,e){this.counter=0,this.stale=!0,this.view=void 0,this.button=t,this.options=e;const i=t.querySelector(".badge");if(i){const t=parseInt(i.textContent.trim());t&&(this.counter=t)}}getPanelButton(){return this.button}getMenuButtons(){const t=[];return this.options.canStartConversation&&t.push({icon:'<span class="icon icon24 fa-plus"></span>',link:this.options.newConversationLink,name:"newConversation",title:this.options.newConversationTitle}),t}getIdentifier(){return"com.woltlab.wcf.conversation.conversations"}async getData(){const t=await(0,o.dboAction)("getConversations","wcf\\data\\conversation\\ConversationAction").disableLoadingIndicator().dispatch();return this.updateCounter(t.totalCount),this.stale=!1,t.items}getFooter(){return{link:this.options.showAllLink,title:this.options.showAllTitle}}getTitle(){return this.options.title}getView(){return void 0===this.view&&(this.view=new n.default(this)),this.view}getEmptyViewMessage(){return this.options.noItems}hasPlainTitle(){return!0}hasUnreadContent(){return this.counter>0}isStale(){if(this.stale)return!0;const t=this.getView().getItems().filter((t=>"true"===t.dataset.isUnread));return this.counter!==t.length}async markAsRead(t){const e=await(0,o.dboAction)("markAsRead","wcf\\data\\conversation\\ConversationAction").objectIds([t]).dispatch();this.updateCounter(e.totalCount)}async markAllAsRead(){await(0,o.dboAction)("markAllAsRead","wcf\\data\\conversation\\ConversationAction").dispatch(),this.updateCounter(0)}updateCounter(t){let e=this.button.querySelector(".badge");null===e&&t>0&&(e=document.createElement("span"),e.classList.add("badge","badgeUpdate"),this.button.querySelector("a").append(e)),e&&(0===t?e.remove():e.textContent=t.toString()),this.counter=t}}let r=!1;e.setup=function(t){if(!r){const e=document.getElementById("unreadConversations");if(null!==e){const i=new a(e,t);(0,s.registerProvider)(i)}r=!0}}}));
\ No newline at end of file
+define("WoltLabSuite/Core/Conversation/Ui/MarkAllAsRead",["require","exports","tslib","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Ui/Notification"],(function(t,e,o,i,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0,n=o.__importStar(n),e.setup=function(){document.querySelectorAll(".markAllAsReadButton").forEach((t=>{t.addEventListener("click",(t=>{t.preventDefault(),async function(){await(0,i.dboAction)("markAllAsRead","wcf\\data\\conversation\\ConversationAction").dispatch(),document.querySelectorAll(".conversationList .new").forEach((t=>{t.classList.remove("new")})),document.querySelector("#unreadConversations .badgeUpdate")?.remove(),n.show()}()}))}))}})),define("WoltLabSuite/Core/Conversation/Ui/MarkAsRead",["require","exports","WoltLabSuite/Core/Ajax"],(function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0;const i=new WeakSet;e.setup=function(){document.querySelectorAll(".conversationList .new .columnAvatar").forEach((t=>{i.has(t)||(i.add(t),t.addEventListener("dblclick",(e=>{e.preventDefault();const i=t.closest(".conversation");i.classList.contains("new")&&async function(t){const e=parseInt(t.dataset.conversationId,10);await(0,o.dboAction)("markAsRead","wcf\\data\\conversation\\ConversationAction").objectIds([e]).dispatch(),t.classList.remove("new"),t.querySelector(".columnAvatar p")?.removeAttribute("title")}(i)}),{once:!0}))}))}})),define("WoltLabSuite/Core/Conversation/Ui/Message/Quote",["require","exports","WoltLabSuite/Core/Ui/Message/Quote"],(function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.UiConversationMessageQuote=void 0;class i extends o.UiMessageQuote{constructor(t){super(t,"wcf\\data\\conversation\\message\\ConversationMessageAction","com.woltlab.wcf.conversation.message",".message",".messageBody",".messageBody > div > div.messageText",!0)}}e.UiConversationMessageQuote=i,e.default=i})),define("WoltLabSuite/Core/Conversation/Ui/Participant/Add",["require","exports","tslib","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Dom/Util","WoltLabSuite/Core/Ui/Dialog","WoltLabSuite/Core/Ui/Notification","WoltLabSuite/Core/Ui/ItemList/User","WoltLabSuite/Core/Language"],(function(t,e,o,i,n,a,s,r,c){"use strict";return i=o.__importStar(i),n=o.__importDefault(n),a=o.__importDefault(a),s=o.__importStar(s),r=o.__importStar(r),c=o.__importStar(c),class{conversationId;constructor(t){this.conversationId=t,i.api(this,{actionName:"getAddParticipantsForm"})}_ajaxSetup(){return{data:{className:"wcf\\data\\conversation\\ConversationAction",objectIDs:[this.conversationId]}}}_ajaxSuccess(t){switch(t.actionName){case"addParticipants":this.handleResponse(t);break;case"getAddParticipantsForm":this.render(t)}}handleResponse(t){"errorMessage"in t.returnValues?n.default.innerError(document.getElementById("participantsInput").closest(".inputItemList"),t.returnValues.errorMessage):("count"in t.returnValues&&s.show(t.returnValues.successMessage,(()=>{window.location.reload()})),a.default.close(this))}render(t){a.default.open(this,t.returnValues.template);const e=document.getElementById("addParticipants");e.disabled=!0,r.init("participantsInput",{callbackChange:(t,o)=>{e.disabled=0===o.length},excludedSearchValues:t.returnValues.excludedSearchValues,maxItems:t.returnValues.maxItems,includeUserGroups:t.returnValues.canAddGroupParticipants&&t.returnValues.restrictUserGroupIDs.length>0,restrictUserGroupIDs:t.returnValues.restrictUserGroupIDs,csvPerType:!0}),e.addEventListener("click",(()=>{this.submit()}))}submit(){const t=[],e=[];r.getValues("participantsInput").forEach((o=>{"group"===o.type?e.push(o.objectId):t.push(o.value)}));const o={participants:t,participantsGroupIDs:e,visibility:null},n=a.default.getDialog(this).content.querySelector('input[name="messageVisibility"]:checked, input[name="messageVisibility"][type="hidden"]');n&&(o.visibility=n.value),i.api(this,{actionName:"addParticipants",parameters:o})}_dialogSetup(){return{id:"conversationAddParticipants",options:{title:c.get("wcf.conversation.edit.addParticipants")},source:null}}}})),define("WoltLabSuite/Core/Conversation/Ui/Subject/Editor",["require","exports","tslib","WoltLabSuite/Core/Ui/Dialog","WoltLabSuite/Core/Dom/Util","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Language","WoltLabSuite/Core/Ui/Notification"],(function(t,e,o,i,n,a,s,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.beginEdit=void 0,i=o.__importDefault(i),n=o.__importDefault(n),a=o.__importStar(a),s=o.__importStar(s),r=o.__importStar(r);class c{objectId;subject;constructor(t){this.objectId=t}show(){i.default.open(this)}saveEdit(t){t.preventDefault();const e=this.subject.value.trim();""===e?n.default.innerError(this.subject,s.get("wcf.global.form.error.empty")):(n.default.innerError(this.subject,""),a.api(this,{parameters:{subject:e},objectIDs:[this.objectId]}))}getCurrentValue(){return Array.from(document.querySelectorAll(`.jsConversationSubject[data-conversation-id="${this.objectId}"], .conversationLink[data-object-id="${this.objectId}"]`)).map((t=>t.textContent)).slice(-1)[0]}_ajaxSuccess(t){i.default.close(this),document.querySelectorAll(`.jsConversationSubject[data-conversation-id="${this.objectId}"], .conversationLink[data-object-id="${this.objectId}"]`).forEach((e=>{e.textContent=t.returnValues.subject})),r.show()}_dialogSetup(){return{id:"dialogConversationSubjectEditor",options:{onSetup:t=>{this.subject=document.getElementById("jsConversationSubject"),this.subject.addEventListener("keyup",(t=>{"Enter"===t.key&&this.saveEdit(t)})),t.querySelector(".jsButtonSave").addEventListener("click",(t=>{this.saveEdit(t)}))},onShow:()=>{this.subject.value=this.getCurrentValue()},title:s.get("wcf.conversation.edit.subject")},source:`\n        <dl>\n          <dt>\n            <label for="jsConversationSubject">${s.get("wcf.global.subject")}</label>\n          </dt>\n          <dd>\n            <input type="text" id="jsConversationSubject" class="long" maxlength="255">\n          </dd>\n        </dl>\n        <div class="formSubmit">\n          <button type="button" class="button buttonPrimary jsButtonSave">${s.get("wcf.global.button.save")}</button>\n        </div>\n      `}}_ajaxSetup(){return{data:{actionName:"editSubject",className:"wcf\\data\\conversation\\ConversationAction"}}}}let u;e.beginEdit=function(t){u=new c(t),u.show()}})),define("WoltLabSuite/Core/Conversation/Ui/Object/Action/RemoveParticipant",["require","exports","tslib","WoltLabSuite/Core/Ui/Object/Action/Handler"],(function(t,e,o,i){"use strict";function n(t){t.objectElement.querySelector(".userLink").classList.add("conversationLeft"),t.objectElement.querySelector(".jsObjectAction[data-object-action='removeParticipant']").remove()}Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0,i=o.__importDefault(i),e.setup=function(){new i.default("removeParticipant",[],n)}})),define("WoltLabSuite/Core/Conversation/Ui/User/Menu/Data/Conversation",["require","exports","tslib","WoltLabSuite/Core/Ajax","WoltLabSuite/Core/Ui/User/Menu/View","WoltLabSuite/Core/Ui/User/Menu/Manager"],(function(t,e,o,i,n,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.setup=void 0,n=o.__importDefault(n);class s{button;counter=0;options;stale=!0;view=void 0;constructor(t,e){this.button=t,this.options=e;const o=t.querySelector(".badge");if(o){const t=parseInt(o.textContent.trim());t&&(this.counter=t)}}getPanelButton(){return this.button}getMenuButtons(){const t=[];return this.options.canStartConversation&&t.push({icon:'<fa-icon size="24" name="plus"></fa-icon>',link:this.options.newConversationLink,name:"newConversation",title:this.options.newConversationTitle}),t}getIdentifier(){return"com.woltlab.wcf.conversation.conversations"}async getData(){const t=await(0,i.dboAction)("getConversations","wcf\\data\\conversation\\ConversationAction").disableLoadingIndicator().dispatch();return this.updateCounter(t.totalCount),this.stale=!1,t.items}getFooter(){return{link:this.options.showAllLink,title:this.options.showAllTitle}}getTitle(){return this.options.title}getView(){return void 0===this.view&&(this.view=new n.default(this)),this.view}getEmptyViewMessage(){return this.options.noItems}hasPlainTitle(){return!0}hasUnreadContent(){return this.counter>0}isStale(){if(this.stale)return!0;const t=this.getView().getItems().filter((t=>"true"===t.dataset.isUnread));return this.counter!==t.length}async markAsRead(t){const e=await(0,i.dboAction)("markAsRead","wcf\\data\\conversation\\ConversationAction").objectIds([t]).dispatch();this.updateCounter(e.totalCount)}async markAllAsRead(){await(0,i.dboAction)("markAllAsRead","wcf\\data\\conversation\\ConversationAction").dispatch(),this.updateCounter(0)}updateCounter(t){let e=this.button.querySelector(".badge");null===e&&t>0&&(e=document.createElement("span"),e.classList.add("badge","badgeUpdate"),this.button.querySelector("a").append(e)),e&&(0===t?e.remove():e.textContent=t.toString()),this.counter=t}}let r=!1;e.setup=function(t){if(!r){const e=document.getElementById("unreadConversations");if(null!==e){const o=new s(e,t);(0,a.registerProvider)(o)}r=!0}}}));
\ No newline at end of file
diff --git a/files/js/WoltLabSuite/Core/Conversation/Ui/MarkAllAsRead.js b/files/js/WoltLabSuite/Core/Conversation/Ui/MarkAllAsRead.js
new file mode 100644 (file)
index 0000000..774fd63
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * Marks all conversations as read.
+ *
+ * @author  Marcel Werk
+ * @copyright  2001-2022 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.0
+ */
+define(["require", "exports", "tslib", "WoltLabSuite/Core/Ajax", "WoltLabSuite/Core/Ui/Notification"], function (require, exports, tslib_1, Ajax_1, UiNotification) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.setup = void 0;
+    UiNotification = tslib_1.__importStar(UiNotification);
+    async function markAllAsRead() {
+        await (0, Ajax_1.dboAction)("markAllAsRead", "wcf\\data\\conversation\\ConversationAction").dispatch();
+        document.querySelectorAll(".conversationList .new").forEach((el) => {
+            el.classList.remove("new");
+        });
+        document.querySelector("#unreadConversations .badgeUpdate")?.remove();
+        UiNotification.show();
+    }
+    function setup() {
+        document.querySelectorAll(".markAllAsReadButton").forEach((el) => {
+            el.addEventListener("click", (event) => {
+                event.preventDefault();
+                void markAllAsRead();
+            });
+        });
+    }
+    exports.setup = setup;
+});
diff --git a/files/js/WoltLabSuite/Core/Conversation/Ui/MarkAsRead.js b/files/js/WoltLabSuite/Core/Conversation/Ui/MarkAsRead.js
new file mode 100644 (file)
index 0000000..788357d
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * Handles the mark as read button for single conversations.
+ *
+ * @author  Marcel Werk
+ * @copyright  2001-2022 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.0
+ */
+define(["require", "exports", "WoltLabSuite/Core/Ajax"], function (require, exports, Ajax_1) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.setup = void 0;
+    const unreadConversations = new WeakSet();
+    async function markAsRead(conversation) {
+        const conversationId = parseInt(conversation.dataset.conversationId, 10);
+        await (0, Ajax_1.dboAction)("markAsRead", "wcf\\data\\conversation\\ConversationAction").objectIds([conversationId]).dispatch();
+        conversation.classList.remove("new");
+        conversation.querySelector(".columnAvatar p")?.removeAttribute("title");
+    }
+    function setup() {
+        document.querySelectorAll(".conversationList .new .columnAvatar").forEach((el) => {
+            if (!unreadConversations.has(el)) {
+                unreadConversations.add(el);
+                el.addEventListener("dblclick", (event) => {
+                    event.preventDefault();
+                    const conversation = el.closest(".conversation");
+                    if (!conversation.classList.contains("new")) {
+                        return;
+                    }
+                    void markAsRead(conversation);
+                }, { once: true });
+            }
+        });
+    }
+    exports.setup = setup;
+});
index 3139f42535fb9bc6f536ba616854b91d29c51727..1a5253d3e5057d2e683700f140f383fa5d2d073b 100644 (file)
@@ -4,7 +4,6 @@
  * @author  Matthias Schmidt
  * @copyright 2001-2021 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module  WoltLabSuite/Core/Conversation/Ui/Message/Quote
  * @woltlabExcludeBundle tiny
  */
 define(["require", "exports", "WoltLabSuite/Core/Ui/Message/Quote"], function (require, exports, Quote_1) {
index 327266deb1304e25070ad11ec3dab3ea946fe744..5c8b18f75ebfb6ddaef11dec412dfd9a55d0f930 100644 (file)
@@ -4,7 +4,6 @@
  * @author  Matthias Schmidt
  * @copyright  2001-2021 WoltLab GmbH
  * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module  WoltLabSuite/Core/Conversation/Ui/Object/Action/RemoveParticipant
  */
 define(["require", "exports", "tslib", "WoltLabSuite/Core/Ui/Object/Action/Handler"], function (require, exports, tslib_1, Handler_1) {
     "use strict";
index 5510dda1d01e773c6883f5cbb49d707796fc7b2e..8979f0c381dc9a2f598d940f5cf1656d998dad0a 100644 (file)
@@ -4,7 +4,6 @@
  * @author  Alexander Ebert
  * @copyright   2001-2021 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module  WoltLabSuite/Core/Conversation/Ui/Participant/Add
  */
 define(["require", "exports", "tslib", "WoltLabSuite/Core/Ajax", "WoltLabSuite/Core/Dom/Util", "WoltLabSuite/Core/Ui/Dialog", "WoltLabSuite/Core/Ui/Notification", "WoltLabSuite/Core/Ui/ItemList/User", "WoltLabSuite/Core/Language"], function (require, exports, tslib_1, Ajax, Util_1, Dialog_1, UiNotification, UiItemListUser, Language) {
     "use strict";
@@ -15,6 +14,7 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Ajax", "WoltLabSuite/C
     UiItemListUser = tslib_1.__importStar(UiItemListUser);
     Language = tslib_1.__importStar(Language);
     class UiParticipantAdd {
+        conversationId;
         constructor(conversationId) {
             this.conversationId = conversationId;
             Ajax.api(this, {
index 944fb6f75d5a70f0872f6cdf1f0b5395e84c4e63..af2d0b8fa1a77ebf32f2fbe6c938a4d690de7161 100644 (file)
@@ -8,6 +8,8 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Ui/Dialog", "WoltLabSu
     Language = tslib_1.__importStar(Language);
     UiNotification = tslib_1.__importStar(UiNotification);
     class UiSubjectEditor {
+        objectId;
+        subject;
         constructor(objectId) {
             this.objectId = objectId;
         }
@@ -83,7 +85,7 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Ui/Dialog", "WoltLabSu
           </dd>
         </dl>
         <div class="formSubmit">
-          <button class="buttonPrimary jsButtonSave">${Language.get("wcf.global.button.save")}</button>
+          <button type="button" class="button buttonPrimary jsButtonSave">${Language.get("wcf.global.button.save")}</button>
         </div>
       `,
             };
index 75e79acc32a258a90aa1bab827729858c5a6c408..08a604b16862f1428ce5242bd06fc0c1c2b6bbcb 100644 (file)
@@ -4,7 +4,6 @@
  * @author Alexander Ebert
  * @copyright 2001-2021 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Ui/User/Menu/Data/Notification
  * @woltlabExcludeBundle tiny
  */
 define(["require", "exports", "tslib", "WoltLabSuite/Core/Ajax", "WoltLabSuite/Core/Ui/User/Menu/View", "WoltLabSuite/Core/Ui/User/Menu/Manager"], function (require, exports, tslib_1, Ajax_1, View_1, Manager_1) {
@@ -13,10 +12,12 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Ajax", "WoltLabSuite/C
     exports.setup = void 0;
     View_1 = tslib_1.__importDefault(View_1);
     class UserMenuDataConversation {
+        button;
+        counter = 0;
+        options;
+        stale = true;
+        view = undefined;
         constructor(button, options) {
-            this.counter = 0;
-            this.stale = true;
-            this.view = undefined;
             this.button = button;
             this.options = options;
             const badge = button.querySelector(".badge");
@@ -34,7 +35,7 @@ define(["require", "exports", "tslib", "WoltLabSuite/Core/Ajax", "WoltLabSuite/C
             const buttons = [];
             if (this.options.canStartConversation) {
                 buttons.push({
-                    icon: '<span class="icon icon24 fa-plus"></span>',
+                    icon: '<fa-icon size="24" name="plus"></fa-icon>',
                     link: this.options.newConversationLink,
                     name: "newConversation",
                     title: this.options.newConversationTitle,
diff --git a/files/lib/bootstrap/com.woltlab.wcf.conversation.php b/files/lib/bootstrap/com.woltlab.wcf.conversation.php
new file mode 100644 (file)
index 0000000..95d9bba
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+
+use wcf\system\event\EventHandler;
+use wcf\system\worker\event\RebuildWorkerCollecting;
+
+return static function (): void {
+    $eventHandler = EventHandler::getInstance();
+
+    $eventHandler->register(RebuildWorkerCollecting::class, static function (RebuildWorkerCollecting $event) {
+        $event->register(\wcf\system\worker\ConversationMessageRebuildDataWorker::class, -5);
+        $event->register(\wcf\system\worker\ConversationRebuildDataWorker::class, 0);
+        $event->register(\wcf\system\worker\ConversationMessageSearchIndexRebuildDataWorker::class, 300);
+    });
+};
index c553c2c6d746ca484d54bddd4334cf9a190b2b32..d0c8afc9193aede0bec34ed4f9a54c97045787bd 100644 (file)
@@ -24,7 +24,6 @@ use wcf\util\ArrayUtil;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
  *
  * @property-read   int $conversationID     unique id of the conversation
  * @property-read   string $subject        subject of the conversation
@@ -57,19 +56,19 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
      * default participation state
      * @var int
      */
-    const STATE_DEFAULT = 0;
+    public const STATE_DEFAULT = 0;
 
     /**
      * conversation is hidden but returns visible upon new message
      * @var int
      */
-    const STATE_HIDDEN = 1;
+    public const STATE_HIDDEN = 1;
 
     /**
      * conversation was left permanently
      * @var int
      */
-    const STATE_LEFT/*4DEAD*/ = 2;
+    public const STATE_LEFT/*4DEAD*/ = 2;
 
     /**
      * true if the current user can add users without limitations
@@ -92,7 +91,7 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
     /**
      * @inheritDoc
      */
-    public function getTitle()
+    public function getTitle(): string
     {
         return $this->subject;
     }
@@ -100,7 +99,7 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
     /**
      * @inheritDoc
      */
-    public function getLink()
+    public function getLink(): string
     {
         return LinkHandler::getInstance()->getLink('Conversation', [
             'object' => $this,
@@ -110,10 +109,8 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
 
     /**
      * Returns true if this conversation is new for the active user.
-     *
-     * @return  bool
      */
-    public function isNew()
+    public function isNew(): bool
     {
         if (!$this->isDraft && $this->lastPostTime > $this->lastVisitTime) {
             return true;
@@ -124,11 +121,8 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
 
     /**
      * Returns true if the active user doesn't have read the given message.
-     *
-     * @param ConversationMessage $message
-     * @return  bool
      */
-    public function isNewMessage(ConversationMessage $message)
+    public function isNewMessage(ConversationMessage $message): bool
     {
         if (!$this->isDraft && $message->time > $this->lastVisitTime) {
             return true;
@@ -139,10 +133,8 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
 
     /**
      * Returns true if the conversation is not closed or the user was not removed.
-     *
-     * @return      bool
      */
-    public function canReply()
+    public function canReply(): bool
     {
         if (!$this->canRead()) {
             return false;
@@ -243,10 +235,8 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
 
     /**
      * Returns true if the active user has the permission to read this conversation.
-     *
-     * @return  bool
      */
-    public function canRead()
+    public function canRead(): bool
     {
         if (!WCF::getUser()->userID) {
             return false;
@@ -265,10 +255,8 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
 
     /**
      * Returns true if the current user can add new participants to this conversation.
-     *
-     * @return  bool
      */
-    public function canAddParticipants()
+    public function canAddParticipants(): bool
     {
         if ($this->isDraft) {
             return false;
@@ -299,10 +287,8 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
 
     /**
      * Returns true if the current user can add participants without limitations.
-     *
-     * @return      bool
      */
-    public function canAddParticipantsUnrestricted()
+    public function canAddParticipantsUnrestricted(): bool
     {
         if ($this->canAddUnrestricted === null) {
             $this->canAddUnrestricted = false;
@@ -406,10 +392,8 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
 
     /**
      * Returns false if the active user is the last participant of this conversation.
-     *
-     * @return  bool
      */
-    public function hasOtherParticipants()
+    public function hasOtherParticipants(): bool
     {
         if ($this->userID == WCF::getUser()->userID) {
             // author
@@ -448,10 +432,8 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
 
     /**
      * Returns true if the current user is an active participant of this conversation.
-     *
-     * @return      bool
      */
-    public function isActiveParticipant()
+    public function isActiveParticipant(): bool
     {
         if ($this->isActiveParticipant === null) {
             $sql = "SELECT  leftAt
@@ -474,7 +456,7 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
     /**
      * @inheritDoc
      */
-    public function getPopoverLinkClass()
+    public function getPopoverLinkClass(): string
     {
         return 'conversationLink';
     }
@@ -485,9 +467,8 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
      *
      * @param int[] $conversationIDs
      * @param int $userID
-     * @return  bool
      */
-    public static function isParticipant(array $conversationIDs, $userID = null)
+    public static function isParticipant(array $conversationIDs, $userID = null): bool
     {
         if ($userID === null) {
             $userID = WCF::getUser()->userID;
index d21b0fe6ce63d49c80a623ed71eef1ea70f66cb8..335ecbb5d07e893f229c14de83b1daf90f97fdb9 100644 (file)
@@ -22,6 +22,7 @@ use wcf\system\exception\UserInputException;
 use wcf\system\log\modification\ConversationModificationLogHandler;
 use wcf\system\request\LinkHandler;
 use wcf\system\search\SearchIndexManager;
+use wcf\system\style\FontAwesomeIcon;
 use wcf\system\user\notification\object\ConversationUserNotificationObject;
 use wcf\system\user\notification\UserNotificationHandler;
 use wcf\system\user\storage\UserStorageHandler;
@@ -33,7 +34,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
  *
  * @method  ConversationEditor[]    getObjects()
  * @method  ConversationEditor  getSingleObject()
@@ -757,85 +757,6 @@ class ConversationAction extends AbstractDatabaseObjectAction implements
         ];
     }
 
-    /**
-     * Validates parameters to return the mixed conversation list.
-     *
-     * @deprecated 5.5
-     */
-    public function validateGetMixedConversationList()
-    {
-        // does nothing
-    }
-
-    /**
-     * Returns a mixed conversation list with up to 10 unread conversations.
-     *
-     * @return  mixed[][]
-     * @deprecated 5.5 This method provided the data for the legacy user panel implementation.
-     */
-    public function getMixedConversationList()
-    {
-        $sqlSelect = '  , (
-            SELECT      participantID
-            FROM        wcf' . WCF_N . '_conversation_to_user
-            WHERE       conversationID = conversation.conversationID
-                    AND participantID <> conversation.userID
-                    AND isInvisible = 0
-            ORDER BY    username, participantID
-            LIMIT 1
-        ) AS otherParticipantID
-        , (
-            SELECT      username
-            FROM        wcf' . WCF_N . '_conversation_to_user
-            WHERE       conversationID = conversation.conversationID
-                    AND participantID <> conversation.userID
-                    AND isInvisible = 0
-            ORDER BY    username, participantID
-            LIMIT       1
-        ) AS otherParticipant';
-
-        $unreadConversationList = new UserConversationList(WCF::getUser()->userID);
-        $unreadConversationList->sqlSelects .= $sqlSelect;
-        $unreadConversationList->getConditionBuilder()->add('conversation_to_user.lastVisitTime < lastPostTime');
-        $unreadConversationList->sqlLimit = 10;
-        $unreadConversationList->sqlOrderBy = 'lastPostTime DESC';
-        $unreadConversationList->readObjects();
-
-        $conversations = [];
-        $count = 0;
-        foreach ($unreadConversationList as $conversation) {
-            $conversations[] = $conversation;
-            $count++;
-        }
-
-        if ($count < 10) {
-            $conversationList = new UserConversationList(WCF::getUser()->userID);
-            $conversationList->sqlSelects .= $sqlSelect;
-            $conversationList->getConditionBuilder()->add('conversation_to_user.lastVisitTime >= lastPostTime');
-            $conversationList->sqlLimit = (10 - $count);
-            $conversationList->sqlOrderBy = 'lastPostTime DESC';
-            $conversationList->readObjects();
-
-            foreach ($conversationList as $conversation) {
-                $conversations[] = $conversation;
-            }
-        }
-
-        WCF::getTPL()->assign([
-            'conversations' => $conversations,
-        ]);
-
-        $totalCount = ConversationHandler::getInstance()->getUnreadConversationCount();
-        if ($count < 10 && $count < $totalCount) {
-            UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
-        }
-
-        return [
-            'template' => WCF::getTPL()->fetch('conversationListUserPanel'),
-            'totalCount' => $totalCount,
-        ];
-    }
-
     /**
      * @since 5.5
      */
@@ -909,7 +830,7 @@ class ConversationAction extends AbstractDatabaseObjectAction implements
         $conversations = \array_map(static function (ViewableConversation $conversation) {
             if ($conversation->userID === WCF::getUser()->userID) {
                 if ($conversation->participants > 1) {
-                    $image = '<span class="icon icon48 fa-users"></span>';
+                    $image = FontAwesomeIcon::fromValues('users')->toHtml(48);
                     $usernames = \array_column($conversation->getParticipantSummary(), 'username');
                 } else {
                     $image = $conversation->getOtherParticipantProfile()->getAvatar()->getImageTag(48);
@@ -917,7 +838,7 @@ class ConversationAction extends AbstractDatabaseObjectAction implements
                 }
             } else {
                 if ($conversation->participants > 1) {
-                    $image = '<span class="icon icon48 fa-users"></span>';
+                    $image = FontAwesomeIcon::fromValues('users')->toHtml(48);
                     $usernames = \array_filter($conversation->getParticipantNames(), static function ($username) use ($conversation) {
                         return $username !== $conversation->getUserProfile()->username;
                     });
index 1c98e7806032ca7f80071cec2095403362f07750..85603562c425038ed6133a2a9f5d053dce6dca5e 100644 (file)
@@ -13,7 +13,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
  *
  * @method static Conversation    create(array $parameters = [])
  * @method      Conversation    getDecoratedObject()
index 5bb4973c00efbf5def6ae58db93796be94587bf8..8118d6a11242c18ed125a50701d43fb51ac48115 100644 (file)
@@ -10,7 +10,6 @@ use wcf\data\DatabaseObjectList;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
  *
  * @method  Conversation        current()
  * @method  Conversation[]      getObjects()
index a9de865fd9744acf462abed815497a3ab47a1e6b..f57259f0d945da17b2e3176131d108960bbe2f39 100644 (file)
@@ -12,7 +12,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
  */
 class ConversationParticipantList extends UserProfileList
 {
index 94dabc3ddbe9b701ddbe9015385453d266c0696d..3789a4ec4ebb88abaa47dac13f90d6892df224fa 100644 (file)
@@ -12,7 +12,6 @@ use wcf\system\request\LinkHandler;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
  *
  * @method  Conversation    getDecoratedObject()
  * @mixin   Conversation
@@ -27,7 +26,7 @@ class FeedConversation extends DatabaseObjectDecorator implements IFeedEntry
     /**
      * @inheritDoc
      */
-    public function getLink()
+    public function getLink(): string
     {
         return LinkHandler::getInstance()->getLink('Conversation', [
             'object' => $this->getDecoratedObject(),
@@ -38,7 +37,7 @@ class FeedConversation extends DatabaseObjectDecorator implements IFeedEntry
     /**
      * @inheritDoc
      */
-    public function getTitle()
+    public function getTitle(): string
     {
         return $this->getDecoratedObject()->getTitle();
     }
@@ -46,7 +45,7 @@ class FeedConversation extends DatabaseObjectDecorator implements IFeedEntry
     /**
      * @inheritDoc
      */
-    public function getFormattedMessage()
+    public function getFormattedMessage(): string
     {
         return '';
     }
@@ -54,7 +53,7 @@ class FeedConversation extends DatabaseObjectDecorator implements IFeedEntry
     /**
      * @inheritDoc
      */
-    public function getMessage()
+    public function getMessage(): string
     {
         return '';
     }
@@ -62,7 +61,7 @@ class FeedConversation extends DatabaseObjectDecorator implements IFeedEntry
     /**
      * @inheritDoc
      */
-    public function getExcerpt($maxLength = 255)
+    public function getExcerpt($maxLength = 255): string
     {
         return '';
     }
@@ -78,7 +77,7 @@ class FeedConversation extends DatabaseObjectDecorator implements IFeedEntry
     /**
      * @inheritDoc
      */
-    public function getUsername()
+    public function getUsername(): string
     {
         return $this->getDecoratedObject()->lastPoster;
     }
@@ -94,7 +93,7 @@ class FeedConversation extends DatabaseObjectDecorator implements IFeedEntry
     /**
      * @inheritDoc
      */
-    public function __toString()
+    public function __toString(): string
     {
         return $this->getFormattedMessage();
     }
index 3dcf198d90fe615a6307be6877631f157a804889..7575d6aa588c04cd403bd84b40debf9477ced927 100644 (file)
@@ -10,7 +10,6 @@ use wcf\system\WCF;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
  *
  * @method  FeedConversation    current()
  * @method  FeedConversation[]  getObjects()
index 4c24b19949b79fecae190c363a26c2678a873734..305250a2e4d17a62a67b77c5be84c1be5be5de75 100644 (file)
@@ -14,7 +14,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
  *
  * @method  ViewableConversation        current()
  * @method  ViewableConversation[]      getObjects()
@@ -107,6 +106,7 @@ class UserConversationList extends ConversationList
             conversation.*,
             (CASE
                 WHEN    conversation_to_user.leftAt <> 0
+                        AND conversation.lastPostTime > conversation_to_user.leftAt
                 THEN    conversation_to_user.leftAt
                 ELSE    conversation.lastPostTime
             END) AS lastPostTime";
index 165c2badbc7f2b59284c707e6586503ffb4fa7e9..e6e5e2d17fd372c71136a5a95d32aa29ef655144 100644 (file)
@@ -17,7 +17,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
  *
  * @method  Conversation    getDecoratedObject()
  * @mixin   Conversation
index d8141a8b715ab7a4f9f6b4692b604cd2c16c76db..e3b9a87ebc7df23ab4ffb8e39c0ea642d413840b 100644 (file)
@@ -11,7 +11,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
  *
  * @property-read   int $labelID    unique id of the conversation label
  * @property-read   int $userID     id of the user who created the conversation label
index 577cb7ef364b7170b80f387f503675b3ee5503b5..9a3f4323bf4b1ca193e0c6af9e0930e96a8936a9 100644 (file)
@@ -19,7 +19,6 @@ use wcf\util\StringUtil;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
  *
  * @method  ConversationLabel       create()
  * @method  ConversationLabelEditor[]   getObjects()
index 525c8c2861843a5fe5f5c1b53e6b36b6d8ba1476..9b1d3af071988f7f7336dfd81691790f00966eaf 100644 (file)
@@ -10,7 +10,6 @@ use wcf\data\DatabaseObjectEditor;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
  *
  * @method static ConversationLabel   create(array $parameters = [])
  * @method      ConversationLabel   getDecoratedObject()
index b6ba884c4565a99fb88645083d5561d2fa735d1e..b99786e12ea69d5dddb0d83100ac1c8cc95065cb 100644 (file)
@@ -10,7 +10,6 @@ use wcf\data\DatabaseObjectList;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
  *
  * @method  ConversationLabel       current()
  * @method  ConversationLabel[]     getObjects()
index 548ae64785ba20b34ebdfd385c2f015f2e3f081d..4dec86e4159d673979d1b415016a99ade75840f9 100644 (file)
@@ -18,7 +18,6 @@ use wcf\util\StringUtil;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
  *
  * @property-read   int $messageID      unique id of the conversation message
  * @property-read   int $conversationID     id of the conversation the conversation message belongs to
@@ -46,7 +45,7 @@ class ConversationMessage extends DatabaseObject implements IMessage
     /**
      * @inheritDoc
      */
-    public function getFormattedMessage()
+    public function getFormattedMessage(): string
     {
         $processor = new HtmlOutputProcessor();
         $processor->process($this->message, 'com.woltlab.wcf.conversation.message', $this->messageID);
@@ -56,10 +55,8 @@ class ConversationMessage extends DatabaseObject implements IMessage
 
     /**
      * Returns a simplified version of the formatted message.
-     *
-     * @return  string
      */
-    public function getSimplifiedFormattedMessage()
+    public function getSimplifiedFormattedMessage(): string
     {
         $processor = new HtmlOutputProcessor();
         $processor->setOutputType('text/simplified-html');
@@ -98,7 +95,7 @@ class ConversationMessage extends DatabaseObject implements IMessage
     /**
      * @inheritDoc
      */
-    public function getExcerpt($maxLength = 255)
+    public function getExcerpt($maxLength = 255): string
     {
         return StringUtil::truncateHTML($this->getSimplifiedFormattedMessage(), $maxLength);
     }
@@ -107,9 +104,8 @@ class ConversationMessage extends DatabaseObject implements IMessage
      * Returns a version of this message optimized for use in emails.
      *
      * @param string $mimeType Either 'text/plain' or 'text/html'
-     * @return  string
      */
-    public function getMailText($mimeType = 'text/plain')
+    public function getMailText($mimeType = 'text/plain'): string
     {
         switch ($mimeType) {
             case 'text/plain':
@@ -153,10 +149,8 @@ class ConversationMessage extends DatabaseObject implements IMessage
 
     /**
      * Returns true if current user may edit this message.
-     *
-     * @return  bool
      */
-    public function canEdit()
+    public function canEdit(): bool
     {
         return WCF::getUser()->userID == $this->userID
             && (
@@ -169,7 +163,7 @@ class ConversationMessage extends DatabaseObject implements IMessage
     /**
      * @inheritDoc
      */
-    public function getMessage()
+    public function getMessage(): string
     {
         return $this->message;
     }
@@ -177,7 +171,7 @@ class ConversationMessage extends DatabaseObject implements IMessage
     /**
      * @inheritDoc
      */
-    public function getLink()
+    public function getLink(): string
     {
         return LinkHandler::getInstance()->getLink('Conversation', [
             'object' => $this->getConversation(),
@@ -189,7 +183,7 @@ class ConversationMessage extends DatabaseObject implements IMessage
     /**
      * @inheritDoc
      */
-    public function getTitle()
+    public function getTitle(): string
     {
         if ($this->messageID == $this->getConversation()->firstMessageID) {
             return $this->getConversation()->subject;
@@ -201,7 +195,7 @@ class ConversationMessage extends DatabaseObject implements IMessage
     /**
      * @inheritDoc
      */
-    public function isVisible()
+    public function isVisible(): bool
     {
         return true;
     }
@@ -209,7 +203,7 @@ class ConversationMessage extends DatabaseObject implements IMessage
     /**
      * @inheritDoc
      */
-    public function __toString()
+    public function __toString(): string
     {
         return $this->getFormattedMessage();
     }
index 1f7c1078f4faa7bfda04074aede5cfa6aa100dc9..7890b605732d4320f183f3fe6f5e63f71c153652 100644 (file)
@@ -39,7 +39,6 @@ use wcf\util\UserUtil;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
  *
  * @method  ConversationMessageEditor[] getObjects()
  * @method  ConversationMessageEditor   getSingleObject()
index 694118b0d819ad9659a2684da6810de8e8197f6c..4d0c62cb33b01ec20a82e865a4c5c77e55a50b13 100644 (file)
@@ -10,7 +10,6 @@ use wcf\data\DatabaseObjectEditor;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
  *
  * @method static ConversationMessage create(array $parameters = [])
  * @method      ConversationMessage getDecoratedObject()
index df13dd4742ab073b2179c1e1522ab02ecff415b2..20b1990e1ca19c8b44e0c943b176e012cd6ed0c6 100644 (file)
@@ -10,7 +10,6 @@ use wcf\data\DatabaseObjectList;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
  *
  * @method  ConversationMessage     current()
  * @method  ConversationMessage[]       getObjects()
index d00005631710d274812d4121f12d333f9b1c0f3f..342e4deea826c4a4b789b3abaae08c4342f7aa90 100644 (file)
@@ -13,7 +13,6 @@ use wcf\system\search\SearchResultTextParser;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
  *
  * @property-read   string|null $subject
  */
index f5475c956e6b1a25cd201a4068323aea3e3d0d36..a5449d581f09cfa5fe8cd4af6df0ec08fc4a93ca 100644 (file)
@@ -8,7 +8,6 @@ namespace wcf\data\conversation\message;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
  *
  * @method  SearchResultConversationMessage     current()
  * @method  SearchResultConversationMessage[]   getObjects()
index aa74800c5bd5d91c28c53bd22d3198344ad60d25..3edaf7a47d230ebc15244b4b27284f815de912c4 100644 (file)
@@ -9,7 +9,6 @@ namespace wcf\data\conversation\message;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
  */
 class SimplifiedViewableConversationMessageList extends ViewableConversationMessageList
 {
index 2315d46bbba80d3eecddf200df59c7f996cb8b88..a030ba709c372c238389fa9c07d11f853c460aff 100644 (file)
@@ -12,7 +12,6 @@ use wcf\system\cache\runtime\UserProfileRuntimeCache;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
  *
  * @method  ConversationMessage getDecoratedObject()
  * @mixin   ConversationMessage
index 79a24db604c2ae2641b4f42199071f5247edce86..34c02ee3f8c0791da31c6ed05366ba31cc43cdb5 100644 (file)
@@ -14,7 +14,6 @@ use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
  *
  * @method  ViewableConversationMessage     current()
  * @method  ViewableConversationMessage[]       getObjects()
index 5628b37dcbd74d27a5cdb301848746eaa91cb373..919f285dd08121bcbb404709ed4acc50389bfec8 100644 (file)
@@ -12,7 +12,6 @@ use wcf\system\WCF;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Modification\Log
  *
  * @method  ViewableConversationModificationLog     current()
  * @method  ViewableConversationModificationLog[]       getObjects()
index 210e1e590eac93998cd0d78d02e84ba603864344..ce4bbf0192b7b388f51c4adfbdc45d1cdb29e3a4 100644 (file)
@@ -13,7 +13,6 @@ use wcf\system\WCF;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Modification\Log
  *
  * @method  ModificationLog     getDecoratedObject()
  * @mixin   ModificationLog
index 0027ef11cb7550dd986d4cb3e2577a16c50315a8..ffd4778796acfa339daaa7c44e8fada81784aa37 100644 (file)
@@ -26,7 +26,6 @@ use wcf\util\StringUtil;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Form
  */
 class ConversationAddForm extends MessageForm
 {
index a3624000a9ad3f3a6e14c45c3c325b2c025c5b24..c373385c1addd159c2510604b8bbce5f5d7683b8 100644 (file)
@@ -19,7 +19,6 @@ use wcf\util\HeaderUtil;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Form
  */
 class ConversationDraftEditForm extends ConversationAddForm
 {
index 8910a2d76218e16d145aa5c8d338394e3c3a0cdc..3a0956a17476b81416c453703f06fa33cf7c70f1 100644 (file)
@@ -11,7 +11,6 @@ use wcf\system\WCF;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Page
  */
 class ConversationFeedPage extends AbstractFeedPage
 {
index 1ad9c850e47b219b4bd31556fcd780250b91c931..3c9897ef0b7456fa0180dc0d82d96360e6f705b4 100644 (file)
@@ -20,7 +20,6 @@ use wcf\util\HeaderUtil;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Page
  *
  * @property    UserConversationList $objectList
  */
@@ -202,7 +201,7 @@ class ConversationListPage extends SortablePage
             if (!empty($userIDs)) {
                 // The condition is split into two branches in order to account for invisible participants.
                 // Invisible participants are only visible to the conversation starter and remain invisible
-                // until the write their first message.
+                // until they write their first message.
                 //
                 // We need to protect these users from being exposed as participants by including them for
                 // any conversation that the current user has started. For all other conversations, users
index b7b2ec11a53dbafb3c00721eb67ffc505a03eed2..07b869c6fad3461c0c9765dd205277c284a0b0f3 100644 (file)
@@ -24,7 +24,6 @@ use wcf\system\request\LinkHandler;
 use wcf\system\user\signature\SignatureCache;
 use wcf\system\WCF;
 use wcf\util\HeaderUtil;
-use wcf\util\StringUtil;
 
 /**
  * Shows a conversation.
@@ -32,7 +31,6 @@ use wcf\util\StringUtil;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Page
  *
  * @property    ViewableConversationMessageList $objectList
  */
@@ -324,7 +322,13 @@ class ConversationPage extends MultipleLinkPage
 
         MessageQuoteManager::getInstance()->assignVariables();
 
-        $tmpHash = StringUtil::getRandomID();
+        $tmpHash = \sha1(\implode("\0", [
+            // Use class name + conversation ID to match the autosave scoping.
+            self::class,
+            $this->conversation->conversationID,
+            // Bind the tmpHash to the current session to make it unguessable.
+            WCF::getSession()->sessionID,
+        ]));
         $attachmentHandler = new AttachmentHandler('com.woltlab.wcf.conversation.message', 0, $tmpHash, 0);
 
         WCF::getTPL()->assign([
index 621c1ed7d5205434a866839f4cd40bcbf3766ea9..c6964c207ec3f08d0c61a71ef587902c2171ffc0 100644 (file)
@@ -14,7 +14,6 @@ use wcf\util\ArrayUtil;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Attachment
  *
  * @method  ConversationMessage getObject($objectID)
  */
index 91a3e8cad2b592afe9f3c10126037fb130c2dc6c..8f5f9a2c9bd5ea623264c1bd4575b50e2de41d96 100644 (file)
@@ -11,7 +11,6 @@ use wcf\data\conversation\ConversationList;
  * @author  Matthias Schmidt
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Cache\Runtime
  * @since   3.0
  *
  * @method  Conversation[]      getCachedObjects()
index 4d329170f9de2145034a7e64a05c92f7f3261002..df671b46cd5c9003657c416df9c487f92ec34197 100644 (file)
@@ -12,7 +12,6 @@ use wcf\system\WCF;
  * @author  Matthias Schmidt
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Cache\Runtime
  * @since   3.0
  *
  * @method  Conversation[]      getCachedObjects()
index e802babfaf8a18837ddd4947f454cd6bac7d1afc..cddeb69af387a3d0248a6c8d442734d47aed5a51 100644 (file)
@@ -14,7 +14,6 @@ use wcf\system\WCF;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Clipboard\Action
  */
 class ConversationClipboardAction extends AbstractClipboardAction
 {
index 3490d20d4dff0cff4cb7a75a5ef9ad6ed78d6653..210622f423e96e12823b1673aa54f09987e62d3c 100644 (file)
@@ -16,7 +16,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Conversation
  */
 class ConversationHandler extends SingletonFactory
 {
index a35df3e90620fcd1436e442b8bbd29c31fc44f50..4f5e50c2106b131b43cde7a09b7d5bd278a55b7f 100644 (file)
@@ -10,7 +10,6 @@ use wcf\system\cronjob\PruneIpAddressesCronjob;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
  * @since       5.2
  */
 class ConversationPruneIpAddressesCronjobListener implements IParameterizedEventListener
index 3eb89219cf049ac652f80f6d16ff62cfe9c5b177..563b62af02a0f520a62e7fe2a689f9218d9f7020 100644 (file)
@@ -8,7 +8,6 @@ namespace wcf\system\event\listener;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
  */
 class ConversationUserActionRenameListener extends AbstractUserActionRenameListener
 {
index 7cb15ccd08f9ed5ed7e83661c658a46da43717e3..e250f643f37e6b4072a15bc228390b372fece5f9 100644 (file)
@@ -8,7 +8,6 @@ namespace wcf\system\event\listener;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
  */
 class ConversationUserMergeListener extends AbstractUserMergeListener
 {
index 09594f1d31eca6d4e40d42f821619e1b958ba013..752df02f59d34d614b854266f16ced681b6d6614 100644 (file)
@@ -13,7 +13,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
  */
 class UserGroupAddCanBeAddedAsConversationParticipantListener implements IParameterizedEventListener
 {
index eb1e6035515b3092a795d541618a769785a58eb1..3bc7c527f22dc3ec1b8ef2af60d2573c153571de 100644 (file)
@@ -12,7 +12,6 @@ use wcf\data\object\type\ObjectTypeCache;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
  */
 class ConversationAttachmentImporter extends AbstractAttachmentImporter
 {
index 4db0a301a7d07eb161f1e017c941374546aa01e8..3712d2a3e13889d9e14eed4abd2c76b927be3623 100644 (file)
@@ -11,7 +11,6 @@ use wcf\data\conversation\ConversationEditor;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
  */
 class ConversationImporter extends AbstractImporter
 {
index ad7130b9ce605ab35c23c1d7307fe395e5ec67ec..06d90ed3fcf43b1d8a0acddeb906952c2728ca87 100644 (file)
@@ -11,7 +11,6 @@ use wcf\data\conversation\label\ConversationLabelAction;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
  */
 class ConversationLabelImporter extends AbstractImporter
 {
index 11bec63269516a4f4532db25e8ed06e5af4bda7b..af1ed60ec2170dabff94df75625c3f201a6d5022 100644 (file)
@@ -11,7 +11,6 @@ use wcf\data\conversation\message\ConversationMessageEditor;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
  */
 class ConversationMessageImporter extends AbstractImporter
 {
index e638ed3283fdc5c53aba19c8f5727ca113acf223..9b6049e2d8dc4b86b72bb9d1945a2170e7f2ccff 100644 (file)
@@ -10,7 +10,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
  */
 class ConversationUserImporter extends AbstractImporter
 {
@@ -26,13 +25,13 @@ class ConversationUserImporter extends AbstractImporter
         }
         $data['participantID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['participantID']);
 
-        $sql = "INSERT INTO             wcf" . WCF_N . "_conversation_to_user
+        $sql = "INSERT INTO             wcf1_conversation_to_user
                                         (conversationID, participantID, username, hideConversation, isInvisible, lastVisitTime)
                 VALUES                  (?, ?, ?, ?, ?, ?)
                 ON DUPLICATE KEY UPDATE hideConversation = IF(hideConversation > 0 AND hideConversation = VALUES(hideConversation),hideConversation,0),
                                         isInvisible = IF(isInvisible AND VALUES(isInvisible),1,0),
                                         lastVisitTime = GREATEST(lastVisitTime,VALUES(lastVisitTime))";
-        $statement = WCF::getDB()->prepareStatement($sql);
+        $statement = WCF::getDB()->prepare($sql);
         $statement->execute([
             $data['conversationID'],
             $data['participantID'],
@@ -44,10 +43,10 @@ class ConversationUserImporter extends AbstractImporter
 
         // save labels
         if ($data['participantID'] && !empty($additionalData['labelIDs'])) {
-            $sql = "INSERT IGNORE INTO  wcf" . WCF_N . "_conversation_label_to_object
+            $sql = "INSERT IGNORE INTO  wcf1_conversation_label_to_object
                                         (labelID, conversationID)
                     VALUES              (?, ?)";
-            $statement = WCF::getDB()->prepareStatement($sql);
+            $statement = WCF::getDB()->prepare($sql);
             foreach ($additionalData['labelIDs'] as $labelID) {
                 $labelID = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.conversation.label', $labelID);
                 if ($labelID) {
index 4ee9cc8bfccde779cdb7e8802cdbed9920844eeb..334b1d78c039e213aaf725b019ee1ac84acf2ae1 100644 (file)
@@ -12,7 +12,6 @@ use wcf\data\user\UserList;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Log\Modification
  */
 class ConversationModificationLogHandler extends VoidExtendedModificationLogHandler
 {
index dfa7060076415ee8d6d73a6b3f91e8261e21a047..60f6457bcbe0d509e6833f9160c93ca076cfd22c 100644 (file)
@@ -11,7 +11,6 @@ use wcf\data\conversation\message\ConversationMessageList;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Message\Quote
  */
 class ConversationMessageQuoteHandler extends AbstractMessageQuoteHandler
 {
index 8edd3c2587694580493c99fad52fd49f38f5821c..17e8a13c8582a255db681bd966245f04af6a67a1 100644 (file)
@@ -20,7 +20,6 @@ use wcf\system\WCF;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Moderation\Queue
  */
 class ConversationMessageModerationQueueReportHandler extends AbstractModerationQueueHandler implements
     IModerationQueueReportHandler
index 785b2b650f6f74fee68e69bb9d33964c3d3688c9..8dd0e5efd28ca2680d3128e9796e43b5f78cff07 100644 (file)
@@ -11,7 +11,6 @@ use wcf\system\WCF;
  * @author  Matthias Schmidt
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Page\Handler
  * @since   3.0
  */
 class ConversationListPageHandler extends AbstractMenuPageHandler
index 974f088ffc679a06815ea01865a94dac749d9f1e..b2f89d0f77618d25d1742936b2c5eba5788e0ba0 100644 (file)
@@ -10,7 +10,6 @@ namespace wcf\system\page\handler;
  * @author  Matthias Schmidt
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Page\Handler
  * @since   3.0
  */
 class DefaultConversationRelatedPageHandler extends AbstractMenuPageHandler implements IOnlineLocationPageHandler
index 89561bf6b0b4d9de24150951299c18a844f3cc21..2b8cc34c230b41a12523715d2e9a49ec33bfed47 100644 (file)
@@ -14,7 +14,6 @@ use wcf\system\WCF;
  * @author  Matthias Schmidt
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Page\Handler
  * @since   3.0
  */
 trait TConversationOnlineLocationPageHandler
index cd40e16a03624e8e51db52036653e3b3aaa8e64f..11524374b8f0068b4815463b594fdde873f9b7f8 100644 (file)
@@ -15,7 +15,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Search
  */
 final class ConversationMessageSearch extends AbstractSearchProvider
 {
index b2661c1ab11ccf5e02cebf049e60d1e02bb0a1af..224404ac04d1ea185881296da80790e5965e62c1 100644 (file)
@@ -8,7 +8,6 @@ namespace wcf\system\stat;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Stat
  */
 class ConversationMessageStatDailyHandler extends AbstractStatDailyHandler
 {
index c3229d7a62c95578260c26f880005a3af9071be4..cff7012a54e752c4ff59eee0a4195f748d70685f 100644 (file)
@@ -8,7 +8,6 @@ namespace wcf\system\stat;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Stat
  */
 class ConversationStatDailyHandler extends AbstractStatDailyHandler
 {
index 58829672c5239465562ae27bd62107078412470c..dcdf06f182713ab1e417506c6d90ffb98f422c76 100644 (file)
@@ -10,7 +10,6 @@ use wcf\data\conversation\message\ConversationMessage;
  * @author  Joshua Ruesweg
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Content\Provider
  * @since   5.2
  */
 class ConversationMessageUserContentProvider extends AbstractDatabaseUserContentProvider
index ccc764acb6aaab57da8ca0af4e427b40b5a702da..1145d86483993cf971df83eaf04e90c73de4ba4c 100644 (file)
@@ -10,7 +10,6 @@ use wcf\data\conversation\Conversation;
  * @author  Joshua Ruesweg
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Content\Provider
  * @since   5.2
  */
 class ConversationUserContentProvider extends AbstractDatabaseUserContentProvider
index 16a4ce92d2768e9037c3fb0e9902cc737b376274..7ae93b4cd275965d25efeecfcded06001f1be0ac 100644 (file)
@@ -12,7 +12,6 @@ use wcf\system\user\notification\object\ConversationMessageUserNotificationObjec
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Event
  *
  * @method  ConversationMessageUserNotificationObject   getUserNotificationObject()
  */
@@ -30,7 +29,7 @@ class ConversationMessageUserNotificationEvent extends AbstractUserNotificationE
     /**
      * @inheritDoc
      */
-    public function getTitle()
+    public function getTitle(): string
     {
         $count = \count($this->getAuthors());
         if ($count > 1) {
@@ -46,7 +45,7 @@ class ConversationMessageUserNotificationEvent extends AbstractUserNotificationE
     /**
      * @inheritDoc
      */
-    public function getMessage()
+    public function getMessage(): string
     {
         $authors = \array_values($this->getAuthors());
         $count = \count($authors);
@@ -94,7 +93,7 @@ class ConversationMessageUserNotificationEvent extends AbstractUserNotificationE
      * @inheritDoc
      * @since   5.2
      */
-    public function getEmailTitle()
+    public function getEmailTitle(): string
     {
         if (\count($this->getAuthors()) > 1) {
             return parent::getEmailTitle();
@@ -110,7 +109,7 @@ class ConversationMessageUserNotificationEvent extends AbstractUserNotificationE
     /**
      * @inheritDoc
      */
-    public function getLink()
+    public function getLink(): string
     {
         return $this->getUserNotificationObject()->getLink();
     }
@@ -118,7 +117,7 @@ class ConversationMessageUserNotificationEvent extends AbstractUserNotificationE
     /**
      * @inheritDoc
      */
-    public function getEventHash()
+    public function getEventHash(): string
     {
         return \sha1($this->eventID . '-' . $this->getUserNotificationObject()->conversationID);
     }
@@ -126,7 +125,7 @@ class ConversationMessageUserNotificationEvent extends AbstractUserNotificationE
     /**
      * @inheritDoc
      */
-    public function checkAccess()
+    public function checkAccess(): bool
     {
         return $this->getUserNotificationObject()->getConversation()->canRead();
     }
index b0d8f8628b1937bd922a748945c7ec07b5888302..fb9f8bdf4360db95fb1a9451b96b5a879fb82ff7 100644 (file)
@@ -11,7 +11,6 @@ use wcf\system\user\notification\object\ConversationUserNotificationObject;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Event
  *
  * @method  ConversationUserNotificationObject  getUserNotificationObject()
  */
@@ -23,7 +22,7 @@ class ConversationUserNotificationEvent extends AbstractUserNotificationEvent im
     /**
      * @inheritDoc
      */
-    public function getTitle()
+    public function getTitle(): string
     {
         return $this->getLanguage()->get('wcf.user.notification.conversation.title');
     }
@@ -31,7 +30,7 @@ class ConversationUserNotificationEvent extends AbstractUserNotificationEvent im
     /**
      * @inheritDoc
      */
-    public function getMessage()
+    public function getMessage(): string
     {
         return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message', [
             'author' => $this->author,
@@ -59,7 +58,7 @@ class ConversationUserNotificationEvent extends AbstractUserNotificationEvent im
      * @inheritDoc
      * @since   5.2
      */
-    public function getEmailTitle()
+    public function getEmailTitle(): string
     {
         return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.mail.title', [
             'author' => $this->author,
@@ -70,7 +69,7 @@ class ConversationUserNotificationEvent extends AbstractUserNotificationEvent im
     /**
      * @inheritDoc
      */
-    public function getLink()
+    public function getLink(): string
     {
         return $this->getUserNotificationObject()->getLink();
     }
@@ -78,7 +77,7 @@ class ConversationUserNotificationEvent extends AbstractUserNotificationEvent im
     /**
      * @inheritDoc
      */
-    public function checkAccess()
+    public function checkAccess(): bool
     {
         return $this->getUserNotificationObject()->canRead();
     }
index 77dcfb58e72ca03dc7da6019f958ce51c09eafa7..3477b13ac2205ca4f965a9d46f14e9b79fa5e6c2 100644 (file)
@@ -15,7 +15,6 @@ use wcf\data\user\UserProfile;
  * @author  Matthias Schmidt
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Event
  * @since   3.1
  */
 trait TTestableConversationRelatedUserNotificationEvent
index da9ea3a6dfadd800a8b6be96cc38013d0c606878..3ca8b3613b53107ca0ad7cb3286f1e31fe535776 100644 (file)
@@ -11,7 +11,6 @@ use wcf\data\DatabaseObjectDecorator;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object
  *
  * @method  ConversationMessage getDecoratedObject()
  * @mixin   ConversationMessage
@@ -26,7 +25,7 @@ class ConversationMessageUserNotificationObject extends DatabaseObjectDecorator
     /**
      * @inheritDoc
      */
-    public function getTitle()
+    public function getTitle(): string
     {
         return $this->getConversation()->subject;
     }
@@ -34,7 +33,7 @@ class ConversationMessageUserNotificationObject extends DatabaseObjectDecorator
     /**
      * @inheritDoc
      */
-    public function getURL()
+    public function getURL(): string
     {
         return $this->getLink();
     }
index ab6e27dacf3e2f207418912ebbd21fb6e8ad129b..5bedbae6d1e0661a6638e28f3bb33a5cab146bc2 100644 (file)
@@ -11,7 +11,6 @@ use wcf\data\DatabaseObjectDecorator;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object
  *
  * @method  Conversation    getDecoratedObject()
  * @mixin   Conversation
@@ -26,7 +25,7 @@ class ConversationUserNotificationObject extends DatabaseObjectDecorator impleme
     /**
      * @inheritDoc
      */
-    public function getTitle()
+    public function getTitle(): string
     {
         return $this->subject;
     }
@@ -34,7 +33,7 @@ class ConversationUserNotificationObject extends DatabaseObjectDecorator impleme
     /**
      * @inheritDoc
      */
-    public function getURL()
+    public function getURL(): string
     {
         return $this->getLink();
     }
index f55fca1d3a5a1825b8289fccc76e753246fe9594..e0c3b432718bad60448b9fc0df562de5ab539ef4 100644 (file)
@@ -12,7 +12,6 @@ use wcf\system\user\notification\object\ConversationMessageUserNotificationObjec
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object\Type
  */
 class ConversationMessageNotificationObjectType extends AbstractUserNotificationObjectType
 {
index 96ce0c6402b49c25658147607725347cffc17825..5c04933c3fcfaf4f209c9e9f5d9e10f972b15536 100644 (file)
@@ -13,7 +13,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object\Type
  */
 class ConversationNotificationObjectType extends AbstractUserNotificationObjectType
 {
index eb43269a05bbf0fe8a88bf1bba2a1d1275f2a7b9..77f033065391e4cf15540c15847c3dfceaf27776 100644 (file)
@@ -15,7 +15,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Worker
  *
  * @method  ConversationMessageList     getObjectList()
  */
@@ -39,8 +38,8 @@ class ConversationMessageRebuildDataWorker extends AbstractRebuildDataWorker
         if ($this->count === null) {
             $this->count = 0;
             $sql = "SELECT  MAX(messageID) AS messageID
-                    FROM    wcf" . WCF_N . "_conversation_message";
-            $statement = WCF::getDB()->prepareStatement($sql);
+                    FROM    wcf1_conversation_message";
+            $statement = WCF::getDB()->prepare($sql);
             $statement->execute();
             $row = $statement->fetchArray();
             if ($row !== false) {
@@ -83,10 +82,10 @@ class ConversationMessageRebuildDataWorker extends AbstractRebuildDataWorker
         $attachmentObjectType = ObjectTypeCache::getInstance()
             ->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'com.woltlab.wcf.conversation.message');
         $sql = "SELECT  COUNT(*) AS attachments
-                FROM    wcf" . WCF_N . "_attachment
+                FROM    wcf1_attachment
                 WHERE   objectTypeID = ?
                     AND objectID = ?";
-        $attachmentStatement = WCF::getDB()->prepareStatement($sql);
+        $attachmentStatement = WCF::getDB()->prepare($sql);
 
         // retrieve permissions
         $userIDs = [];
@@ -137,13 +136,13 @@ class ConversationMessageRebuildDataWorker extends AbstractRebuildDataWorker
             $updateData[$message->messageID] = $data;
         }
 
-        $sql = "UPDATE  wcf" . WCF_N . "_conversation_message
+        $sql = "UPDATE  wcf1_conversation_message
                 SET     attachments = ?,
                         message = ?,
                         enableHtml = ?,
                         hasEmbeddedObjects = ?
                 WHERE   messageID = ?";
-        $statement = WCF::getDB()->prepareStatement($sql);
+        $statement = WCF::getDB()->prepare($sql);
 
         WCF::getDB()->beginTransaction();
         foreach ($updateData as $messageID => $data) {
index daf143eb38dee504c8029bd5f40181fea21dc141..7972ef1fe11d83cea28673cbdc92352f23c21cbf 100644 (file)
@@ -13,7 +13,6 @@ use wcf\system\WCF;
  * @author  Tim Duesterhus
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Worker
  *
  * @method  ConversationMessageList     getObjectList()
  */
@@ -32,8 +31,8 @@ final class ConversationMessageSearchIndexRebuildDataWorker extends AbstractRebu
         if ($this->count === null) {
             $this->count = 0;
             $sql = "SELECT  MAX(messageID) AS messageID
-                    FROM    wcf" . WCF_N . "_conversation_message";
-            $statement = WCF::getDB()->prepareStatement($sql);
+                    FROM    wcf1_conversation_message";
+            $statement = WCF::getDB()->prepare($sql);
             $statement->execute();
             $row = $statement->fetchArray();
             if ($row !== false) {
index e53b2996e705a481ac77f04f457e4d9b25765d8e..0b104101ae2b791d341d8eceb7e82e3782d96dd8 100644 (file)
@@ -14,7 +14,6 @@ use wcf\system\WCF;
  * @author  Marcel Werk
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Worker
  *
  * @method  ConversationList    getObjectList()
  */
@@ -33,8 +32,8 @@ class ConversationRebuildDataWorker extends AbstractRebuildDataWorker
         if ($this->count === null) {
             $this->count = 0;
             $sql = "SELECT  MAX(conversationID) AS conversationID
-                    FROM    wcf" . WCF_N . "_conversation";
-            $statement = WCF::getDB()->prepareStatement($sql);
+                    FROM    wcf1_conversation";
+            $statement = WCF::getDB()->prepare($sql);
             $statement->execute();
             $row = $statement->fetchArray();
             if ($row !== false) {
@@ -66,43 +65,43 @@ class ConversationRebuildDataWorker extends AbstractRebuildDataWorker
 
         // prepare statements
         $sql = "SELECT      messageID, time, userID, username
-                FROM        wcf" . WCF_N . "_conversation_message
+                FROM        wcf1_conversation_message
                 WHERE       conversationID = ?
                 ORDER BY    time";
-        $firstMessageStatement = WCF::getDB()->prepareStatement($sql, 1);
+        $firstMessageStatement = WCF::getDB()->prepare($sql, 1);
         $sql = "SELECT      time, userID, username
-                FROM        wcf" . WCF_N . "_conversation_message
+                FROM        wcf1_conversation_message
                 WHERE       conversationID = ?
                 ORDER BY    time DESC";
-        $lastMessageStatement = WCF::getDB()->prepareStatement($sql, 1);
+        $lastMessageStatement = WCF::getDB()->prepare($sql, 1);
         $sql = "SELECT  COUNT(*) AS messages,
                         SUM(attachments) AS attachments
-                FROM    wcf" . WCF_N . "_conversation_message
+                FROM    wcf1_conversation_message
                 WHERE   conversationID = ?";
-        $statsStatement = WCF::getDB()->prepareStatement($sql);
+        $statsStatement = WCF::getDB()->prepare($sql);
         $sql = "SELECT  COUNT(*) AS participants
-                FROM    wcf" . WCF_N . "_conversation_to_user conversation_to_user
+                FROM    wcf1_conversation_to_user conversation_to_user
                 WHERE   conversation_to_user.conversationID = ?
                     AND conversation_to_user.hideConversation <> ?
                     AND conversation_to_user.participantID <> ?
                     AND conversation_to_user.isInvisible = ?";
-        $participantCounterStatement = WCF::getDB()->prepareStatement($sql);
+        $participantCounterStatement = WCF::getDB()->prepare($sql);
         $sql = "SELECT      conversation_to_user.participantID AS userID, conversation_to_user.hideConversation, user_table.username
-                FROM        wcf" . WCF_N . "_conversation_to_user conversation_to_user
-                LEFT JOIN   wcf" . WCF_N . "_user user_table
+                FROM        wcf1_conversation_to_user conversation_to_user
+                LEFT JOIN   wcf1_user user_table
                 ON          user_table.userID = conversation_to_user.participantID
                 WHERE       conversation_to_user.conversationID = ?
                         AND conversation_to_user.participantID <> ?
                         AND conversation_to_user.isInvisible = ?
                 ORDER BY    user_table.username";
-        $participantStatement = WCF::getDB()->prepareStatement($sql, 5);
+        $participantStatement = WCF::getDB()->prepare($sql, 5);
 
         $sql = "SELECT  COUNT(*) AS participants
-                FROM    wcf" . WCF_N . "_conversation_to_user
+                FROM    wcf1_conversation_to_user
                 WHERE   conversationID = ?
                     AND hideConversation <> ?
                     AND participantID IS NOT NULL";
-        $existingParticipantStatement = WCF::getDB()->prepareStatement($sql);
+        $existingParticipantStatement = WCF::getDB()->prepare($sql);
 
         $obsoleteConversations = [];
         $updateData = [];
@@ -182,7 +181,7 @@ class ConversationRebuildDataWorker extends AbstractRebuildDataWorker
             $updateData[$conversation->conversationID] = $data;
         }
 
-        $sql = "UPDATE  wcf" . WCF_N . "_conversation
+        $sql = "UPDATE  wcf1_conversation
                 SET     firstMessageID = ?,
                         lastPostTime = ?,
                         lastPosterID = ?,
@@ -194,7 +193,7 @@ class ConversationRebuildDataWorker extends AbstractRebuildDataWorker
                         participants = ?,
                         participantSummary = ?
                 WHERE   conversationID = ?";
-        $statement = WCF::getDB()->prepareStatement($sql);
+        $statement = WCF::getDB()->prepare($sql);
 
         WCF::getDB()->beginTransaction();
         foreach ($updateData as $conversationID => $data) {
index 871d367477aa2741e962a98fb18fe95b71bfeb96..1b981e90a49c5ee376859d5061d4b872964f74c1 100644 (file)
 .sidebar .box.conversationQuota .boxContent {
        text-align: center;
 }
-.conversationUsageBar {
-       background-color: rgba(165, 223, 65, 1);
-       height: 5px;
-
-       > span {
-               background-color: rgba(76, 169, 22, 1);
-               color: transparent;
-               display: block;
-               height: 100%;
-       }
-
-       &.yellow {
-               background-color: rgba(254, 207, 35, 1);
-
-               > span {
-                       background-color: rgba(253, 146, 21, 1);
-               }
-       }
-
-       &.red {
-               background-color: rgba(255, 205, 210, 1);
-
-               > span {
-                       background-color: rgba(244, 67, 54, 1);
-               }
-       }
+.conversationQuotaMeter {
+       width: 100%;
 }
 
 .conversationItem {
index 7a2c97f16c1f19aea4201c4fe8fd9104cb1c7c30..68f3da39beb657f9d97372aba846cf2d0b3b8e1e 100644 (file)
                <item name="wcf.acp.option.module_conversation"><![CDATA[Konversationen]]></item>
        </category>
        <category name="wcf.acp.rebuildData">
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation"><![CDATA[Konversationen aktualisieren]]></item>
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.description"><![CDATA[Aktualisiert Zähler der Konversationen]]></item>
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message"><![CDATA[Konversationsnachrichten aktualisieren]]></item>
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.description"><![CDATA[Aktualisiert Zähler der Konversationsnachrichten]]></item>
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index"><![CDATA[Suchindex für Konversationsnachrichten aktualisieren]]></item>
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index.description"><![CDATA[Warnung: Die Ausführung dieser Aktion kann bei größeren Foren sehr lange dauern.]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationRebuildDataWorker"><![CDATA[Konversationen aktualisieren]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationRebuildDataWorker.description"><![CDATA[Aktualisiert Zähler der Konversationen]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageRebuildDataWorker"><![CDATA[Konversationsnachrichten aktualisieren]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageRebuildDataWorker.description"><![CDATA[Aktualisiert Zähler der Konversationsnachrichten]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageSearchIndexRebuildDataWorker"><![CDATA[Suchindex für Konversationsnachrichten aktualisieren]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageSearchIndexRebuildDataWorker.description"><![CDATA[Warnung: Die Ausführung dieser Aktion kann bei größeren Foren sehr lange dauern.]]></item>
        </category>
        <category name="wcf.acp.stat">
                <item name="wcf.acp.stat.com.woltlab.wcf.conversation"><![CDATA[Konversationen]]></item>
                <item name="wcf.conversation.participants.other"><![CDATA[und {if $conversation->participants - $participantSummaryCount == 1}ein weiterer{else}{#$conversation->participants-$participantSummaryCount} weitere{/if}]]></item>
                <item name="wcf.conversation.attachments"><![CDATA[Diese Konversation enthält {if $conversation->attachments == 1}einen Dateianhang{else}{#$conversation->attachments} Dateianhänge{/if}.]]></item>
                <item name="wcf.conversation.error.mailboxIsFull"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du hast{else}Sie haben{/if} das zulässige Limit für Konversationen bereits erreicht und {if LANGUAGE_USE_INFORMAL_VARIANT}kannst{else}können{/if} keine neuen Konversationen starten.]]></item>
-               <item name="wcf.conversation.message.editNote"><![CDATA[{$message->username} hat diese Nachricht {#$message->editCount} Mal editiert, zuletzt: {@$message->lastEditTime|time}.]]></item>
+               <item name="wcf.conversation.message.editNote"><![CDATA[{$message->username} hat diese Nachricht {#$message->editCount} Mal editiert, zuletzt: {time time=$message->lastEditTime}.]]></item>
                <item name="wcf.conversation.noParticipantsWarning"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du bist{else}Sie sind{/if} dabei, auf eine Konversation ohne weitere Teilnehmer zu antworten. Alle anderen Teilnehmer haben diese Konversation verlassen. Niemand wird {if LANGUAGE_USE_INFORMAL_VARIANT}deine{else}Ihre{/if} Nachricht lesen!]]></item>
                <item name="wcf.conversation.message.permalink"><![CDATA[Permalink zur {#$startIndex}. Nachricht]]></item>
                <item name="wcf.conversation.markAsRead.doubleClick"><![CDATA[Konversation durch Doppelklick als gelesen markieren]]></item>
                <item name="wcf.conversation.visibility.previousMessages"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du wurdest{else}Sie wurden{/if} einer laufenden Konversation hinzugefügt, vorherige Nachrichten werden {if LANGUAGE_USE_INFORMAL_VARIANT}dir{else}Ihnen{/if} nicht angezeigt.]]></item>
                <item name="wcf.conversation.time"><![CDATA[Erstellung]]></item>
                <item name="wcf.conversation.username"><![CDATA[Autor]]></item>
-               <item name="wcf.conversation.error.floodControl"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du hast{else}Sie haben{/if} innerhalb der letzten 24 Stunden bereits {if $limit == 1}eine Konversation{else}{#$limit} Konversationen{/if} gestartet. Bitte {if LANGUAGE_USE_INFORMAL_VARIANT}warte{else}warten Sie{/if} bis zum <strong>{@$notBefore|time}</strong>, bevor {if LANGUAGE_USE_INFORMAL_VARIANT}du{else}Sie{/if} eine neue Konversation {if LANGUAGE_USE_INFORMAL_VARIANT}startest{else}starten{/if}.]]></item>
+               <item name="wcf.conversation.error.floodControl"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du hast{else}Sie haben{/if} innerhalb der letzten 24 Stunden bereits {if $limit == 1}eine Konversation{else}{#$limit} Konversationen{/if} gestartet. Bitte {if LANGUAGE_USE_INFORMAL_VARIANT}warte{else}warten Sie{/if} bis zum <strong>{time time=$notBefore type='plainTime'}</strong>, bevor {if LANGUAGE_USE_INFORMAL_VARIANT}du{else}Sie{/if} eine neue Konversation {if LANGUAGE_USE_INFORMAL_VARIANT}startest{else}starten{/if}.]]></item>
                <item name="wcf.conversation.message.error.floodControl"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du hast{else}Sie haben{/if} bereits eine Nachricht innerhalb der letzten {plural value=$__wcf->getSession()->getPermission('user.conversation.floodControlTime') 1='Sekunde' other='# Sekunden'} versendet. {if LANGUAGE_USE_INFORMAL_VARIANT}Du kannst{else}Sie können{/if} erst in {plural value=$waitTime 1='einer Sekunde' other='# Sekunden'} eine neue Nachricht verfassen.]]></item>
        </category>
        <category name="wcf.conversation.edit">
                <item name="wcf.conversation.log.conversation.open"><![CDATA[Hat die Konversation wieder geöffnet.]]></item>
                <item name="wcf.conversation.log.conversation.close"><![CDATA[Hat die Konversation für neue Nachrichten geschlossen.]]></item>
                <item name="wcf.conversation.log.conversation.leave"><![CDATA[Hat die Konversation verlassen.]]></item>
-               <item name="wcf.conversation.log.conversation.addParticipants"><![CDATA[Hat folgende Teilnehmer hinzugefügt: {implode from=$additionalData[participants] item=participant}<a href="{link controller='User' id=$participant[userID] title=$participant[username]}{/link}" class="userLink" data-object-id="{@$participant[userID]}">{$participant[username]}</a>{/implode}]]></item>
-               <item name="wcf.conversation.log.conversation.removeParticipant"><![CDATA[Hat folgenden Teilnehmer entfernt: <a href="{link controller='User' id=$additionalData[userID] title=$additionalData[username]}{/link}" class="userLink" data-object-id="{@$additionalData[userID]}">{$additionalData[username]}</a>]]></item>
+               <item name="wcf.conversation.log.conversation.addParticipants"><![CDATA[Hat folgende Teilnehmer hinzugefügt: {implode from=$additionalData[participants] item=participant}<a href="{link controller='User' id=$participant[userID] title=$participant[username]}{/link}" class="userLink" data-object-id="{$participant[userID]}">{$participant[username]}</a>{/implode}]]></item>
+               <item name="wcf.conversation.log.conversation.removeParticipant"><![CDATA[Hat folgenden Teilnehmer entfernt: <a href="{link controller='User' id=$additionalData[userID] title=$additionalData[username]}{/link}" class="userLink" data-object-id="{$additionalData[userID]}">{$additionalData[username]}</a>]]></item>
        </category>
        <category name="wcf.acp.dataImport">
                <item name="wcf.acp.dataImport.data.com.woltlab.wcf.conversation"><![CDATA[Konversationen]]></item>
                <item name="wcf.user.notification.conversation.title"><![CDATA[Neue Konversation]]></item>
                <item name="wcf.user.notification.conversation.mail.plaintext"><![CDATA[{@$author} hat die Konversation „{@$conversation->getTitle()}“ [URL:{@$conversation->getLink()}] gestartet:]]></item>
                <item name="wcf.user.notification.conversation.mail.html"><![CDATA[<p><strong>{$author}</strong> hat die Konversation <a href="{$conversation->getLink()}">{$conversation->getTitle()}</a> gestartet:</p>]]></item>
-               <item name="wcf.user.notification.conversation.mail.title"><![CDATA[Neue Konversation von "{@$author->username}"]]></item>
+               <item name="wcf.user.notification.conversation.mail.title"><![CDATA["{@$author}" hat die Konversation "{@$conversation->getTitle()}" gestartet]]></item>
                <item name="wcf.user.notification.com.woltlab.wcf.conversation"><![CDATA[Konversationen]]></item>
                <item name="wcf.user.notification.com.woltlab.wcf.conversation.notification.conversation"><![CDATA[Neue Konversation]]></item>
                <item name="wcf.user.notification.com.woltlab.wcf.conversation.message.notification.conversationMessage"><![CDATA[Antwort auf bestehende Konversation]]></item>
        </category>
 </import>
 <delete>
-       <item name="wcf.conversation.markAllAsRead" />
+       <item name="wbb.conversation.gotoFirstNewPost"/>
+       <item name="wbb.conversation.gotoLastPost"/>
+       <item name="wcf.acp.group.canBeAddedAsParticipant"/>
+       <item name="wcf.acp.group.option.user.conversation.allowedAttachmentExtensions.description"/>
+       <item name="wcf.acp.option.conversation_reply_show_messages_max"/>
+       <item name="wcf.acp.option.conversation_reply_show_messages_max.description"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.description"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.description"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index.description"/>
+       <item name="wcf.clipboard.item.conversation.assignLabel"/>
+       <item name="wcf.clipboard.item.conversation.close"/>
+       <item name="wcf.clipboard.item.conversation.leave"/>
+       <item name="wcf.clipboard.item.conversation.leavePermanently"/>
+       <item name="wcf.clipboard.item.conversation.open"/>
+       <item name="wcf.clipboard.item.conversation.restore"/>
+       <item name="wcf.clipboard.label.conversation.marked"/>
+       <item name="wcf.conversation.gotoFirstNewPost"/>
+       <item name="wcf.conversation.log"/>
+       <item name="wcf.conversation.log.action"/>
+       <item name="wcf.conversation.log.noEntries"/>
+       <item name="wcf.conversation.log.time"/>
+       <item name="wcf.conversation.log.title"/>
+       <item name="wcf.conversation.markAllAsRead"/>
+       <item name="wcf.conversation.markAllAsRead.confirmMessage"/>
+       <item name="wcf.conversation.message.add"/>
+       <item name="wcf.conversation.message.add.previousPosts"/>
+       <item name="wcf.conversation.message.new"/>
+       <item name="wcf.conversation.subject"/>
+       <item name="wcf.page.category.com.woltlab.wcf.conversation"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.Conversation"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationAdd"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationAddForm"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationList"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationListPage"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageAdd"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageAddForm"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageEdit"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageEditForm"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationPage"/>
+       <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationAdd"/>
+       <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationList"/>
+       <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationMessageAdd"/>
+       <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationMessageEdit"/>
+       <item name="wcf.user.notification.com.woltlab.wcf.conversation.conversation"/>
+       <item name="wcf.user.notification.com.woltlab.wcf.conversation.conversationMessage"/>
+       <item name="wcf.user.notification.conversation.mail"/>
+       <item name="wcf.user.notification.conversation.message.mail"/>
+       <item name="wcf.user.notification.conversation.message.output"/>
+       <item name="wcf.user.notification.conversation.message.shortOutput"/>
+       <item name="wcf.user.notification.conversation.output"/>
+       <item name="wcf.user.notification.conversation.shortOutput"/>
+       <item name="wcf.user.usersOnline.location.ConversationAddForm"/>
+       <item name="wcf.user.usersOnline.location.ConversationListPage"/>
+       <item name="wcf.user.usersOnline.location.ConversationMessageAddForm"/>
+       <item name="wcf.user.usersOnline.location.ConversationMessageEditForm"/>
+       <item name="wcf.user.usersOnline.location.ConversationPage"/>
 </delete>
 </language>
index e5627400844d6581f2ea6432533a1c432f63735f..8cbf192e92e8aeaeec40de2251b969e36a9dba31 100644 (file)
                <item name="wcf.acp.option.module_conversation"><![CDATA[Conversations]]></item>
        </category>
        <category name="wcf.acp.rebuildData">
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation"><![CDATA[Rebuild Conversations]]></item>
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.description"><![CDATA[Rebuilds the conversation counters.]]></item>
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message"><![CDATA[Rebuild Conversation Messages]]></item>
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.description"><![CDATA[Rebuilds the conversation message counters.]]></item>
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index"><![CDATA[Rebuild Conversation Message Search Index]]></item>
-               <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index.description"><![CDATA[Warning: This action can take a while to complete on large forums.]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationRebuildDataWorker"><![CDATA[Rebuild Conversations]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationRebuildDataWorker.description"><![CDATA[Rebuilds the conversation counters.]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageRebuildDataWorker"><![CDATA[Rebuild Conversation Messages]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageRebuildDataWorker.description"><![CDATA[Rebuilds the conversation message counters.]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageSearchIndexRebuildDataWorker"><![CDATA[Rebuild Conversation Message Search Index]]></item>
+               <item name="wcf.acp.rebuildData.wcf_system_worker_ConversationMessageSearchIndexRebuildDataWorker.description"><![CDATA[Warning: This action can take a while to complete on large forums.]]></item>
        </category>
        <category name="wcf.acp.stat">
                <item name="wcf.acp.stat.com.woltlab.wcf.conversation"><![CDATA[Conversations]]></item>
                <item name="wcf.conversation.searchConversation"><![CDATA[Search This Conversation Only]]></item>
                <item name="wcf.conversation.searchedConversation"><![CDATA[Only search conversation <a href="{link controller='Conversation' object=$searchedConversation}{/link}">{$searchedConversation->getTitle()}</a>]]></item>
                <item name="wcf.conversation.participants.other"><![CDATA[and {if $conversation->participants - $participantSummaryCount == 1}one other{else}{#$conversation->participants-$participantSummaryCount} others{/if}]]></item>
-               <item name="wcf.conversation.attachments"><![CDATA[Conversation contains {#$conversation->attachments} attachment{if $conversation->attachments != 1}s{/if}]]></item>
+               <item name="wcf.conversation.attachments"><![CDATA[Conversation Contains {#$conversation->attachments} Attachment{if $conversation->attachments != 1}s{/if}]]></item>
                <item name="wcf.conversation.error.mailboxIsFull"><![CDATA[You have reached your maximum conversations limit and cannot create new conversations.]]></item>
-               <item name="wcf.conversation.message.editNote"><![CDATA[{$message->username} edited this message {#$message->editCount} times, last: {@$message->lastEditTime|time}.]]></item>
+               <item name="wcf.conversation.message.editNote"><![CDATA[{$message->username} edited this message {#$message->editCount} times, last: {time time=$message->lastEditTime}.]]></item>
                <item name="wcf.conversation.noParticipantsWarning"><![CDATA[You are about to reply to a conversation without other participants, nobody is going to read your message!]]></item>
                <item name="wcf.conversation.message.permalink"><![CDATA[Permalink to {#$startIndex}. message]]></item>
                <item name="wcf.conversation.markAsRead.doubleClick"><![CDATA[Double-Click to Mark This Conversation Read]]></item>
                <item name="wcf.conversation.visibility.previousMessages"><![CDATA[You have been added to an existing conversation, previously written messages are hidden.]]></item>
                <item name="wcf.conversation.time"><![CDATA[Creation]]></item>
                <item name="wcf.conversation.username"><![CDATA[Author]]></item>
-               <item name="wcf.conversation.error.floodControl"><![CDATA[You have already started {if $limit == 1}one conversation{else}{#$limit} conversations{/if} in the past 24 hours. Please wait until <strong>{@$notBefore|time}</strong> before you start a new conversation.]]></item>
+               <item name="wcf.conversation.error.floodControl"><![CDATA[You have already started {if $limit == 1}one conversation{else}{#$limit} conversations{/if} in the past 24 hours. Please wait until <strong>{time time=$notBefore type='plainTime'}</strong> before you start a new conversation.]]></item>
                <item name="wcf.conversation.message.error.floodControl"><![CDATA[You have already sent a message within the last {plural value=$__wcf->getSession()->getPermission('user.conversation.floodControlTime') 1='second' other='# seconds'}. You must wait at least {plural value=$waitTime 1='one second' other='# seconds'} before attempting to write a new message.]]></item>
        </category>
        <category name="wcf.conversation.edit">
                <item name="wcf.conversation.log.conversation.open"><![CDATA[Opened the conversation again.]]></item>
                <item name="wcf.conversation.log.conversation.close"><![CDATA[Closed the conversation for new replies.]]></item>
                <item name="wcf.conversation.log.conversation.leave"><![CDATA[Left the conversation.]]></item>
-               <item name="wcf.conversation.log.conversation.addParticipants"><![CDATA[Added the following participants: {implode from=$additionalData[participants] item=participant}<a href="{link controller='User' id=$participant[userID] title=$participant[username]}{/link}" class="userLink" data-object-id="{@$participant[userID]}">{$participant[username]}</a>{/implode}.]]></item>
-               <item name="wcf.conversation.log.conversation.removeParticipant"><![CDATA[Removed a participant: <a href="{link controller='User' id=$additionalData[userID] title=$additionalData[username]}{/link}" class="userLink" data-object-id="{@$additionalData[userID]}">{$additionalData[username]}</a>.]]></item>
+               <item name="wcf.conversation.log.conversation.addParticipants"><![CDATA[Added the following participants: {implode from=$additionalData[participants] item=participant}<a href="{link controller='User' id=$participant[userID] title=$participant[username]}{/link}" class="userLink" data-object-id="{$participant[userID]}">{$participant[username]}</a>{/implode}.]]></item>
+               <item name="wcf.conversation.log.conversation.removeParticipant"><![CDATA[Removed a participant: <a href="{link controller='User' id=$additionalData[userID] title=$additionalData[username]}{/link}" class="userLink" data-object-id="{$additionalData[userID]}">{$additionalData[username]}</a>.]]></item>
        </category>
        <category name="wcf.acp.dataImport">
                <item name="wcf.acp.dataImport.data.com.woltlab.wcf.conversation"><![CDATA[Conversations]]></item>
                <item name="wcf.user.notification.conversation.title"><![CDATA[New Conversation]]></item>
                <item name="wcf.user.notification.conversation.mail.plaintext"><![CDATA[{@$author} started the conversation “{@$conversation->getTitle()}” [URL:{@$conversation->getLink()}]:]]></item>
                <item name="wcf.user.notification.conversation.mail.html"><![CDATA[<p><strong>{$author}</strong> started the conversation <a href="{$conversation->getLink()}">{$conversation->getTitle()}</a>:</p>]]></item>
-               <item name="wcf.user.notification.conversation.mail.title"><![CDATA[New Conversation from "{@$author->username}"]]></item>
+               <item name="wcf.user.notification.conversation.mail.title"><![CDATA["{@$author}" started the conversation "{@$conversation->getTitle()}"]]></item>
                <item name="wcf.user.notification.com.woltlab.wcf.conversation"><![CDATA[Conversations]]></item>
                <item name="wcf.user.notification.com.woltlab.wcf.conversation.notification.conversation"><![CDATA[Notify me of new conversations]]></item>
                <item name="wcf.user.notification.com.woltlab.wcf.conversation.message.notification.conversationMessage"><![CDATA[Notify me of new replies in conversations]]></item>
        </category>
 </import>
 <delete>
-       <item name="wcf.conversation.markAllAsRead" />
+       <item name="wcf.acp.group.canBeAddedAsParticipant"/>
+       <item name="wcf.acp.group.option.user.conversation.allowedAttachmentExtensions.description"/>
+       <item name="wcf.acp.option.conversation_reply_show_messages_max"/>
+       <item name="wcf.acp.option.conversation_reply_show_messages_max.description"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.description"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.description"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index"/>
+       <item name="wcf.acp.rebuildData.com.woltlab.wcf.conversation.message.search.index.description"/>
+       <item name="wcf.clipboard.item.conversation.assignLabel"/>
+       <item name="wcf.clipboard.item.conversation.close"/>
+       <item name="wcf.clipboard.item.conversation.leave"/>
+       <item name="wcf.clipboard.item.conversation.leavePermanently"/>
+       <item name="wcf.clipboard.item.conversation.open"/>
+       <item name="wcf.clipboard.item.conversation.restore"/>
+       <item name="wcf.clipboard.label.conversation.marked"/>
+       <item name="wcf.conversation.gotoFirstNewPost"/>
+       <item name="wcf.conversation.markAllAsRead"/>
+       <item name="wcf.conversation.markAllAsRead.confirmMessage"/>
+       <item name="wcf.conversation.message.add"/>
+       <item name="wcf.conversation.message.add.previousPosts"/>
+       <item name="wcf.conversation.message.new"/>
+       <item name="wcf.conversation.subject"/>
+       <item name="wcf.page.category.com.woltlab.wcf.conversation"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.Conversation"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationAdd"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationAddForm"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationList"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationListPage"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageAdd"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageAddForm"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageEdit"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationMessageEditForm"/>
+       <item name="wcf.page.com.woltlab.wcf.conversation.ConversationPage"/>
+       <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationAdd"/>
+       <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationList"/>
+       <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationMessageAdd"/>
+       <item name="wcf.page.onlineLocation.com.woltlab.wcf.conversation.ConversationMessageEdit"/>
+       <item name="wcf.user.notification.conversation.mail"/>
+       <item name="wcf.user.notification.conversation.message.mail"/>
+       <item name="wcf.user.notification.conversation.message.output"/>
+       <item name="wcf.user.notification.conversation.message.shortOutput"/>
+       <item name="wcf.user.notification.conversation.output"/>
+       <item name="wcf.user.notification.conversation.shortOutput"/>
+       <item name="wcf.user.usersOnline.location.ConversationAddForm"/>
+       <item name="wcf.user.usersOnline.location.ConversationListPage"/>
+       <item name="wcf.user.usersOnline.location.ConversationMessageAddForm"/>
+       <item name="wcf.user.usersOnline.location.ConversationMessageEditForm"/>
+       <item name="wcf.user.usersOnline.location.ConversationPage"/>
 </delete>
 </language>
index d284d12302339e219c51c1649309038ab3770b8e..60da2f1af304dfb085decb9c9b3f49761ddefa41 100644 (file)
                </type>
                <!-- /importers -->
                <!-- rebuild data workers -->
-               <type>
-                       <name>com.woltlab.wcf.conversation</name>
-                       <definitionname>com.woltlab.wcf.rebuildData</definitionname>
-                       <classname>wcf\system\worker\ConversationRebuildDataWorker</classname>
-               </type>
-               <type>
-                       <name>com.woltlab.wcf.conversation.message</name>
-                       <definitionname>com.woltlab.wcf.rebuildData</definitionname>
-                       <classname>wcf\system\worker\ConversationMessageRebuildDataWorker</classname>
-                       <nicevalue>-5</nicevalue>
-               </type>
-               <type>
-                       <name>com.woltlab.wcf.conversation.message.search.index</name>
-                       <definitionname>com.woltlab.wcf.rebuildData</definitionname>
-                       <classname>wcf\system\worker\ConversationMessageSearchIndexRebuildDataWorker</classname>
-                       <nicevalue>121</nicevalue>
-               </type>
+               
                <!-- /rebuild data workers -->
                <!-- stat handlers -->
                <type>
                        <definitionname>com.woltlab.wcf.floodControl</definitionname>
                </type>
        </import>
+       <delete>
+               <type name="com.woltlab.wcf.conversation">
+                       <definitionname>com.woltlab.wcf.rebuildData</definitionname>
+                       <classname>wcf\system\worker\ConversationRebuildDataWorker</classname>
+               </type>
+               <type name="com.woltlab.wcf.conversation.message">
+                       <definitionname>com.woltlab.wcf.rebuildData</definitionname>
+                       <classname>wcf\system\worker\ConversationMessageRebuildDataWorker</classname>
+                       <nicevalue>-5</nicevalue>
+               </type>
+               <type name="com.woltlab.wcf.conversation.message.search.index">
+                       <definitionname>com.woltlab.wcf.rebuildData</definitionname>
+                       <classname>wcf\system\worker\ConversationMessageSearchIndexRebuildDataWorker</classname>
+                       <nicevalue>121</nicevalue>
+               </type>
+       </delete>
 </data>
index 2dbcc1d0e0961433d2751cf3a53d34c84ac32a72..a83f35fd1a16da47afe4b4a869b577863478d4a1 100644 (file)
@@ -5,7 +5,7 @@
   "packages": {
     "": {
       "dependencies": {
-        "@woltlab/wcf": "https://github.com/WoltLab/WCF.git#5ed76b3a3267dfbffdf19405822d22510ad2bc7d"
+        "@woltlab/d.ts": "https://github.com/WoltLab/d.ts.git#c08648e9f82c381bd18b91ac1072c430e58e71f1"
       },
       "devDependencies": {
         "@typescript-eslint/eslint-plugin": "^6.5.0",
@@ -13,7 +13,6 @@
         "eslint": "^8.48.0",
         "eslint-config-prettier": "^9.0.0",
         "prettier": "^3.0.3",
-        "tslib": "^2.6.0",
         "typescript": "^5.2.2"
       }
     },
         "node": ">=0.10.0"
       }
     },
+    "node_modules/@ckeditor/ckeditor5-alignment": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-39.0.2.tgz",
+      "integrity": "sha512-TjM+9h3tFn1wgnF4RJg0WaA758kT5VGSaVi0Ti6NECckPGXnccJpIQ7ZMSKAe4zCfaRSmNQsNYc20iq7w7+leg==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-autosave": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autosave/-/ckeditor5-autosave-39.0.2.tgz",
+      "integrity": "sha512-2YZwsPSFVwhqVoxU6HtQppmn8+TPnm7LmSKYt+7ESc72oqmWIcFGTkCmP5/gIt4oqz5twtJZ/v5lBg+92i3PyQ==",
+      "dependencies": {
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-basic-styles": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-39.0.2.tgz",
+      "integrity": "sha512-sp5sfE4d8Tng/zIssBK+SgaEkPfGcbmoGkjbHhPlWYAoQB9ONwvWkRZy9s3C+H0gfsEj3EqqxUKY70Us0yT8rA==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-block-quote": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-39.0.2.tgz",
+      "integrity": "sha512-ykxkLWJ1nuu5vVBnvHKKgKleudUNTjt/2zDsvUAiBbl4iN0rnOqhLbSL54fY4130p/DvE1CVoozqNiv7L83Vjw==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-clipboard": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-39.0.2.tgz",
+      "integrity": "sha512-SSuanBiQ4lWznXSGyeV5vqQweVWZ1+iZG1/atmrZSb/BOWa3XD6EGPu9tuzdm9MCjk2OxBuyMT07Cw+WzXFosQ==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "@ckeditor/ckeditor5-widget": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-code-block": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-code-block/-/ckeditor5-code-block-39.0.2.tgz",
+      "integrity": "sha512-VlG/+VqxrR/JWQZVsGzemr3caOgQLB5OmSsFKPBEzoMI+05zf2UM232DyBVBUfA6UJ5L/ZMkT9YdUi+XhFnhAQ==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-core": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-39.0.2.tgz",
+      "integrity": "sha512-/xtor5vIXgwBVsAj+yO/wyzezQUmXabdkb/T8aSXtO2665zeOVbDbtSsJ1Ov7Tz5A4Ia1pA9d7iDCt7E8Kva7A==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-editor-classic": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-39.0.2.tgz",
+      "integrity": "sha512-zDDFe70junUJT5VltMsVdBqSZUew4fCe8fmi9JMI2m2MAwNwARAOkOy9mQMMTJlrD+P3CfD/Y9QpromEjLOnYA==",
+      "dependencies": {
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-engine": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-39.0.2.tgz",
+      "integrity": "sha512-ERcEpIrmTML0/uhukkC+ZJSOx4mRaPbNG5vPEBXIentfDpzu1NrmUhGZRGXaw5lltL+NJbuTI0wjEINap0Hl3w==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-enter": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-39.0.2.tgz",
+      "integrity": "sha512-7yeZI/mzJH4/yryXFQemrueZA/UNGkfnauN8Mu6XFMykoRNo6l+cASz0x4iGb3pWumV3g+tUeX6AJmuwXkRb5A==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-essentials": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-39.0.2.tgz",
+      "integrity": "sha512-5Nf3XeuB0thXTJS2M2JYrlW2uuSujNOhwW7L05e7Z5JP4nUSkopBHdvymX9feZKMzGPOw6SVhk8gQIDYV7S28A==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-font": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-39.0.2.tgz",
+      "integrity": "sha512-6sGgo9X23gAllVjzGH1gOkjIEHkvm2O40IqUKCBwzn0K6Ry6St4R4QtcQeFV5jxAMKn0eD7blPuhItVrjmN0hw==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-heading": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-39.0.2.tgz",
+      "integrity": "sha512-P1ogDMAsTZB/TfuNwifNv1H9KHaMSPRaPfd+clhhLV/GAdt2rGMeH0HKuSke54cZYB6qMQP7Za8Xsfi2ufY0GA==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-highlight": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-highlight/-/ckeditor5-highlight-39.0.2.tgz",
+      "integrity": "sha512-WlinrcgNRgTMPCtg3ZfirEdbVpP+xSQdYGA/kmMTcjEnzfEUZv5ceecAF367158+hQNhY06p7Zpvxot8z6pobA==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-horizontal-line": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-39.0.2.tgz",
+      "integrity": "sha512-lKPqiOwmuX/9s5TclET7cywcQ76TJh/w+6u3BK8buzlmyWzdeYXUyljNqWCgiS0i2yyY4w5XaJxXB/Ey7Ks8/w==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-html-embed": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-embed/-/ckeditor5-html-embed-39.0.2.tgz",
+      "integrity": "sha512-51dt9ndDl8Ba1ETmBDwAM0u82/yyF1uY5bXnHrkfrcYwGn+pHojKMTysilmniY35fo9Rn2TaV8eBsp/2h/tYMg==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-image": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-39.0.2.tgz",
+      "integrity": "sha512-sp7ce+j/UqRW4kmhMX8DfZKPbNs5HgiEQY8ChQUPOKghstEjBrPpGFYCJ++NMPmWguDTzLxVAVuo2k+VOt+swA==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-indent": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-39.0.2.tgz",
+      "integrity": "sha512-wU/1jBqgkK068fxkZDxnZM5iACunABXBVtpgfXqe2S6cMPVQyhiLzo955Yt7BhqN7Mkor59xESO2+Npj/vwB7w==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-inspector": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-inspector/-/ckeditor5-inspector-4.1.0.tgz",
+      "integrity": "sha512-yKoIFpaSVQQIhgFEyoltwG40OSsWX5psYdYvNxW84nfxgrs90DJrbMQDtdchVZNMXBu6CkJfPiPG0WBLU9su3g==",
+      "engines": {
+        "node": ">=14.0.0",
+        "npm": ">=5.7.1"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-link": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-39.0.2.tgz",
+      "integrity": "sha512-UKSamaD+yGaLPo/7pLS6bi+h2pRpX7qFSe4isVvmC8PfhN4YAm6ZYpIXpnktzfv2+/Jx6P9HzfjOnJPPT5PRdQ==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-list": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-39.0.2.tgz",
+      "integrity": "sha512-XRcp67PuDK/mP0sL8g+TFLIr/MigVHKATwO+7OAJZlGAGxr73V/eRw3G6ZAe6Lh0lVQPRA54r+h5DHG5P+KRRg==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-mention": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-mention/-/ckeditor5-mention-39.0.2.tgz",
+      "integrity": "sha512-uTRenNKntYlzqnK5urqtwWRS5Frn888tne6YRJsHUJINX1h9kxgQ44svYx6QF9ZMdStmkEbKJfjZwNfnwWd95g==",
+      "dependencies": {
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-paragraph": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-39.0.2.tgz",
+      "integrity": "sha512-is0+G3ghz+6EwoNT5ciySiPt05FI0I/lxPksSDl4QG9BcGUwkN94fJalCxgXuMlGulojm/YZ3dCmJPnLMrAnUA==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-paste-from-office": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-39.0.2.tgz",
+      "integrity": "sha512-Y9O1C+9BpFCtvYI80AJzm/BkZWMedhreCaZcSCsEUUIo6vrIwehatTvgqWZJLwKZwL+4iy5/Kv9OfUhvO10I8Q==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-remove-format": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-39.0.2.tgz",
+      "integrity": "sha512-gCoWMMUyvqjtQs+EUr7JpO8LEF2Ip7qXmCuSwLTteet79a8sQyllPY6O3UOUEuFMO2GtT36+jtQ93pQh7onn+g==",
+      "dependencies": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-select-all": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-39.0.2.tgz",
+      "integrity": "sha512-/zTPZ14sfsL6E7LHcdOSW5JR7A5tsaSO2KNlQ/jm77XWSeQ7HZ4I7hoLXWksvcseubQ+xExWrzMQIjIOGqBLcQ==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-table": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-39.0.2.tgz",
+      "integrity": "sha512-IpI53KPEOj1F1vbMYUHLkOeoQoQV/q3pfiJxXXHZja1QaIEnqZT7YcSvJQbCyiuQw4UCZqU5x84c8GcyIZlBhg==",
+      "dependencies": {
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-theme-lark": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-39.0.2.tgz",
+      "integrity": "sha512-v6S3++hkoKgqV71BCafKWYmPA6o/X44kUzdahnFs1rYBM5WS87y9Jb0W8Rv8FXXD5QD0H2axtySw9S6HfYspQw==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-ui": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-typing": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-39.0.2.tgz",
+      "integrity": "sha512-ylkBumukIRe/8jQTanVYNcExvoraXX9TIX3POwiug2F+c/POKjoHgeq8+Wf/JEl7/ydtXZKT5tROqOe9haSteA==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-ui": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-39.0.2.tgz",
+      "integrity": "sha512-OHYasdPXG1Vy1tR5hcGeffeqg6ujWzCEbRczuU+0sC3ttYkxrnFk6qYe7gjA+BoqD61otk1au+rhCVux8dy0hQ==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "color-convert": "2.0.1",
+        "color-parse": "1.4.2",
+        "lodash-es": "4.17.21",
+        "vanilla-colorful": "0.7.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-undo": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-39.0.2.tgz",
+      "integrity": "sha512-DSy7rRtnpVPpzZYOoQJNZ/6Zx4LEk3WVf8VG8wJDgpuxbRrE59DsNwVEqGEvDyVGlgzbuWZrfkkcL4hjcoYHCw==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-upload": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-39.0.2.tgz",
+      "integrity": "sha512-6LLU9lJDlnE4RT1GBzK1V6gsIv/+4NiWVojblzET9AlyMI4BRTn3/PPxZRWyPPKH96AeuIWoyj32D/a24yQujg==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-utils": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-39.0.2.tgz",
+      "integrity": "sha512-aqiGhPJxEihSLW21lGWcAvjVTTwJYxEbfMk1eLf/BEY3euy6iltRC6EqbXkyJDcKGU7cQtk6JXAIkH+D2FF87g==",
+      "dependencies": {
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-watchdog": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-39.0.2.tgz",
+      "integrity": "sha512-9E7BNp9c+nj/01JWF4lBVcDwJI2lN/Vgerw+ex4l/nTRl7crLzckSy3DWhYlpQPjJzsrkFjGQ+zCG4C/Vevl3Q==",
+      "dependencies": {
+        "lodash-es": "4.17.21"
+      }
+    },
+    "node_modules/@ckeditor/ckeditor5-widget": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-39.0.2.tgz",
+      "integrity": "sha512-bGs8iKD3c+r3/JCqhXoh/MPJut0JcdUdxDSgS+xYu1UJ03b/K39/0QbdVjT1I6oNRSDb4IUwBO2Xc3zTMl/qTw==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-enter": "39.0.2",
+        "@ckeditor/ckeditor5-typing": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
     "node_modules/@eslint-community/eslint-utils": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
       }
     },
+    "node_modules/@googlemaps/markerclusterer": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.4.1.tgz",
+      "integrity": "sha512-ETBWYVLrBiBwDYG7gBmfwSlBluYfqq469I0Lz2qnJt3bGSI6cNAfIi8qjJChcjt4fM7s7OTxGSNlylzmql0BVQ==",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.3",
+        "supercluster": "^8.0.1"
+      }
+    },
     "node_modules/@humanwhocodes/config-array": {
       "version": "0.11.10",
       "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
       "integrity": "sha512-CxTLMVtZsgrj9Ven5Pn1vcFumCFs+CG8Jfc63xWq/8b9e6uWjGyZlMnvQk7lIVn97Zd1vpu0ZK/OFWAoap0RCw=="
     },
     "node_modules/@types/google.maps": {
-      "version": "3.51.1",
-      "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.51.1.tgz",
-      "integrity": "sha512-Wtl6PUL26jEbC1NBqJi7uoyYZo1/I3EDCd9pZk9EN6ZDvKaO28M5+nIQGyYomzvkMpMHnfywpTzalhwr76/oAg=="
+      "version": "3.54.0",
+      "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.54.0.tgz",
+      "integrity": "sha512-b1MBy2eGrZoEFLnzq1RrlHbfzuWHz+Nitgqbb5N+MFA0kAUv0kYPmAXtczpb4dHlFZyu58EYzcKXtWNqSInyXg=="
     },
     "node_modules/@types/jquery": {
-      "version": "3.5.14",
-      "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz",
-      "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==",
+      "version": "3.5.16",
+      "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.16.tgz",
+      "integrity": "sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw==",
       "dependencies": {
         "@types/sizzle": "*"
       }
       "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==",
       "dev": true
     },
-    "node_modules/@types/perfect-scrollbar": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/@types/perfect-scrollbar/-/perfect-scrollbar-0.7.0.tgz",
-      "integrity": "sha512-hz9JUDS872oHDuRxi1Wqa3sdqxhZ3NkQk/T/+2Pz/nsPA6Lajf54kxocRLj6Ofi99YqzlSkDI7TrRc1qtbvzYQ==",
-      "dependencies": {
-        "@types/jquery": "*"
-      }
-    },
     "node_modules/@types/pica": {
       "version": "5.1.3",
       "resolved": "https://registry.npmjs.org/@types/pica/-/pica-5.1.3.tgz",
       "resolved": "https://registry.npmjs.org/@types/twitter-for-web/-/twitter-for-web-0.0.2.tgz",
       "integrity": "sha512-fDg882G9KHOkVxyJFkZ1hIOHxgj1vHLZnMJshF9W+8C2f9lzkIc/DeD1Ed2q1SWaHD/hdooaFIWTDhgL8zzpYg=="
     },
+    "node_modules/@types/zxcvbn": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/@types/zxcvbn/-/zxcvbn-4.4.2.tgz",
+      "integrity": "sha512-T7SEL8b/eN7AEhHQ8oFt7c6Y+l3p8OpH7KwJIe+5oBOPLMMioPeMsUTB3huNgEnXhiittV8Ohdw21Jg8E/f70Q=="
+    },
     "node_modules/@typescript-eslint/eslint-plugin": {
       "version": "6.5.0",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.5.0.tgz",
         "url": "https://opencollective.com/typescript-eslint"
       }
     },
-    "node_modules/@woltlab/wcf": {
-      "version": "5.4.0",
-      "resolved": "git+ssh://git@github.com/WoltLab/WCF.git#5ed76b3a3267dfbffdf19405822d22510ad2bc7d",
-      "integrity": "sha512-RFdoxbASRY4VpBSZkGhI6Vovf49YR4D9bjdxweJgobf+rPAcJAXmE5idzwk3osKrUS+yH2STewzsxZ6Bpak5cQ==",
+    "node_modules/@woltlab/d.ts": {
+      "resolved": "git+ssh://git@github.com/WoltLab/d.ts.git#c08648e9f82c381bd18b91ac1072c430e58e71f1",
+      "integrity": "sha512-cqNfrQOmIb3rX7qc/NtLQ/abvV5nxY8IS5ybE2h15q0X/jskjwdnSdGfX44bAbNKmjC9bQvi8LdZSzY0PNGHMw==",
       "dependencies": {
+        "@ckeditor/ckeditor5-inspector": "^4.1.0",
+        "@googlemaps/markerclusterer": "^2.0.15",
         "@types/facebook-js-sdk": "^3.3.6",
-        "@types/google.maps": "^3.51.1",
-        "@types/jquery": "^3.5.14",
-        "@types/perfect-scrollbar": "^0.7.0",
+        "@types/google.maps": "^3.54.0",
+        "@types/jquery": "^3.5.16",
         "@types/pica": "^5.1.3",
-        "@types/prismjs": "^1.16.6",
+        "@types/prismjs": "^1.26.0",
         "@types/twitter-for-web": "0.0.2",
-        "focus-trap": "^6.9.4",
+        "@woltlab/editor": "git+https://github.com/WoltLab/editor.git#c407a8efe4f3ad08d7777cd71dce30b4dd2a523a",
+        "@woltlab/zxcvbn": "git+https://github.com/WoltLab/zxcvbn.git#5b582b24e437f1883ccad3c37dae7c3c5f1e7da3",
+        "focus-trap": "^7.5.2",
+        "html-parsed-element": "^0.4.1",
+        "perfect-scrollbar": "^1.5.5",
         "qr-creator": "^1.0.0",
-        "tabbable": "^5.3.3",
-        "tslib": "^2.5.0"
+        "reflect-metadata": "^0.1.13",
+        "tabbable": "^6.2.0",
+        "tslib": "^2.6.2"
+      }
+    },
+    "node_modules/@woltlab/editor": {
+      "resolved": "git+ssh://git@github.com/WoltLab/editor.git#c407a8efe4f3ad08d7777cd71dce30b4dd2a523a",
+      "integrity": "sha512-ArKFz4h0uCEt+hPzhQN9rjJ1cQzXyASQiRlmubi4q9mYqc2ZAh1EQWUiVoaHAMPglcz0607712zJR0MQa9UYeg==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-alignment": "^39.0.2",
+        "@ckeditor/ckeditor5-autosave": "^39.0.2",
+        "@ckeditor/ckeditor5-basic-styles": "^39.0.2",
+        "@ckeditor/ckeditor5-block-quote": "^39.0.2",
+        "@ckeditor/ckeditor5-code-block": "^39.0.2",
+        "@ckeditor/ckeditor5-editor-classic": "^39.0.2",
+        "@ckeditor/ckeditor5-engine": "^39.0.2",
+        "@ckeditor/ckeditor5-essentials": "^39.0.2",
+        "@ckeditor/ckeditor5-font": "^39.0.2",
+        "@ckeditor/ckeditor5-heading": "^39.0.2",
+        "@ckeditor/ckeditor5-highlight": "^39.0.2",
+        "@ckeditor/ckeditor5-horizontal-line": "^39.0.2",
+        "@ckeditor/ckeditor5-html-embed": "^39.0.2",
+        "@ckeditor/ckeditor5-image": "^39.0.2",
+        "@ckeditor/ckeditor5-indent": "^39.0.2",
+        "@ckeditor/ckeditor5-link": "^39.0.2",
+        "@ckeditor/ckeditor5-list": "^39.0.2",
+        "@ckeditor/ckeditor5-mention": "^39.0.2",
+        "@ckeditor/ckeditor5-paragraph": "^39.0.2",
+        "@ckeditor/ckeditor5-paste-from-office": "^39.0.2",
+        "@ckeditor/ckeditor5-remove-format": "^39.0.2",
+        "@ckeditor/ckeditor5-table": "^39.0.2",
+        "@ckeditor/ckeditor5-theme-lark": "^39.0.2",
+        "@ckeditor/ckeditor5-ui": "^39.0.2",
+        "@ckeditor/ckeditor5-undo": "^39.0.2",
+        "@ckeditor/ckeditor5-utils": "^39.0.2",
+        "@ckeditor/ckeditor5-widget": "^39.0.2"
+      }
+    },
+    "node_modules/@woltlab/zxcvbn": {
+      "version": "4.4.2",
+      "resolved": "git+ssh://git@github.com/WoltLab/zxcvbn.git#5b582b24e437f1883ccad3c37dae7c3c5f1e7da3",
+      "integrity": "sha512-gi/PpP8I5YmaZV6oH8I6JfkKJhUfuKVGu6IkvQYMx3qXHXxzaCS1wSdy9WXIUG185PVRk9ca+RysLAcXd6lhYA==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/zxcvbn": "^4.4.1"
       }
     },
     "node_modules/acorn": {
         "url": "https://github.com/chalk/chalk?sponsor=1"
       }
     },
+    "node_modules/ckeditor5": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-39.0.2.tgz",
+      "integrity": "sha512-7wuhb5LYeAZ9PaEZlNNAOnfDLWozt3+tOdc1St7AYR4PO1UW/5crWHvs+6jejxB56Zk6LUaHUS6ECecdapihmA==",
+      "dependencies": {
+        "@ckeditor/ckeditor5-clipboard": "39.0.2",
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-enter": "39.0.2",
+        "@ckeditor/ckeditor5-paragraph": "39.0.2",
+        "@ckeditor/ckeditor5-select-all": "39.0.2",
+        "@ckeditor/ckeditor5-typing": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-undo": "39.0.2",
+        "@ckeditor/ckeditor5-upload": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "@ckeditor/ckeditor5-watchdog": "39.0.2",
+        "@ckeditor/ckeditor5-widget": "39.0.2"
+      }
+    },
     "node_modules/color-convert": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
       "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
       "dependencies": {
         "color-name": "~1.1.4"
       },
     "node_modules/color-name": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+    },
+    "node_modules/color-parse": {
+      "version": "1.4.2",
+      "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.4.2.tgz",
+      "integrity": "sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA==",
+      "dependencies": {
+        "color-name": "^1.0.0"
+      }
     },
     "node_modules/concat-map": {
       "version": "0.0.1",
     "node_modules/fast-deep-equal": {
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
-      "dev": true
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
     "node_modules/fast-glob": {
       "version": "3.3.1",
       "dev": true
     },
     "node_modules/focus-trap": {
-      "version": "6.9.4",
-      "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-6.9.4.tgz",
-      "integrity": "sha512-v2NTsZe2FF59Y+sDykKY+XjqZ0cPfhq/hikWVL88BqLivnNiEffAsac6rP6H45ff9wG9LL5ToiDqrLEP9GX9mw==",
+      "version": "7.5.2",
+      "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.2.tgz",
+      "integrity": "sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==",
       "dependencies": {
-        "tabbable": "^5.3.3"
+        "tabbable": "^6.2.0"
       }
     },
     "node_modules/fs.realpath": {
         "node": ">=8"
       }
     },
+    "node_modules/html-parsed-element": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/html-parsed-element/-/html-parsed-element-0.4.1.tgz",
+      "integrity": "sha512-uRNt6oVAFAQ/PBS9JZiURMpR2Me0KR11mOG6sbamJl1PIX7qMX1h/ck2EhY11RPU4m39o9x9XvOs5KaLneaxGA=="
+    },
     "node_modules/ignore": {
       "version": "5.2.4",
       "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
       "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
       "dev": true
     },
+    "node_modules/kdbush": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz",
+      "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA=="
+    },
     "node_modules/levn": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/lodash-es": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+      "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+    },
     "node_modules/lodash.merge": {
       "version": "4.6.2",
       "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
         "node": ">=8"
       }
     },
+    "node_modules/perfect-scrollbar": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz",
+      "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g=="
+    },
     "node_modules/picomatch": {
       "version": "2.3.1",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
         }
       ]
     },
+    "node_modules/reflect-metadata": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+      "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
+    },
     "node_modules/resolve-from": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/supercluster": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz",
+      "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==",
+      "dependencies": {
+        "kdbush": "^4.0.2"
+      }
+    },
     "node_modules/supports-color": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
       }
     },
     "node_modules/tabbable": {
-      "version": "5.3.3",
-      "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz",
-      "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA=="
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
+      "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
     },
     "node_modules/text-table": {
       "version": "0.2.0",
       }
     },
     "node_modules/tslib": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
-      "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+      "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
     },
     "node_modules/type-check": {
       "version": "0.4.0",
         "punycode": "^2.1.0"
       }
     },
+    "node_modules/vanilla-colorful": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz",
+      "integrity": "sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg=="
+    },
     "node_modules/which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
       "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
       "dev": true
     },
+    "@ckeditor/ckeditor5-alignment": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-39.0.2.tgz",
+      "integrity": "sha512-TjM+9h3tFn1wgnF4RJg0WaA758kT5VGSaVi0Ti6NECckPGXnccJpIQ7ZMSKAe4zCfaRSmNQsNYc20iq7w7+leg==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-autosave": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autosave/-/ckeditor5-autosave-39.0.2.tgz",
+      "integrity": "sha512-2YZwsPSFVwhqVoxU6HtQppmn8+TPnm7LmSKYt+7ESc72oqmWIcFGTkCmP5/gIt4oqz5twtJZ/v5lBg+92i3PyQ==",
+      "requires": {
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-basic-styles": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-39.0.2.tgz",
+      "integrity": "sha512-sp5sfE4d8Tng/zIssBK+SgaEkPfGcbmoGkjbHhPlWYAoQB9ONwvWkRZy9s3C+H0gfsEj3EqqxUKY70Us0yT8rA==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-block-quote": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-39.0.2.tgz",
+      "integrity": "sha512-ykxkLWJ1nuu5vVBnvHKKgKleudUNTjt/2zDsvUAiBbl4iN0rnOqhLbSL54fY4130p/DvE1CVoozqNiv7L83Vjw==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-clipboard": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-39.0.2.tgz",
+      "integrity": "sha512-SSuanBiQ4lWznXSGyeV5vqQweVWZ1+iZG1/atmrZSb/BOWa3XD6EGPu9tuzdm9MCjk2OxBuyMT07Cw+WzXFosQ==",
+      "requires": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "@ckeditor/ckeditor5-widget": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-code-block": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-code-block/-/ckeditor5-code-block-39.0.2.tgz",
+      "integrity": "sha512-VlG/+VqxrR/JWQZVsGzemr3caOgQLB5OmSsFKPBEzoMI+05zf2UM232DyBVBUfA6UJ5L/ZMkT9YdUi+XhFnhAQ==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-core": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-39.0.2.tgz",
+      "integrity": "sha512-/xtor5vIXgwBVsAj+yO/wyzezQUmXabdkb/T8aSXtO2665zeOVbDbtSsJ1Ov7Tz5A4Ia1pA9d7iDCt7E8Kva7A==",
+      "requires": {
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-editor-classic": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-39.0.2.tgz",
+      "integrity": "sha512-zDDFe70junUJT5VltMsVdBqSZUew4fCe8fmi9JMI2m2MAwNwARAOkOy9mQMMTJlrD+P3CfD/Y9QpromEjLOnYA==",
+      "requires": {
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-engine": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-39.0.2.tgz",
+      "integrity": "sha512-ERcEpIrmTML0/uhukkC+ZJSOx4mRaPbNG5vPEBXIentfDpzu1NrmUhGZRGXaw5lltL+NJbuTI0wjEINap0Hl3w==",
+      "requires": {
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-enter": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-39.0.2.tgz",
+      "integrity": "sha512-7yeZI/mzJH4/yryXFQemrueZA/UNGkfnauN8Mu6XFMykoRNo6l+cASz0x4iGb3pWumV3g+tUeX6AJmuwXkRb5A==",
+      "requires": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-essentials": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-39.0.2.tgz",
+      "integrity": "sha512-5Nf3XeuB0thXTJS2M2JYrlW2uuSujNOhwW7L05e7Z5JP4nUSkopBHdvymX9feZKMzGPOw6SVhk8gQIDYV7S28A==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-font": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-39.0.2.tgz",
+      "integrity": "sha512-6sGgo9X23gAllVjzGH1gOkjIEHkvm2O40IqUKCBwzn0K6Ry6St4R4QtcQeFV5jxAMKn0eD7blPuhItVrjmN0hw==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-heading": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-39.0.2.tgz",
+      "integrity": "sha512-P1ogDMAsTZB/TfuNwifNv1H9KHaMSPRaPfd+clhhLV/GAdt2rGMeH0HKuSke54cZYB6qMQP7Za8Xsfi2ufY0GA==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-highlight": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-highlight/-/ckeditor5-highlight-39.0.2.tgz",
+      "integrity": "sha512-WlinrcgNRgTMPCtg3ZfirEdbVpP+xSQdYGA/kmMTcjEnzfEUZv5ceecAF367158+hQNhY06p7Zpvxot8z6pobA==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-horizontal-line": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-39.0.2.tgz",
+      "integrity": "sha512-lKPqiOwmuX/9s5TclET7cywcQ76TJh/w+6u3BK8buzlmyWzdeYXUyljNqWCgiS0i2yyY4w5XaJxXB/Ey7Ks8/w==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-html-embed": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-embed/-/ckeditor5-html-embed-39.0.2.tgz",
+      "integrity": "sha512-51dt9ndDl8Ba1ETmBDwAM0u82/yyF1uY5bXnHrkfrcYwGn+pHojKMTysilmniY35fo9Rn2TaV8eBsp/2h/tYMg==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-image": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-39.0.2.tgz",
+      "integrity": "sha512-sp7ce+j/UqRW4kmhMX8DfZKPbNs5HgiEQY8ChQUPOKghstEjBrPpGFYCJ++NMPmWguDTzLxVAVuo2k+VOt+swA==",
+      "requires": {
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-indent": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-39.0.2.tgz",
+      "integrity": "sha512-wU/1jBqgkK068fxkZDxnZM5iACunABXBVtpgfXqe2S6cMPVQyhiLzo955Yt7BhqN7Mkor59xESO2+Npj/vwB7w==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-inspector": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-inspector/-/ckeditor5-inspector-4.1.0.tgz",
+      "integrity": "sha512-yKoIFpaSVQQIhgFEyoltwG40OSsWX5psYdYvNxW84nfxgrs90DJrbMQDtdchVZNMXBu6CkJfPiPG0WBLU9su3g=="
+    },
+    "@ckeditor/ckeditor5-link": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-39.0.2.tgz",
+      "integrity": "sha512-UKSamaD+yGaLPo/7pLS6bi+h2pRpX7qFSe4isVvmC8PfhN4YAm6ZYpIXpnktzfv2+/Jx6P9HzfjOnJPPT5PRdQ==",
+      "requires": {
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-list": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-39.0.2.tgz",
+      "integrity": "sha512-XRcp67PuDK/mP0sL8g+TFLIr/MigVHKATwO+7OAJZlGAGxr73V/eRw3G6ZAe6Lh0lVQPRA54r+h5DHG5P+KRRg==",
+      "requires": {
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-mention": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-mention/-/ckeditor5-mention-39.0.2.tgz",
+      "integrity": "sha512-uTRenNKntYlzqnK5urqtwWRS5Frn888tne6YRJsHUJINX1h9kxgQ44svYx6QF9ZMdStmkEbKJfjZwNfnwWd95g==",
+      "requires": {
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-paragraph": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-39.0.2.tgz",
+      "integrity": "sha512-is0+G3ghz+6EwoNT5ciySiPt05FI0I/lxPksSDl4QG9BcGUwkN94fJalCxgXuMlGulojm/YZ3dCmJPnLMrAnUA==",
+      "requires": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-paste-from-office": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-39.0.2.tgz",
+      "integrity": "sha512-Y9O1C+9BpFCtvYI80AJzm/BkZWMedhreCaZcSCsEUUIo6vrIwehatTvgqWZJLwKZwL+4iy5/Kv9OfUhvO10I8Q==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-remove-format": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-39.0.2.tgz",
+      "integrity": "sha512-gCoWMMUyvqjtQs+EUr7JpO8LEF2Ip7qXmCuSwLTteet79a8sQyllPY6O3UOUEuFMO2GtT36+jtQ93pQh7onn+g==",
+      "requires": {
+        "ckeditor5": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-select-all": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-39.0.2.tgz",
+      "integrity": "sha512-/zTPZ14sfsL6E7LHcdOSW5JR7A5tsaSO2KNlQ/jm77XWSeQ7HZ4I7hoLXWksvcseubQ+xExWrzMQIjIOGqBLcQ==",
+      "requires": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-table": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-39.0.2.tgz",
+      "integrity": "sha512-IpI53KPEOj1F1vbMYUHLkOeoQoQV/q3pfiJxXXHZja1QaIEnqZT7YcSvJQbCyiuQw4UCZqU5x84c8GcyIZlBhg==",
+      "requires": {
+        "ckeditor5": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-theme-lark": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-39.0.2.tgz",
+      "integrity": "sha512-v6S3++hkoKgqV71BCafKWYmPA6o/X44kUzdahnFs1rYBM5WS87y9Jb0W8Rv8FXXD5QD0H2axtySw9S6HfYspQw==",
+      "requires": {
+        "@ckeditor/ckeditor5-ui": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-typing": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-39.0.2.tgz",
+      "integrity": "sha512-ylkBumukIRe/8jQTanVYNcExvoraXX9TIX3POwiug2F+c/POKjoHgeq8+Wf/JEl7/ydtXZKT5tROqOe9haSteA==",
+      "requires": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-ui": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-39.0.2.tgz",
+      "integrity": "sha512-OHYasdPXG1Vy1tR5hcGeffeqg6ujWzCEbRczuU+0sC3ttYkxrnFk6qYe7gjA+BoqD61otk1au+rhCVux8dy0hQ==",
+      "requires": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "color-convert": "2.0.1",
+        "color-parse": "1.4.2",
+        "lodash-es": "4.17.21",
+        "vanilla-colorful": "0.7.2"
+      }
+    },
+    "@ckeditor/ckeditor5-undo": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-39.0.2.tgz",
+      "integrity": "sha512-DSy7rRtnpVPpzZYOoQJNZ/6Zx4LEk3WVf8VG8wJDgpuxbRrE59DsNwVEqGEvDyVGlgzbuWZrfkkcL4hjcoYHCw==",
+      "requires": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-upload": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-39.0.2.tgz",
+      "integrity": "sha512-6LLU9lJDlnE4RT1GBzK1V6gsIv/+4NiWVojblzET9AlyMI4BRTn3/PPxZRWyPPKH96AeuIWoyj32D/a24yQujg==",
+      "requires": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2"
+      }
+    },
+    "@ckeditor/ckeditor5-utils": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-39.0.2.tgz",
+      "integrity": "sha512-aqiGhPJxEihSLW21lGWcAvjVTTwJYxEbfMk1eLf/BEY3euy6iltRC6EqbXkyJDcKGU7cQtk6JXAIkH+D2FF87g==",
+      "requires": {
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-watchdog": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-39.0.2.tgz",
+      "integrity": "sha512-9E7BNp9c+nj/01JWF4lBVcDwJI2lN/Vgerw+ex4l/nTRl7crLzckSy3DWhYlpQPjJzsrkFjGQ+zCG4C/Vevl3Q==",
+      "requires": {
+        "lodash-es": "4.17.21"
+      }
+    },
+    "@ckeditor/ckeditor5-widget": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-39.0.2.tgz",
+      "integrity": "sha512-bGs8iKD3c+r3/JCqhXoh/MPJut0JcdUdxDSgS+xYu1UJ03b/K39/0QbdVjT1I6oNRSDb4IUwBO2Xc3zTMl/qTw==",
+      "requires": {
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-enter": "39.0.2",
+        "@ckeditor/ckeditor5-typing": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "lodash-es": "4.17.21"
+      }
+    },
     "@eslint-community/eslint-utils": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
       "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==",
       "dev": true
     },
+    "@googlemaps/markerclusterer": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/@googlemaps/markerclusterer/-/markerclusterer-2.4.1.tgz",
+      "integrity": "sha512-ETBWYVLrBiBwDYG7gBmfwSlBluYfqq469I0Lz2qnJt3bGSI6cNAfIi8qjJChcjt4fM7s7OTxGSNlylzmql0BVQ==",
+      "requires": {
+        "fast-deep-equal": "^3.1.3",
+        "supercluster": "^8.0.1"
+      }
+    },
     "@humanwhocodes/config-array": {
       "version": "0.11.10",
       "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
       "integrity": "sha512-CxTLMVtZsgrj9Ven5Pn1vcFumCFs+CG8Jfc63xWq/8b9e6uWjGyZlMnvQk7lIVn97Zd1vpu0ZK/OFWAoap0RCw=="
     },
     "@types/google.maps": {
-      "version": "3.51.1",
-      "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.51.1.tgz",
-      "integrity": "sha512-Wtl6PUL26jEbC1NBqJi7uoyYZo1/I3EDCd9pZk9EN6ZDvKaO28M5+nIQGyYomzvkMpMHnfywpTzalhwr76/oAg=="
+      "version": "3.54.0",
+      "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.54.0.tgz",
+      "integrity": "sha512-b1MBy2eGrZoEFLnzq1RrlHbfzuWHz+Nitgqbb5N+MFA0kAUv0kYPmAXtczpb4dHlFZyu58EYzcKXtWNqSInyXg=="
     },
     "@types/jquery": {
-      "version": "3.5.14",
-      "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz",
-      "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==",
+      "version": "3.5.16",
+      "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.16.tgz",
+      "integrity": "sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw==",
       "requires": {
         "@types/sizzle": "*"
       }
       "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==",
       "dev": true
     },
-    "@types/perfect-scrollbar": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/@types/perfect-scrollbar/-/perfect-scrollbar-0.7.0.tgz",
-      "integrity": "sha512-hz9JUDS872oHDuRxi1Wqa3sdqxhZ3NkQk/T/+2Pz/nsPA6Lajf54kxocRLj6Ofi99YqzlSkDI7TrRc1qtbvzYQ==",
-      "requires": {
-        "@types/jquery": "*"
-      }
-    },
     "@types/pica": {
       "version": "5.1.3",
       "resolved": "https://registry.npmjs.org/@types/pica/-/pica-5.1.3.tgz",
       "resolved": "https://registry.npmjs.org/@types/twitter-for-web/-/twitter-for-web-0.0.2.tgz",
       "integrity": "sha512-fDg882G9KHOkVxyJFkZ1hIOHxgj1vHLZnMJshF9W+8C2f9lzkIc/DeD1Ed2q1SWaHD/hdooaFIWTDhgL8zzpYg=="
     },
+    "@types/zxcvbn": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/@types/zxcvbn/-/zxcvbn-4.4.2.tgz",
+      "integrity": "sha512-T7SEL8b/eN7AEhHQ8oFt7c6Y+l3p8OpH7KwJIe+5oBOPLMMioPeMsUTB3huNgEnXhiittV8Ohdw21Jg8E/f70Q=="
+    },
     "@typescript-eslint/eslint-plugin": {
       "version": "6.5.0",
       "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.5.0.tgz",
         "eslint-visitor-keys": "^3.4.1"
       }
     },
-    "@woltlab/wcf": {
-      "version": "git+ssh://git@github.com/WoltLab/WCF.git#5ed76b3a3267dfbffdf19405822d22510ad2bc7d",
-      "integrity": "sha512-RFdoxbASRY4VpBSZkGhI6Vovf49YR4D9bjdxweJgobf+rPAcJAXmE5idzwk3osKrUS+yH2STewzsxZ6Bpak5cQ==",
-      "from": "@woltlab/wcf@https://github.com/WoltLab/WCF.git#5ed76b3a3267dfbffdf19405822d22510ad2bc7d",
+    "@woltlab/d.ts": {
+      "version": "git+ssh://git@github.com/WoltLab/d.ts.git#c08648e9f82c381bd18b91ac1072c430e58e71f1",
+      "integrity": "sha512-cqNfrQOmIb3rX7qc/NtLQ/abvV5nxY8IS5ybE2h15q0X/jskjwdnSdGfX44bAbNKmjC9bQvi8LdZSzY0PNGHMw==",
+      "from": "@woltlab/d.ts@https://github.com/WoltLab/d.ts.git#c08648e9f82c381bd18b91ac1072c430e58e71f1",
       "requires": {
+        "@ckeditor/ckeditor5-inspector": "^4.1.0",
+        "@googlemaps/markerclusterer": "^2.0.15",
         "@types/facebook-js-sdk": "^3.3.6",
-        "@types/google.maps": "^3.51.1",
-        "@types/jquery": "^3.5.14",
-        "@types/perfect-scrollbar": "^0.7.0",
+        "@types/google.maps": "^3.54.0",
+        "@types/jquery": "^3.5.16",
         "@types/pica": "^5.1.3",
-        "@types/prismjs": "^1.16.6",
+        "@types/prismjs": "^1.26.0",
         "@types/twitter-for-web": "0.0.2",
-        "focus-trap": "^6.9.4",
+        "@woltlab/editor": "git+https://github.com/WoltLab/editor.git#c407a8efe4f3ad08d7777cd71dce30b4dd2a523a",
+        "@woltlab/zxcvbn": "git+https://github.com/WoltLab/zxcvbn.git#5b582b24e437f1883ccad3c37dae7c3c5f1e7da3",
+        "focus-trap": "^7.5.2",
+        "html-parsed-element": "^0.4.1",
+        "perfect-scrollbar": "^1.5.5",
         "qr-creator": "^1.0.0",
-        "tabbable": "^5.3.3",
-        "tslib": "^2.5.0"
+        "reflect-metadata": "^0.1.13",
+        "tabbable": "^6.2.0",
+        "tslib": "^2.6.2"
+      }
+    },
+    "@woltlab/editor": {
+      "version": "git+ssh://git@github.com/WoltLab/editor.git#c407a8efe4f3ad08d7777cd71dce30b4dd2a523a",
+      "integrity": "sha512-ArKFz4h0uCEt+hPzhQN9rjJ1cQzXyASQiRlmubi4q9mYqc2ZAh1EQWUiVoaHAMPglcz0607712zJR0MQa9UYeg==",
+      "from": "@woltlab/editor@git+https://github.com/WoltLab/editor.git#c407a8efe4f3ad08d7777cd71dce30b4dd2a523a",
+      "requires": {
+        "@ckeditor/ckeditor5-alignment": "^39.0.2",
+        "@ckeditor/ckeditor5-autosave": "^39.0.2",
+        "@ckeditor/ckeditor5-basic-styles": "^39.0.2",
+        "@ckeditor/ckeditor5-block-quote": "^39.0.2",
+        "@ckeditor/ckeditor5-code-block": "^39.0.2",
+        "@ckeditor/ckeditor5-editor-classic": "^39.0.2",
+        "@ckeditor/ckeditor5-engine": "^39.0.2",
+        "@ckeditor/ckeditor5-essentials": "^39.0.2",
+        "@ckeditor/ckeditor5-font": "^39.0.2",
+        "@ckeditor/ckeditor5-heading": "^39.0.2",
+        "@ckeditor/ckeditor5-highlight": "^39.0.2",
+        "@ckeditor/ckeditor5-horizontal-line": "^39.0.2",
+        "@ckeditor/ckeditor5-html-embed": "^39.0.2",
+        "@ckeditor/ckeditor5-image": "^39.0.2",
+        "@ckeditor/ckeditor5-indent": "^39.0.2",
+        "@ckeditor/ckeditor5-link": "^39.0.2",
+        "@ckeditor/ckeditor5-list": "^39.0.2",
+        "@ckeditor/ckeditor5-mention": "^39.0.2",
+        "@ckeditor/ckeditor5-paragraph": "^39.0.2",
+        "@ckeditor/ckeditor5-paste-from-office": "^39.0.2",
+        "@ckeditor/ckeditor5-remove-format": "^39.0.2",
+        "@ckeditor/ckeditor5-table": "^39.0.2",
+        "@ckeditor/ckeditor5-theme-lark": "^39.0.2",
+        "@ckeditor/ckeditor5-ui": "^39.0.2",
+        "@ckeditor/ckeditor5-undo": "^39.0.2",
+        "@ckeditor/ckeditor5-utils": "^39.0.2",
+        "@ckeditor/ckeditor5-widget": "^39.0.2"
+      }
+    },
+    "@woltlab/zxcvbn": {
+      "version": "git+ssh://git@github.com/WoltLab/zxcvbn.git#5b582b24e437f1883ccad3c37dae7c3c5f1e7da3",
+      "integrity": "sha512-gi/PpP8I5YmaZV6oH8I6JfkKJhUfuKVGu6IkvQYMx3qXHXxzaCS1wSdy9WXIUG185PVRk9ca+RysLAcXd6lhYA==",
+      "from": "@woltlab/zxcvbn@git+https://github.com/WoltLab/zxcvbn.git#5b582b24e437f1883ccad3c37dae7c3c5f1e7da3",
+      "requires": {
+        "@types/zxcvbn": "^4.4.1"
       }
     },
     "acorn": {
         "supports-color": "^7.1.0"
       }
     },
+    "ckeditor5": {
+      "version": "39.0.2",
+      "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-39.0.2.tgz",
+      "integrity": "sha512-7wuhb5LYeAZ9PaEZlNNAOnfDLWozt3+tOdc1St7AYR4PO1UW/5crWHvs+6jejxB56Zk6LUaHUS6ECecdapihmA==",
+      "requires": {
+        "@ckeditor/ckeditor5-clipboard": "39.0.2",
+        "@ckeditor/ckeditor5-core": "39.0.2",
+        "@ckeditor/ckeditor5-engine": "39.0.2",
+        "@ckeditor/ckeditor5-enter": "39.0.2",
+        "@ckeditor/ckeditor5-paragraph": "39.0.2",
+        "@ckeditor/ckeditor5-select-all": "39.0.2",
+        "@ckeditor/ckeditor5-typing": "39.0.2",
+        "@ckeditor/ckeditor5-ui": "39.0.2",
+        "@ckeditor/ckeditor5-undo": "39.0.2",
+        "@ckeditor/ckeditor5-upload": "39.0.2",
+        "@ckeditor/ckeditor5-utils": "39.0.2",
+        "@ckeditor/ckeditor5-watchdog": "39.0.2",
+        "@ckeditor/ckeditor5-widget": "39.0.2"
+      }
+    },
     "color-convert": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
       "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
       "requires": {
         "color-name": "~1.1.4"
       }
     "color-name": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+    },
+    "color-parse": {
+      "version": "1.4.2",
+      "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.4.2.tgz",
+      "integrity": "sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA==",
+      "requires": {
+        "color-name": "^1.0.0"
+      }
     },
     "concat-map": {
       "version": "0.0.1",
     "fast-deep-equal": {
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
-      "dev": true
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
     "fast-glob": {
       "version": "3.3.1",
       "dev": true
     },
     "focus-trap": {
-      "version": "6.9.4",
-      "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-6.9.4.tgz",
-      "integrity": "sha512-v2NTsZe2FF59Y+sDykKY+XjqZ0cPfhq/hikWVL88BqLivnNiEffAsac6rP6H45ff9wG9LL5ToiDqrLEP9GX9mw==",
+      "version": "7.5.2",
+      "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.2.tgz",
+      "integrity": "sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==",
       "requires": {
-        "tabbable": "^5.3.3"
+        "tabbable": "^6.2.0"
       }
     },
     "fs.realpath": {
       "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
       "dev": true
     },
+    "html-parsed-element": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/html-parsed-element/-/html-parsed-element-0.4.1.tgz",
+      "integrity": "sha512-uRNt6oVAFAQ/PBS9JZiURMpR2Me0KR11mOG6sbamJl1PIX7qMX1h/ck2EhY11RPU4m39o9x9XvOs5KaLneaxGA=="
+    },
     "ignore": {
       "version": "5.2.4",
       "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
       "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
       "dev": true
     },
+    "kdbush": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz",
+      "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA=="
+    },
     "levn": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
         "p-locate": "^5.0.0"
       }
     },
+    "lodash-es": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+      "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+    },
     "lodash.merge": {
       "version": "4.6.2",
       "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
       "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
       "dev": true
     },
+    "perfect-scrollbar": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz",
+      "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g=="
+    },
     "picomatch": {
       "version": "2.3.1",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
       "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
       "dev": true
     },
+    "reflect-metadata": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+      "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
+    },
     "resolve-from": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
       "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
       "dev": true
     },
+    "supercluster": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz",
+      "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==",
+      "requires": {
+        "kdbush": "^4.0.2"
+      }
+    },
     "supports-color": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
       }
     },
     "tabbable": {
-      "version": "5.3.3",
-      "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz",
-      "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA=="
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
+      "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
     },
     "text-table": {
       "version": "0.2.0",
       "requires": {}
     },
     "tslib": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
-      "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+      "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
     },
     "type-check": {
       "version": "0.4.0",
         "punycode": "^2.1.0"
       }
     },
+    "vanilla-colorful": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz",
+      "integrity": "sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg=="
+    },
     "which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
index d343cc641e96b17b9accfb24b434e39fa4c53eb0..8e4bccb861ae3cf7a7e7b71198fd45b351425f2f 100644 (file)
@@ -5,10 +5,9 @@
     "eslint": "^8.48.0",
     "eslint-config-prettier": "^9.0.0",
     "prettier": "^3.0.3",
-    "tslib": "^2.6.0",
     "typescript": "^5.2.2"
   },
   "dependencies": {
-    "@woltlab/wcf": "https://github.com/WoltLab/WCF.git#5ed76b3a3267dfbffdf19405822d22510ad2bc7d"
+    "@woltlab/d.ts": "https://github.com/WoltLab/d.ts.git#c08648e9f82c381bd18b91ac1072c430e58e71f1"
   }
 }
index a1e6231b1fd58ff7f9c721850e8cea7199a1d801..b1ca9e74e221821206f8726037bb86eb118ad0d2 100644 (file)
@@ -3,10 +3,10 @@
        <packageinformation>
                <packagename>WoltLab Suite Core: Conversations</packagename>
                <packagename language="de">WoltLab Suite Core: Konversationen</packagename>
-               <packagedescription>Private conversations between multiple users</packagedescription>
-               <packagedescription language="de">Private Konversationen zwischen mehreren Benutzern</packagedescription>
-               <version>5.5.17</version>
-               <date>2023-09-26</date>
+               <packagedescription>Private conversations between multiple users.</packagedescription>
+               <packagedescription language="de">Private Konversationen zwischen mehreren Benutzern.</packagedescription>
+               <version>6.0.0 RC 1</version>
+               <date>2023-09-15</date>
        </packageinformation>
        
        <authorinformation>
        </authorinformation>
        
        <requiredpackages>
-               <requiredpackage minversion="5.5.17">com.woltlab.wcf</requiredpackage>
+               <requiredpackage minversion="6.0.0 RC 1">com.woltlab.wcf</requiredpackage>
        </requiredpackages>
        
        <excludedpackages>
-               <excludedpackage version="5.6.0 Alpha 1">com.woltlab.wcf</excludedpackage>
+               <excludedpackage version="6.1.0 Alpha 1">com.woltlab.wcf</excludedpackage>
        </excludedpackages>
        
        <instructions type="install">
                <instruction type="eventListener" />
                <instruction type="page" />
        </instructions>
-       
-       <instructions type="update" fromversion="5.5.16">
-               <instruction type="file"/>
+
+       <instructions type="update" fromversion="5.5.*">
+               <instruction type="file" />
+               <instruction type="database">acp/database/install_com.woltlab.wcf.conversation.php</instruction>
+               <instruction type="userGroupOption" />
+               <instruction type="template" />
+               <instruction type="acpTemplate" />
+               <instruction type="option" />
+               <instruction type="templateListener" />
+               <instruction type="language" />
+               <instruction type="objectType" />
+               <instruction type="clipboardAction" />
+               <instruction type="coreObject" />
+               <instruction type="userNotificationEvent" />
+               <instruction type="userOption" />
+               <instruction type="eventListener" />
+               <instruction type="page" />
+
+               <instruction type="fileDelete" />
+               <instruction type="templateDelete" />
+       </instructions>
+
+       <instructions type="update" fromversion="6.0.0 Beta 1">
+               <void/>
        </instructions>
 </package>
index f1379e86e094b554dce6fda123a81d7b7276ff9c..ab67efda2c30fe221bdf9c8471190554616d2730 100644 (file)
@@ -1,11 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <data xmlns="http://www.woltlab.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.woltlab.com http://www.woltlab.com/XSD/2019/templateDelete.xsd">
        <delete>
-               <template>__userStartConversation</template>
-               <template>conversationListUnread</template>
-               <template>conversationLog</template>
-               <template>conversationMessageAdd</template>
-               <template>conversationMessageEdit</template>
-               <template>searchResultConversationMessage</template>
+               <template>conversationListUserPanel</template>
        </delete>
 </data>
index 508f7629b5a3cf9885a4ae8a1d04bc6a72b085c0..bc8b25821b1c17d0638f477e7fc1f65cc2fb83ec 100644 (file)
                        <eventname>menuInteraction</eventname>
                        <templatecode><![CDATA[{include file='__userProfileStartConversation'}]]></templatecode>
                </templatelistener>
-               <templatelistener name="mobileMenuConversation">
-                       <environment>user</environment>
-                       <templatename>pageMenuMobile</templatename>
-                       <eventname>userMenuItems</eventname>
-                       <templatecode><![CDATA[{include file='__mobileMenuConversation'}]]></templatecode>
-               </templatelistener>
                <templatelistener name="userGroupAddCanBeAddedAsConversationParticipant">
                        <environment>admin</environment>
                        <templatename>userGroupAdd</templatename>
                        <templatecode><![CDATA[{include file='__userGroupAddCanBeAddedAsConversationParticipant'}]]></templatecode>
                </templatelistener>
        </import>
+       <delete>
+               <templatelistener name="mobileMenuConversation">
+                       <environment>user</environment>
+                       <templatename>pageMenuMobile</templatename>
+                       <eventname>userMenuItems</eventname>
+                       <templatecode><![CDATA[{include file='__mobileMenuConversation'}]]></templatecode>
+               </templatelistener>
+       </delete>
 </data>
diff --git a/templates/__mobileMenuConversation.tpl b/templates/__mobileMenuConversation.tpl
deleted file mode 100644 (file)
index ce80998..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-{if MODULE_CONVERSATION && $__wcf->user->userID && $__wcf->session->getPermission('user.conversation.canUseConversation')}
-       <li class="menuOverlayItem" data-more="com.woltlab.wcf.conversation">
-               <a href="{link controller='ConversationList'}{/link}" class="menuOverlayItemLink menuOverlayItemBadge box24" data-badge-identifier="unreadConversations">
-                       <span class="icon icon24 fa-comments"></span>
-                       <span class="menuOverlayItemTitle">{lang}wcf.conversation.conversations{/lang}</span>
-                       {if $__wcf->getConversationHandler()->getUnreadConversationCount()}<span class="badge badgeUpdate">{#$__wcf->getConversationHandler()->getUnreadConversationCount()}</span>{/if}
-               </a>
-       </li>
-{/if}
index 33b1a158aeefbc303714980dd9efe6c5c3a2c886..71d33136e47148a71d92007119d13020a30ce737 100644 (file)
@@ -1,8 +1,8 @@
-{if $__searchAreaInitialized|empty && $templateName|substr:0:12 == 'conversation'}
+{if $__searchAreaInitialized|empty && $templateName|str_starts_with:'conversation'}
        {assign var='__searchObjectTypeName' value='com.woltlab.wcf.conversation.message'}
        
        {if $__wcf->getActivePage()->identifier == 'com.woltlab.wcf.conversation.Conversation'}
                {capture assign='__searchTypeLabel'}{lang}wcf.search.type.com.woltlab.wcf.conversation{/lang}{/capture}
-               {capture assign='__searchTypesScoped'}<li><a href="#" data-extended-link="{link controller='Search'}extended=1&type=com.woltlab.wcf.conversation.message{/link}" data-object-type="com.woltlab.wcf.conversation.message" data-parameters='{ "conversationID": {@$conversation->conversationID} }'>{lang}wcf.search.type.com.woltlab.wcf.conversation{/lang}</a></li>{/capture}
+               {capture assign='__searchTypesScoped'}<li><a href="#" data-extended-link="{link controller='Search'}extended=1&type=com.woltlab.wcf.conversation.message{/link}" data-object-type="com.woltlab.wcf.conversation.message" data-parameters='{ "conversationID": {$conversation->conversationID} }'>{lang}wcf.search.type.com.woltlab.wcf.conversation{/lang}</a></li>{/capture}
        {/if}
 {/if}
index 9c31c4d45890d5bc8755cdb3c1ef097fd9fc7a60..6d1ef1fd455b3eb6f7b9712e881de79a85a5a768 100644 (file)
@@ -1,3 +1,8 @@
 {if MODULE_CONVERSATION && $__wcf->user->userID && $__wcf->session->getPermission('user.conversation.canUseConversation') && $__wcf->session->getPermission('user.conversation.canStartConversation') && $user->userID != $__wcf->user->userID}
-       <li><a class="jsTooltip" href="{link controller='ConversationAdd'}userID={@$user->userID}{/link}" title="{lang}wcf.conversation.button.add{/lang}"><span class="icon icon16 fa-comments"></span> <span class="invisible">{lang}wcf.conversation.button.add{/lang}</span></a></li>
-{/if}
\ No newline at end of file
+       <li>
+               <a class="jsTooltip" href="{link controller='ConversationAdd'}userID={@$user->userID}{/link}" title="{lang}wcf.conversation.button.add{/lang}">
+                       {icon name='comments' type='solid'}
+                       <span class="invisible">{lang}wcf.conversation.button.add{/lang}</span>
+               </a>
+       </li>
+{/if}
index a7bb916cdf6e3c1ba47af7c615f58d2fe1eff3d1..4fdc3d7b66575262122f7554b2b16a37e8a30bbc 100644 (file)
@@ -9,10 +9,14 @@
                        aria-haspopup="true"
                        aria-expanded="false"
                >
-                       <span class="icon icon32 fa-comments"></span> <span>{lang}wcf.conversation.conversations{/lang}</span> {if $__wcf->getConversationHandler()->getUnreadConversationCount()}<span class="badge badgeUpdate">{#$__wcf->getConversationHandler()->getUnreadConversationCount()}</span>{/if}
+                       {icon size=32 name='comments' type='solid'}
+                       <span>{lang}wcf.conversation.conversations{/lang}</span>
+                       {if $__wcf->getConversationHandler()->getUnreadConversationCount()}
+                               <span class="badge badgeUpdate">{#$__wcf->getConversationHandler()->getUnreadConversationCount()}</span>
+                       {/if}
                </a>
                {if !OFFLINE || $__wcf->session->getPermission('admin.general.canViewPageDuringOfflineMode')}
-                       <script data-relocate="true" src="{@$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
+                       <script data-relocate="true" src="{$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
                        <script data-relocate="true">
                                require(["WoltLabSuite/Core/Conversation/Ui/User/Menu/Data/Conversation"], ({ setup }) => {
                                        setup({
index e15374b98db48b08d670539999696b289c4cd7e9..0ad06769f7cafa18416d529fc6c8767dfc76f7b0 100644 (file)
@@ -7,12 +7,12 @@
                </div>
                
                <div class="contentHeaderTitle">
-                       <h1 class="contentTitle jsConversationSubject" data-conversation-id="{@$conversation->conversationID}">{$conversation->subject}</h1>
+                       <h1 class="contentTitle jsConversationSubject" data-conversation-id="{$conversation->conversationID}">{$conversation->subject}</h1>
                        
                        <ul class="inlineList contentHeaderMetaData">
                                {hascontent}
                                        <li>
-                                               <span class="icon icon16 fa-tags"></span>
+                                               {icon name='tags'}
                                                <ul class="labelList">
                                                        {content}
                                                                {foreach from=$conversation->getAssignedLabels() item=label}
                                {/hascontent}
                                
                                <li>
-                                       <span class="icon icon16 fa-user"></span>
+                                       {icon name='user'}
                                        {user object=$conversation->getUserProfile()}
                                </li>
                                
                                <li>
-                                       <span class="icon icon16 fa-clock-o"></span>
-                                       <a href="{$conversation->getLink()}">{@$conversation->time|time}</a>
+                                       {icon name='clock'}
+                                       <a href="{$conversation->getLink()}">{time time=$conversation->time}</a>
                                </li>
                                
                                {if $conversation->isClosed}
                                        <li>
-                                               <span class="icon icon16 fa-lock jsIconLock"></span>
+                                               <span class="jsIconLock">
+                                                       {icon name='lock'}
+                                               </span>
                                                {lang}wcf.global.state.closed{/lang}
                                        </li>
                                {/if}
                        <nav class="contentHeaderNavigation">
                                <ul>
                                        {content}
-                                               {if $conversation->canReply()}<li class="jsOnly"><a href="#" class="button buttonPrimary jsQuickReply"><span class="icon icon16 fa-reply"></span> <span>{lang}wcf.conversation.message.button.add{/lang}</span></a></li>{/if}
+                                               {if $conversation->canReply()}
+                                                       <li class="jsOnly">
+                                                               <button type="button" class="button buttonPrimary jsQuickReply">
+                                                                       {icon name='reply'}
+                                                                       <span>{lang}wcf.conversation.message.button.add{/lang}</span>
+                                                               </button>
+                                                       </li>
+                                               {/if}
                                                {event name='contentHeaderNavigation'}
                                        {/content}
                                </ul>
 {/capture}
 
 {capture assign='contentInteractionButtons'}
-       <div class="conversation jsConversationInlineEditorContainer contentInteractionButton" data-conversation-id="{@$conversation->conversationID}" data-label-ids="[ {implode from=$conversation->getAssignedLabels() item=label}{@$label->labelID}{/implode} ]" data-is-closed="{@$conversation->isClosed}" data-can-close-conversation="{if $conversation->userID == $__wcf->getUser()->userID}1{else}0{/if}" data-can-add-participants="{if $conversation->canAddParticipants()}1{else}0{/if}" data-is-draft="{if $conversation->isDraft}1{else}0{/if}">
-               <a href="{if $conversation->isDraft}{link controller='ConversationDraftEdit' id=$conversation->conversationID}{/link}{else}#{/if}" class="button small jsConversationInlineEditor"><span class="icon icon16 fa-pencil"></span> <span>{lang}wcf.global.button.edit{/lang}</span></a>
+       <div class="conversation jsConversationInlineEditorContainer contentInteractionButton" data-conversation-id="{$conversation->conversationID}" data-label-ids="[ {implode from=$conversation->getAssignedLabels() item=label}{$label->labelID}{/implode} ]" data-is-closed="{$conversation->isClosed}" data-can-close-conversation="{if $conversation->userID == $__wcf->getUser()->userID}1{else}0{/if}" data-can-add-participants="{if $conversation->canAddParticipants()}1{else}0{/if}" data-is-draft="{if $conversation->isDraft}1{else}0{/if}">
+               {if $conversation->isDraft}
+                       <a href="{link controller='ConversationDraftEdit' id=$conversation->conversationID}{/link}" class="button small jsConversationInlineEditor">
+                               {icon name='pencil'}
+                               <span>{lang}wcf.global.button.edit{/lang}</span>
+                       </a>
+               {else}
+                       <button type="button" class="button small jsConversationInlineEditor">
+                               {icon name='pencil'}
+                               <span>{lang}wcf.global.button.edit{/lang}</span>
+                       </button>
+               {/if}
        </div>
 {/capture}
 
@@ -73,7 +92,7 @@
                
                <ul class="containerBoxList tripleColumned conversationParticipantList jsObjectActionContainer" data-object-action-class-name="wcf\data\conversation\ConversationAction">
                        {foreach from=$participants item=participant}
-                               <li class="jsParticipant jsObjectActionObject{if !$participant->userID || $participant->hideConversation == 2 || $participant->leftAt > 0} conversationLeft{/if}" data-object-id="{@$conversation->getObjectID()}">
+                               <li class="jsParticipant jsObjectActionObject{if !$participant->userID || $participant->hideConversation == 2 || $participant->leftAt > 0} conversationLeft{/if}" data-object-id="{$conversation->getObjectID()}">
                                        <div class="box24">
                                                {user object=$participant type='avatar24' ariaHidden='true' tabindex='-1'}
                                                <div>
                                                                {user object=$participant}
                                                                {if $participant->isInvisible}<small>({lang}wcf.conversation.invisible{/lang})</small>{/if}
                                                                {if $participant->userID && ($conversation->userID == $__wcf->getUser()->userID) && ($participant->userID != $__wcf->getUser()->userID) && $participant->hideConversation != 2 && $participant->leftAt == 0}
-                                                                       <a href="#" class="jsObjectAction jsTooltip jsOnly" data-object-action="removeParticipant" title="{lang}wcf.conversation.participants.removeParticipant{/lang}" data-confirm-message="{lang __encode=true}wcf.conversation.participants.removeParticipant.confirmMessage{/lang}" data-object-action-parameter-user-id="{@$participant->getObjectID()}"><span class="icon icon16 fa-times"></span></a>
+                                                                       <button
+                                                                               type="button"
+                                                                               class="jsObjectAction jsTooltip jsOnly"
+                                                                               data-object-action="removeParticipant"
+                                                                               title="{lang}wcf.conversation.participants.removeParticipant{/lang}"
+                                                                               data-confirm-message="{lang __encode=true}wcf.conversation.participants.removeParticipant.confirmMessage{/lang}"
+                                                                               data-object-action-parameter-user-id="{$participant->getObjectID()}"
+                                                                       >
+                                                                               {icon name='xmark'}
+                                                                       </button>
                                                                {/if}
                                                        </p>
                                                        <dl class="plain inlineDataList small">
                                                                <dt>{lang}wcf.conversation.lastVisitTime{/lang}</dt>
-                                                               <dd>{if $participant->lastVisitTime}{@$participant->lastVisitTime|time}{else}-{/if}</dd>
+                                                               <dd>{if $participant->lastVisitTime}{time time=$participant->lastVisitTime}{else}-{/if}</dd>
                                                        </dl>
                                                </div>
                                        </div>
        </ul>
 </div>
 
-{if !ENABLE_DEBUG_MODE}<script src="{@$__wcf->getPath()}js/WoltLabSuite.Core.Conversation.min.js?v={@LAST_UPDATE_TIME}"></script>{/if}
-<script data-relocate="true" src="{@$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
+{if !ENABLE_DEBUG_MODE}<script src="{$__wcf->getPath()}js/WoltLabSuite.Core.Conversation.min.js?v={@LAST_UPDATE_TIME}"></script>{/if}
+<script data-relocate="true" src="{$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
 <script data-relocate="true">
        $(function() {
                WCF.Language.addObject({
                        'wcf.global.subject': '{jslang}wcf.global.subject{/jslang}',
                        'wcf.message.bbcode.code.copy': '{jslang}wcf.message.bbcode.code.copy{/jslang}',
                        'wcf.message.error.editorAlreadyInUse': '{jslang}wcf.message.error.editorAlreadyInUse{/jslang}',
-                       'wcf.moderation.report.reportContent': '{jslang}wcf.moderation.report.reportContent{/jslang}',
-                       'wcf.moderation.report.success': '{jslang}wcf.moderation.report.success{/jslang}',
                        'wcf.conversation.label.assignLabels': '{jslang}wcf.conversation.label.assignLabels{/jslang}'
                });
                
-               var $availableLabels = [ {implode from=$labelList item=label}{ cssClassName: '{if $label->cssClassName}{@$label->cssClassName}{/if}', labelID: {@$label->labelID}, label: '{$label->label|encodeJS}' }{/implode} ];
+               var $availableLabels = [ {implode from=$labelList item=label}{ cssClassName: '{if $label->cssClassName}{@$label->cssClassName|encodeJS}{/if}', labelID: {@$label->labelID}, label: '{$label->label|encodeJS}' }{/implode} ];
                var $editorHandler = new WCF.Conversation.EditorHandlerConversation($availableLabels);
                var $inlineEditor = new WCF.Conversation.InlineEditor('.conversation');
                $inlineEditor.setEditorHandler($editorHandler);
                                });
                        });
                {/if}
-               
-               {if $__wcf->session->getPermission('user.profile.canReportContent')}
-                       new WCF.Moderation.Report.Content('com.woltlab.wcf.conversation.message', '.jsReportConversationMessage');
-               {/if}
        });
        
        require(['WoltLabSuite/Core/Conversation/Ui/Object/Action/RemoveParticipant'], (UiObjectActionRemoveParticipant) => {
index ced41203dcbc21181c89f1dfcadb9915d18a0693..175eb430475822d1516fd1fc7b71ef7f13cdec94 100644 (file)
@@ -9,7 +9,7 @@
                <dl{if $errorField == 'subject'} class="formError"{/if}>
                        <dt><label for="subject">{lang}wcf.global.subject{/lang}</label></dt>
                        <dd>
-                               <input type="text" id="subject" name="subject" value="{$subject}" required maxlength="255" class="long">
+                               <input type="text" id="subject" name="subject" value="{$subject}" required autofocus maxlength="255" class="long">
                                {if $errorField == 'subject'}
                                        <small class="innerError">
                                                {if $errorType == 'empty'}
        
        <div class="formSubmit">
                <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
-               <button name="draft" accesskey="d" value="1">{lang}wcf.conversation.button.saveAsDraft{/lang}</button>
+               <button type="submit" class="button" name="draft" accesskey="d" value="1">{lang}wcf.conversation.button.saveAsDraft{/lang}</button>
                {include file='messageFormPreviewButton' previewMessageObjectType='com.woltlab.wcf.conversation.message' previewMessageObjectID=0}
                {csrfToken}
        </div>
index cca3719d6b4714d91067145c1afc840cf49db3b8..fecdd1ad8c25fe2e7ec576a8e11fe39c4b0e476c 100644 (file)
@@ -22,5 +22,5 @@
 {/if}
 
 <div class="formSubmit">
-       <button id="addParticipants" class="buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
+       <button type="button" id="addParticipants" class="button buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
 </div>
\ No newline at end of file
index 92c637d292ecc174818fbfa5d9be162904dce4e6..e0d1d665e1fae4edf2f7bbbe91e76a828171dc72 100644 (file)
@@ -2,13 +2,13 @@
        {foreach from=$labelList item=label}
                <li>
                        <label>
-                               <input type="checkbox"{if $label->labelID|in_array:$assignedLabels} checked{/if} data-label-id="{@$label->labelID}">
-                               <span class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}">{$label->label}</span>
+                               <input type="checkbox"{if $label->labelID|in_array:$assignedLabels} checked{/if} data-label-id="{$label->labelID}">
+                               <span class="badge label{if $label->cssClassName} {$label->cssClassName}{/if}">{$label->label}</span>
                        </label>
                </li>
        {/foreach}
 </ul>
 
 <div class="formSubmit">
-       <button class="buttonPrimary" id="assignLabels">{lang}wcf.global.button.save{/lang}</button>
+       <button type="button" class="button buttonPrimary" id="assignLabels">{lang}wcf.global.button.save{/lang}</button>
 </div>
index b915eef36eb7ca15cb3efbfa25b585d71a54a81c..999658fc27ffc119eb1a6999a2243b6d109ce437 100644 (file)
@@ -7,7 +7,7 @@
                <ul class="conversationLabelList">
                        {content}
                                {foreach from=$labelList item=label}
-                                       <li><a class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}" data-label-id="{@$label->labelID}" data-css-class-name="{if $label->cssClassName}{@$label->cssClassName}{else}none{/if}">{$label->label}</a></li>
+                                       <li><a class="badge label{if $label->cssClassName} {$label->cssClassName}{/if}" data-label-id="{$label->labelID}" data-css-class-name="{if $label->cssClassName}{$label->cssClassName}{else}none{/if}">{$label->label}</a></li>
                                {/foreach}
                        {/content}
                </ul>
@@ -27,8 +27,8 @@
                        <ul role="group" aria-label="{lang}wcf.conversation.label.cssClassName{/lang}" id="labelManagementList">
                                {foreach from=$cssClassNames item=cssClassName}
                                        <li><label>
-                                               <input type="radio" name="cssClassName" value="{@$cssClassName}"{if $cssClassName == 'none'} checked{/if}>
-                                               <span class="badge label{if $cssClassName != 'none'} {@$cssClassName}{/if}">{lang}wcf.conversation.label.placeholder{/lang}</span>
+                                               <input type="radio" name="cssClassName" value="{$cssClassName}"{if $cssClassName == 'none'} checked{/if}>
+                                               <span class="badge label{if $cssClassName != 'none'} {$cssClassName}{/if}">{lang}wcf.conversation.label.placeholder{/lang}</span>
                                        </label></li>
                                {/foreach}
                        </ul>
@@ -36,8 +36,8 @@
        </dl>
        
        <div class="formSubmit">
-               <button id="addLabel" class="buttonPrimary">{lang}wcf.global.button.save{/lang}</button>
-               <button id="editLabel" style="display: none;" class="buttonPrimary">{lang}wcf.global.button.save{/lang}</button>
-               <button id="deleteLabel" style="display: none;">{lang}wcf.conversation.label.management.deleteLabel{/lang}</button>
+               <button type="button" id="addLabel" class="button buttonPrimary">{lang}wcf.global.button.save{/lang}</button>
+               <button type="button" id="editLabel" class="button" style="display: none;" class="buttonPrimary">{lang}wcf.global.button.save{/lang}</button>
+               <button type="button" id="deleteLabel" class="button" style="display: none;">{lang}wcf.conversation.label.management.deleteLabel{/lang}</button>
        </div>
-</section>
\ No newline at end of file
+</section>
index 7350529203dc69c23003946bc58ce3bfc75fd891..177fb93f6c3bb06f5ef4c9c75169c4bd7f7643b5 100644 (file)
@@ -16,5 +16,5 @@
 </dl>
 
 <div class="formSubmit">
-       <button id="hideConversation" class="buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
+       <button type="button" id="hideConversation" class="button buttonPrimary">{lang}wcf.global.button.submit{/lang}</button>
 </div>
index 18b3241046e27c79c1ea22cf7e680aba042c5267..8a3d928c7c446eb726b41ccd5f350a35da53d5f7 100644 (file)
                        <nav class="contentHeaderNavigation">
                                <ul>
                                        {content}
-                                               {if $__wcf->session->getPermission('user.conversation.canStartConversation')}<li><a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button buttonPrimary"><span class="icon icon16 fa-plus"></span> <span>{lang}wcf.conversation.button.add{/lang}</span></a></li>{/if}
+                                               {if $__wcf->session->getPermission('user.conversation.canStartConversation')}
+                                                       <li>
+                                                               <a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button buttonPrimary">
+                                                                       {icon name='plus'}
+                                                                       <span>{lang}wcf.conversation.button.add{/lang}</span>
+                                                               </a>
+                                                       </li>
+                                               {/if}
                                                {event name='contentHeaderNavigation'}
                                        {/content}
                                </ul>
@@ -74,7 +81,7 @@
                                        {if $labelID}
                                                {foreach from=$labelList item=label}
                                                        {if $label->labelID == $labelID}
-                                                               <span class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}">{$label->label}</span>
+                                                               <span class="badge label{if $label->cssClassName} {$label->cssClassName}{/if}">{$label->label}</span>
                                                        {/if}
                                                {/foreach}
                                        {else}
@@ -85,7 +92,7 @@
                                <div class="dropdownMenu">
                                        <ul class="scrollableDropdownMenu">
                                                {foreach from=$labelList item=label}
-                                                       <li><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}{if !$participants|empty}participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}&{/if}sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}&labelID={@$label->labelID}{/link}"><span class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}" data-css-class-name="{if $label->cssClassName}{@$label->cssClassName}{/if}" data-label-id="{@$label->labelID}">{$label->label}</span></a></li>
+                                                       <li><a href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}{if !$participants|empty}participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}&{/if}sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}&labelID={@$label->labelID}{/link}"><span class="badge label{if $label->cssClassName} {@$label->cssClassName}{/if}" data-css-class-name="{if $label->cssClassName}{@$label->cssClassName}{/if}" data-label-id="{$label->labelID}">{$label->label}</span></a></li>
                                                {/foreach}
                                        </ul>
                                        <ul>
                </div>
                
                <div class="boxContent">
-                       <button id="manageLabel">{lang}wcf.conversation.label.management{/lang}</button>
+                       <button type="button" id="manageLabel" class="button">{lang}wcf.conversation.label.management{/lang}</button>
                </div>
        </section>
        
                <div class="boxContent">
                        {assign var='conversationCount' value=$__wcf->getConversationHandler()->getConversationCount()}
                        {assign var='maxConversationCount' value=$__wcf->session->getPermission('user.conversation.maxConversations')}
-                       <p class="conversationUsageBar{if $conversationCount/$maxConversationCount >= 1.0} red{elseif $conversationCount/$maxConversationCount > 0.9} yellow{/if}">
-                               <span style="width: {if $conversationCount/$maxConversationCount < 1.0}{@$conversationCount/$maxConversationCount*100|round:0}{else}100{/if}%">{#$conversationCount/$maxConversationCount*100}%</span>
-                       </p>
+                       {assign var='conversationCountValue' value=$conversationCount/$maxConversationCount*100}
+                       <meter class="conversationQuotaMeter" min="0" max="100" low="90" high="99" value="{$conversationCountValue|ceil}" aria-label="{lang}wcf.conversation.quota{/lang}">
+                               {#$conversationCountValue}&nbsp;%
+                       </meter>
                        <p><small>{lang}wcf.conversation.quota.description{/lang}</small></p>
                </div>
        </section>
 {/capture}
 
 {capture assign='contentInteractionButtons'}
-       <a href="#" class="markAllAsReadButton contentInteractionButton button small jsOnly"><span class="icon icon16 fa-check"></span> <span>{lang}wcf.global.button.markAllAsRead{/lang}</span></a>
+       <button type="button" class="markAllAsReadButton contentInteractionButton button small jsOnly">
+               {icon name='check'}
+               <span>{lang}wcf.global.button.markAllAsRead{/lang}</span>
+       </button>
 {/capture}
 
 {capture assign='contentInteractionDropdownItems'}
                                                <ul class="inlineList">
                                                        <li>
                                                                <a rel="nofollow" href="{link controller='ConversationList'}{if $filter}filter={@$filter}&{/if}{if !$participants|empty}participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}&{/if}pageNo={@$pageNo}&sortField={$sortField}&sortOrder={if $sortOrder == 'ASC'}DESC{else}ASC{/if}{if $labelID}&labelID={@$labelID}{/if}{/link}">
-                                                                       <span class="icon icon16 fa-sort-amount-{$sortOrder|strtolower} jsTooltip" title="{lang}wcf.global.sorting{/lang} ({lang}wcf.global.sortOrder.{if $sortOrder === 'ASC'}ascending{else}descending{/if}{/lang})"></span>
+                                                                       {if $sortOrder === 'ASC'}
+                                                                               <span class="jsTooltip" title="{lang}wcf.global.sorting{/lang} ({lang}wcf.global.sortOrder.ascending{/lang})">
+                                                                                       {icon name='arrow-down-wide-short'}
+                                                                               </span>
+                                                                       {else}
+                                                                               <span class="jsTooltip" title="{lang}wcf.global.sorting{/lang} ({lang}wcf.global.sortOrder.descending{/lang})">
+                                                                                       {icon name='arrow-down-short-wide'}
+                                                                               </span>
+                                                                       {/if}
                                                                </a>
                                                        </li>
                                                        <li>
                        
                        {foreach from=$objects item=conversation}
                                <li class="tabularListRow">
-                                       <ol class="tabularListColumns messageGroup conversation jsClipboardObject{if $conversation->isNew()} new{/if}" data-conversation-id="{@$conversation->conversationID}" data-label-ids="[ {implode from=$conversation->getAssignedLabels() item=label}{@$label->labelID}{/implode} ]" data-is-closed="{@$conversation->isClosed}" data-can-close-conversation="{if $conversation->userID == $__wcf->getUser()->userID}1{else}0{/if}" data-can-add-participants="{if $conversation->canAddParticipants()}1{else}0{/if}">
+                                       <ol class="tabularListColumns messageGroup conversation jsClipboardObject{if $conversation->isNew()} new{/if}" data-conversation-id="{$conversation->conversationID}" data-label-ids="[ {implode from=$conversation->getAssignedLabels() item=label}{$label->labelID}{/implode} ]" data-is-closed="{$conversation->isClosed}" data-can-close-conversation="{if $conversation->userID == $__wcf->getUser()->userID}1{else}0{/if}" data-can-add-participants="{if $conversation->canAddParticipants()}1{else}0{/if}">
                                                <li class="columnMark jsOnly">
-                                                       <label><input type="checkbox" class="jsClipboardItem" data-object-id="{@$conversation->conversationID}"></label>
+                                                       <label><input type="checkbox" class="jsClipboardItem" data-object-id="{$conversation->conversationID}"></label>
                                                </li>
                                                <li class="columnIcon columnAvatar">
                                                        {if $conversation->getUserProfile()->getAvatar()}
                                                        {/hascontent}
                                                                
                                                        <h3>
-                                                               <a href="{if $conversation->isNew()}{link controller='Conversation' object=$conversation}action=firstNew{/link}{else}{$conversation->getLink()}{/if}" class="conversationLink messageGroupLink" data-object-id="{@$conversation->conversationID}">{$conversation->subject}</a>
+                                                               <a href="{if $conversation->isNew()}{link controller='Conversation' object=$conversation}action=firstNew{/link}{else}{$conversation->getLink()}{/if}" class="conversationLink messageGroupLink" data-object-id="{$conversation->conversationID}">{$conversation->subject}</a>
                                                                {if $conversation->replies}
                                                                        <span class="badge messageGroupCounterMobile">{@$conversation->replies|shortUnit}</span>
                                                                {/if}
                                                        
                                                        <aside class="statusDisplay" role="presentation">
                                                                <ul class="statusIcons">
-                                                                       {if $conversation->isClosed}<li><span class="icon icon16 fa-lock jsIconLock jsTooltip" title="{lang}wcf.global.state.closed{/lang}"></span></li>{/if}
-                                                                       {if $conversation->attachments}<li><span class="icon icon16 fa-paperclip jsIconAttachment jsTooltip" title="{lang}wcf.conversation.attachments{/lang}"></span></li>{/if}
+                                                                       {if $conversation->isClosed}
+                                                                               <li>
+                                                                                       <span class="jsIconLock jsTooltip" title="{lang}wcf.global.state.closed{/lang}">
+                                                                                               {icon name='lock'}
+                                                                                       </span>
+                                                                               </li>
+                                                                       {/if}
+                                                                       {if $conversation->attachments}
+                                                                               <li>
+                                                                                       <span class="jsIconAttachment jsTooltip" title="{lang}wcf.conversation.attachments{/lang}">
+                                                                                               {icon name='paperclip'}
+                                                                                       </span>
+                                                                               </li>
+                                                                       {/if}
                                                                </ul>
                                                        </aside>
                                                        
                                                        <ul class="inlineList dotSeparated small messageGroupInfo">
                                                                <li class="messageGroupAuthor">{user object=$conversation->getUserProfile()}</li>
-                                                               <li class="messageGroupTime">{@$conversation->time|time}</li>
+                                                               <li class="messageGroupTime">{time time=$conversation->time}</li>
                                                                <li class="messageGroupEditLink jsOnly"><a href="#" class="jsConversationInlineEditor">{lang}wcf.global.button.edit{/lang}</a></li>
                                                                {event name='messageGroupInfo'}
                                                        </ul>
                                                        
                                                        <ul class="messageGroupInfoMobile">
                                                                <li class="messageGroupAuthorMobile">{$conversation->username}</li>
-                                                               <li class="messageGroupLastPostTimeMobile">{@$conversation->lastPostTime|time}</li>
+                                                               <li class="messageGroupLastPostTimeMobile">{time time=$conversation->lastPostTime}</li>
                                                        </ul>
                                                        
                                                        {if $conversation->getParticipantSummary()|count}
                                                                <small class="conversationParticipantSummary">
                                                                        {assign var='participantSummaryCount' value=$conversation->getParticipantSummary()|count}
-                                                                       {lang}wcf.conversation.participants{/lang}: {implode from=$conversation->getParticipantSummary() item=participant}<a href="{$participant->getLink()}" class="userLink{if $participant->hideConversation == 2} conversationLeft{/if}" data-object-id="{@$participant->userID}">{$participant->username}</a>{/implode}
+                                                                       {lang}wcf.conversation.participants{/lang}: {implode from=$conversation->getParticipantSummary() item=participant}<a href="{$participant->getLink()}" class="userLink{if $participant->hideConversation == 2} conversationLeft{/if}" data-object-id="{$participant->userID}">{$participant->username}</a>{/implode}
                                                                        {if $participantSummaryCount < $conversation->participants}{lang}wcf.conversation.participants.other{/lang}{/if}
                                                                </small>
                                                        {/if}
                                                                <dd>{@$conversation->participants|shortUnit}</dd>
                                                        </dl>
                                                        
-                                                       <div class="messageGroupListStatsSimple">{if $conversation->replies}<span class="icon icon16 fa-comment-o" aria-label="{lang}wcf.conversation.replies{/lang}"></span> {@$conversation->replies|shortUnit}{/if}</div>
+                                                       <div class="messageGroupListStatsSimple">
+                                                               {if $conversation->replies}
+                                                                       <span aria-label="{lang}wcf.conversation.replies{/lang}">
+                                                                               {icon name='comment'}
+                                                                       </span>
+                                                                       {@$conversation->replies|shortUnit}
+                                                               {/if}
+                                                       </div>
                                                </li>
                                                <li class="columnLastPost">
                                                        {if $conversation->replies != 0 && $conversation->lastPostTime}
                                                                                <p>
                                                                                        {user object=$conversation->getLastPosterProfile()}
                                                                                </p>
-                                                                               <small>{@$conversation->lastPostTime|time}</small>
+                                                                               <small>{time time=$conversation->lastPostTime}</small>
                                                                        </div>
                                                                </div>
                                                        {/if}
                <nav class="contentFooterNavigation">
                        <ul>
                                {content}
-                                       {if $__wcf->session->getPermission('user.conversation.canStartConversation')}<li><a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button buttonPrimary"><span class="icon icon16 fa-plus"></span> <span>{lang}wcf.conversation.button.add{/lang}</span></a></li>{/if}
+                                       {if $__wcf->session->getPermission('user.conversation.canStartConversation')}
+                                               <li>
+                                                       <a href="{link controller='ConversationAdd'}{/link}" title="{lang}wcf.conversation.add{/lang}" class="button buttonPrimary">
+                                                               {icon name='plus'}
+                                                               <span>{lang}wcf.conversation.button.add{/lang}</span>
+                                                       </a>
+                                               </li>
+                                       {/if}
                                        {event name='contentFooterNavigation'}
                                {/content}
                        </ul>
        {/hascontent}
 </footer>
 
-<script data-relocate="true" src="{@$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
+<script data-relocate="true" src="{$__wcf->getPath()}js/WCF.Conversation{if !ENABLE_DEBUG_MODE}.min{/if}.js?v={@LAST_UPDATE_TIME}"></script>
 <script data-relocate="true">
        require([
                'WoltLabSuite/Core/Language',
                
                new WCF.Conversation.Clipboard($editorHandler);
                new WCF.Conversation.Label.Manager('{link controller='ConversationList' encode=false}{if $filter}filter={@$filter}&{/if}{if !$participants|empty}participants={implode from=$participants item=participant}{$participant|rawurlencode}{/implode}&{/if}sortField={$sortField}&sortOrder={$sortOrder}&pageNo={@$pageNo}{/link}');
-               new WCF.Conversation.MarkAsRead();
-               new WCF.Conversation.MarkAllAsRead();
                
                // mobile safari hover workaround
                if ($(window).width() <= 800) {
        });
 </script>
 
+<script data-relocate="true">
+       require(['WoltLabSuite/Core/Conversation/Ui/MarkAsRead'], (MarkAsRead) => {
+               MarkAsRead.setup();
+       });
+       require(['WoltLabSuite/Core/Conversation/Ui/MarkAllAsRead'], (MarkAllAsRead) => {
+               MarkAllAsRead.setup();
+       });
+</script>
+
 {include file='footer'}
diff --git a/templates/conversationListUserPanel.tpl b/templates/conversationListUserPanel.tpl
deleted file mode 100644 (file)
index c5badc7..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-{foreach from=$conversations item=conversation}
-       <li class="conversationItem{if $conversation->lastVisitTime < $conversation->lastPostTime} conversationItemUnread interactiveDropdownItemOutstanding{/if}" data-link="{link controller='Conversation' object=$conversation}action=firstNew{/link}" data-object-id="{@$conversation->conversationID}" data-is-read="{if $conversation->lastVisitTime < $conversation->lastPostTime}false{else}true{/if}">
-               <div class="box48">
-                       <div>
-                               {if $conversation->userID == $__wcf->user->userID}
-                                       {if $conversation->participants > 1}
-                                               <span class="icon icon48 fa-users"></span>
-                                       {else}
-                                               {@$conversation->getOtherParticipantProfile()->getAvatar()->getImageTag(48)}
-                                       {/if}
-                               {else}
-                                       {@$conversation->getUserProfile()->getAvatar()->getImageTag(48)}
-                               {/if}
-                       </div>
-                       <div>
-                               <h3><a href="{link controller='Conversation' object=$conversation}action=firstNew{/link}">{$conversation->subject}</a></h3>
-                               <small class="conversationInfo">
-                                       <span class="conversationParticipant">
-                                               {if $conversation->userID == $__wcf->user->userID}
-                                                       {if $conversation->participants > 1}
-                                                               {assign var='participantSummaryCount' value=$conversation->getParticipantSummary()|count}
-                                                               {implode from=$conversation->getParticipantSummary() item=participant}<a href="{$participant->getLink()}" class="userLink{if $participant->hideConversation == 2} conversationLeft{/if}" data-object-id="{@$participant->userID}">{$participant->username}</a>{/implode}
-                                                               {if $participantSummaryCount < $conversation->participants}{lang}wcf.conversation.participants.other{/lang}{/if}
-                                                       {else}
-                                                               {user object=$conversation->getOtherParticipantProfile()}
-                                                       {/if}
-                                               {else}
-                                                       {user object=$conversation->getUserProfile()}
-                                               {/if}
-                                       </span>
-                                       
-                                       <span class="conversationLastPostTime">{@$conversation->lastPostTime|time}</span>
-                               </small>
-                       </div>
-               </div>
-       </li>
-{/foreach}
index 6eee8d52157740dc0c89479932819c2b47081982..3d275e8bdac92c60619f614543957babe2325410 100644 (file)
@@ -1,18 +1,18 @@
 {capture assign='wysiwygSelector'}messageEditor{@$message->messageID}{/capture}
 <div class="messageInlineEditor">
        <textarea id="{$wysiwygSelector}" class="wysiwygTextarea"
-                 data-autosave="com.woltlab.wcf.conversation.messageEdit-{@$message->messageID}"
+                 data-autosave="com.woltlab.wcf.conversation.messageEdit-{$message->messageID}"
                  data-support-mention="true"
        >{$message->message}</textarea>
        {capture assign=wysiwygContainerID}messageEditor{@$message->messageID}{/capture}
        {include file='messageFormTabsInline' inConversationInlineEdit=true wysiwygContainerID=$wysiwygContainerID}
        
        <div class="formSubmit">
-               <button class="buttonPrimary" data-type="save">{lang}wcf.global.button.save{/lang}</button>
+               <button type="button" class="button buttonPrimary" data-type="save">{lang}wcf.global.button.save{/lang}</button>
                
                {include file='messageFormPreviewButton' previewMessageFieldID=$wysiwygSelector previewButtonID=$wysiwygSelector|concat:'_PreviewButton' previewMessageObjectType='com.woltlab.wcf.conversation.message' previewMessageObjectID=$message->messageID}
                
-               <button data-type="cancel">{lang}wcf.global.button.cancel{/lang}</button>
+               <button type="button" class="button" data-type="cancel">{lang}wcf.global.button.cancel{/lang}</button>
        </div>
        
        {include file='wysiwyg' wysiwygEnableUpload=true}
index 166d58289bae8d39fec282f35b6bd4a67999ea43..327df013ea191268f34d7b97ede3a1a05093a6c7 100644 (file)
@@ -6,15 +6,15 @@
        {assign var='objectID' value=$message->messageID}
        {assign var='userProfile' value=$message->getUserProfile()}
        
-       <li id="message{@$message->messageID}" class="anchorFixedHeader{if $conversation->userID == $message->userID} messageGroupStarter{/if}">
-               <article class="message messageSidebarOrientation{@$__wcf->getStyleHandler()->getStyle()->getVariable('messageSidebarOrientation')|ucfirst} jsMessage{if $userProfile->userOnlineGroupID} userOnlineGroupMarking{@$userProfile->userOnlineGroupID}{/if}" data-user-id="{@$message->userID}" data-can-edit="{if $message->canEdit()}1{else}0{/if}" data-object-id="{@$message->messageID}">
+       <li id="message{$message->messageID}" class="anchorFixedHeader{if $conversation->userID == $message->userID} messageGroupStarter{/if}">
+               <article class="message messageSidebarOrientation{$__wcf->getStyleHandler()->getStyle()->getVariable('messageSidebarOrientation')|ucfirst} jsMessage{if $userProfile->userOnlineGroupID} userOnlineGroupMarking{$userProfile->userOnlineGroupID}{/if}" data-user-id="{$message->userID}" data-can-edit="{if $message->canEdit()}1{else}0{/if}" data-object-id="{$message->messageID}">
                        {include file='messageSidebar'}
                        
                        <div class="messageContent">
                                <header class="messageHeader">
                                        <div class="messageHeaderBox">
                                                <ul class="messageHeaderMetaData">
-                                                       <li><a href="{link controller='Conversation' object=$conversation}messageID={@$message->messageID}{/link}#message{@$message->messageID}" class="permalink messagePublicationTime">{@$message->time|time}</a></li>
+                                                       <li><a href="{link controller='Conversation' object=$conversation}messageID={@$message->messageID}{/link}#message{$message->messageID}" class="permalink messagePublicationTime">{time time=$message->time}</a></li>
                                                        
                                                        {event name='messageHeaderMetaData'}
                                                </ul>
@@ -29,7 +29,7 @@
                                        </div>
                                        
                                        <ul class="messageQuickOptions">
-                                               <li><a href="{link controller='Conversation' object=$conversation}messageID={@$message->messageID}{/link}#message{@$message->messageID}" class="jsTooltip" title="{lang}wcf.conversation.message.permalink{/lang}">#{#$startIndex}</a></li>
+                                               <li><a href="{link controller='Conversation' object=$conversation}messageID={@$message->messageID}{/link}#message{$message->messageID}" class="jsTooltip" title="{lang}wcf.conversation.message.permalink{/lang}">#{#$startIndex}</a></li>
                                                
                                                {event name='messageQuickOptions'}
                                        </ul>
                                        
                                        <div class="messageFooterGroup">
                                                <ul class="messageFooterButtons buttonList smallButtons jsMobileNavigation">
-                                                       {if $message->canEdit()}<li class="jsOnly"><a href="{if $conversation->isDraft && $message->messageID == $conversation->firstMessageID}{link controller='ConversationDraftEdit' id=$conversation->conversationID}{/link}{else}#{/if}" title="{lang}wcf.conversation.message.edit{/lang}" class="button{if !$conversation->isDraft || $message->messageID != $conversation->firstMessageID} jsMessageEditButton{/if}"><span class="icon icon16 fa-pencil"></span> <span>{lang}wcf.global.button.edit{/lang}</span></a></li>{/if}
-                                                       <li class="jsQuoteMessage" data-object-id="{@$message->messageID}" data-is-quoted="{if $__quoteFullQuote|isset && $message->messageID|in_array:$__quoteFullQuote}1{else}0{/if}"><a href="#" title="{lang}wcf.message.quote.quoteMessage{/lang}" class="button jsTooltip{if $__quoteFullQuote|isset && $message->messageID|in_array:$__quoteFullQuote} active{/if}"><span class="icon icon16 fa-quote-left"></span> <span class="invisible">{lang}wcf.message.quote.quoteMessage{/lang}</span></a></li>
-                                                       {if $message->userID != $__wcf->getUser()->userID && $__wcf->session->getPermission('user.profile.canReportContent')}<li class="jsReportConversationMessage jsOnly" data-object-id="{@$message->messageID}"><a href="#" title="{lang}wcf.moderation.report.reportContent{/lang}" class="button jsTooltip"><span class="icon icon16 fa-exclamation-triangle"></span> <span class="invisible">{lang}wcf.moderation.report.reportContent{/lang}</span></a></li>{/if}
+                                                       {if $message->canEdit()}
+                                                               <li class="jsOnly">
+                                                                       <a
+                                                                               href="{if $conversation->isDraft && $message->messageID == $conversation->firstMessageID}{link controller='ConversationDraftEdit' id=$conversation->conversationID}{/link}{else}#{/if}"
+                                                                               title="{lang}wcf.conversation.message.edit{/lang}"
+                                                                               class="button{if !$conversation->isDraft || $message->messageID != $conversation->firstMessageID} jsMessageEditButton{/if}"
+                                                                       >
+                                                                               {icon name='pencil'}
+                                                                               <span>{lang}wcf.global.button.edit{/lang}</span>
+                                                                       </a>
+                                                               </li>
+                                                       {/if}
+                                                       <li
+                                                               class="jsQuoteMessage"
+                                                               data-object-id="{$message->messageID}"
+                                                               data-is-quoted="{if $__quoteFullQuote|isset && $message->messageID|in_array:$__quoteFullQuote}1{else}0{/if}"
+                                                       >
+                                                               <a
+                                                                       href="#"
+                                                                       title="{lang}wcf.message.quote.quoteMessage{/lang}"
+                                                                       class="button jsTooltip{if $__quoteFullQuote|isset && $message->messageID|in_array:$__quoteFullQuote} active{/if}"
+                                                               >
+                                                                       {icon name='quote-left' type='solid'}
+                                                                       <span class="invisible">{lang}wcf.message.quote.quoteMessage{/lang}</span>
+                                                               </a>
+                                                       </li>
+                                                       {if $message->userID != $__wcf->getUser()->userID && $__wcf->session->getPermission('user.profile.canReportContent')}
+                                                               <li>
+                                                                       <button
+                                                                               type="button"
+                                                                               title="{lang}wcf.moderation.report.reportContent{/lang}"
+                                                                               class="button jsTooltip"
+                                                                               data-report-content="com.woltlab.wcf.conversation.message"
+                                                                               data-object-id="{$message->messageID}"
+                                                                       >
+                                                                               {icon name='triangle-exclamation'}
+                                                                               <span class="invisible">{lang}wcf.moderation.report.reportContent{/lang}</span>
+                                                                       </button>
+                                                               </li>
+                                                       {/if}
                                                        {event name='messageFooterButtons'}
                                                </ul>
                                        </div>
index a74d1dec0886c0ae6aff10c7a35c2e77497b09f1..3b2a6994801eac461391e1a2c0c798a1aa7cc2f9 100644 (file)
@@ -11,7 +11,7 @@
                                                        <div class="messageHeaderBox">
                                                                <h2 class="messageTitle">
                                                                        {user object=$modificationLogEntry->getUserProfile() class='username'}
-                                                                       <small class="separatorLeft">{@$modificationLogEntry->time|time}</small>
+                                                                       <small class="separatorLeft">{time time=$modificationLogEntry->time}</small>
                                                                </h2>
                                                                <div>{@$modificationLogEntry}</div>
                                                        </div>
index 8385544226a372d2782282d7267408df2ab1c3b4..f4d0cefe32ff21a2e2213eaea47bfeeeb23f4510 100644 (file)
@@ -5,7 +5,7 @@
        
        <div>
                <div class="containerHeadline">
-                       <h3>{user object=$message->getUserProfile()} <small class="separatorLeft">{@$message->time|time}</small></h3>
+                       <h3>{user object=$message->getUserProfile()} <small class="separatorLeft">{time time=$message->time}</small></h3>
                </div>
                
                <div>{@$message->getExcerpt()}</div>
index cc215757eee2e74b87f5e8bdad1fa23557621457..b66377f0ad304b0bf3a4f204f27e4b0d4a54d33b 100644 (file)
@@ -1,5 +1,5 @@
-<li id="messageQuickReply" class="jsOnly{if $conversation->userID == $__wcf->getUser()->userID} messageGroupStarter{/if}{if $pageNo < $pages} messageQuickReplyCollapsed{/if}" data-object-id="{@$conversation->conversationID}" data-last-post-time="{@$conversation->lastPostTime}" data-page-no="{@$pageNo}">
-       <article class="message messageSidebarOrientation{@$__wcf->getStyleHandler()->getStyle()->getVariable('messageSidebarOrientation')|ucfirst}{if $__wcf->getUserProfileHandler()->userOnlineGroupID} userOnlineGroupMarking{@$__wcf->getUserProfileHandler()->userOnlineGroupID}{/if}">
+<li id="messageQuickReply" class="jsOnly{if $conversation->userID == $__wcf->getUser()->userID} messageGroupStarter{/if}{if $pageNo < $pages} messageQuickReplyCollapsed{/if}" data-object-id="{$conversation->conversationID}" data-last-post-time="{$conversation->lastPostTime}" data-page-no="{$pageNo}">
+       <article class="message messageSidebarOrientation{$__wcf->getStyleHandler()->getStyle()->getVariable('messageSidebarOrientation')|ucfirst}{if $__wcf->getUserProfileHandler()->userOnlineGroupID} userOnlineGroupMarking{$__wcf->getUserProfileHandler()->userOnlineGroupID}{/if}">
                {include file='messageSidebar' userProfile=$__wcf->getUserProfileHandler()->getUserProfile() isReply=true enableMicrodata=false}
                
                <div class="messageContent messageQuickReplyContent"{if $pageNo < $pages} data-placeholder="{lang}wcf.conversation.reply{/lang}"{/if}>
@@ -11,7 +11,7 @@
                                {event name='beforeWysiwyg'}
                                
                                <textarea id="text" name="text" class="wysiwygTextarea"
-                                         data-autosave="com.woltlab.wcf.conversation.messageAdd-{@$conversation->conversationID}"
+                                         data-autosave="com.woltlab.wcf.conversation.messageAdd-{$conversation->conversationID}"
                                          data-support-mention="true"
                                ></textarea>
                                {include file='messageFormTabsInline' inConversationQuickReply=true}
@@ -19,7 +19,7 @@
                        
                        <footer class="messageFooter">
                                <div class="formSubmit">
-                                       <button class="buttonPrimary" data-type="save" accesskey="s">{lang}wcf.global.button.reply{/lang}</button>
+                                       <button class="button buttonPrimary" data-type="save" accesskey="s">{lang}wcf.global.button.reply{/lang}</button>
                                        {include file='messageFormPreviewButton' previewMessageObjectType='com.woltlab.wcf.conversation.message' previewMessageObjectID=0}
                                </div>
                        </footer>
@@ -27,4 +27,4 @@
        </article>
        
        {include file='wysiwyg'}
-</li>
\ No newline at end of file
+</li>
index f6835cc0e9ddfa09e1ed7e817c5ad99fba3f43ae..4262871330440c0db16c045a38f848ebb345f8f7 100644 (file)
@@ -23,7 +23,7 @@
                                                        {$message->username}
                                                {/if}
                                                &#xb7;
-                                               <a href="{$message->getLink()}"><small>{$message->time|plainTime}</small></a>
+                                               <a href="{$message->getLink()}"><small>{time time=$message->time type='plainTime'}</small></a>
                                        </h3>
                                </div>
                                <div>
index 9ef897b0795fb80eda8094290d5c7235c53325ea..c63ce03fe57dd252d51caccd9acd7b96ab719648 100644 (file)
@@ -26,7 +26,7 @@
                                                        {$message->username}
                                                {/if}
                                                &#xb7;
-                                               <a href="{$message->getLink()}"><small>{$message->time|plainTime}</small></a>
+                                               <a href="{$message->getLink()}"><small>{time time=$message->time type='plainTime'}</small></a>
                                        </h3>
                                </div>
                                <div>
index eb91b2d40666f526fd325f000825592b7abe9a1d..b6509feb66d1c6fea757a1b11a416e5c0f9521a7 100644 (file)
@@ -5,11 +5,11 @@
                                {user object=$message->getUserProfile() type='avatar32' ariaHidden='true' tabindex='-1'}
                                
                                <div class="messageHeaderBox">
-                                       <h2 class="messageTitle">{if $message->getConversation()->canRead()}<a href="{@$message->getLink()}">{$message->getTitle()}</a>{else}{$message->getTitle()}{/if}</h2>
+                                       <h2 class="messageTitle">{if $message->getConversation()->canRead()}<a href="{$message->getLink()}">{$message->getTitle()}</a>{else}{$message->getTitle()}{/if}</h2>
                                        
                                        <ul class="messageHeaderMetaData">
                                                <li>{user object=$message->getUserProfile() class='username'}</li>
-                                               <li><span class="messagePublicationTime">{@$message->getTime()|time}</span></li>
+                                               <li><span class="messagePublicationTime">{time time=$message->getTime()}</span></li>
                                                
                                                {event name='messageHeaderMetaData'}
                                        </ul>
@@ -29,4 +29,4 @@
                        {event name='afterMessageText'}
                </div>
        </div>
-</article>
\ No newline at end of file
+</article>
index 34eef4f660afb30abebaff7c6d47879b8f8c175d..40ff1207cbc062ee637658e7354ffdcafa7ee000 100644 (file)
@@ -1,4 +1,4 @@
 <dl>
        <dt></dt>
-       <dd><label><input type="checkbox" name="conversationID" value="{@$searchedConversation->conversationID}" checked> {lang}wcf.conversation.searchedConversation{/lang}</label></dd>
+       <dd><label><input type="checkbox" name="conversationID" value="{$searchedConversation->conversationID}" checked> {lang}wcf.conversation.searchedConversation{/lang}</label></dd>
 </dl>
diff --git a/ts/WoltLabSuite/Core/Conversation/Ui/MarkAllAsRead.ts b/ts/WoltLabSuite/Core/Conversation/Ui/MarkAllAsRead.ts
new file mode 100644 (file)
index 0000000..52d3fac
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * Marks all conversations as read.
+ *
+ * @author  Marcel Werk
+ * @copyright  2001-2022 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.0
+ */
+
+import { dboAction } from "WoltLabSuite/Core/Ajax";
+import * as UiNotification from "WoltLabSuite/Core/Ui/Notification";
+
+async function markAllAsRead(): Promise<void> {
+  await dboAction("markAllAsRead", "wcf\\data\\conversation\\ConversationAction").dispatch();
+
+  document.querySelectorAll(".conversationList .new").forEach((el: HTMLElement) => {
+    el.classList.remove("new");
+  });
+  document.querySelector("#unreadConversations .badgeUpdate")?.remove();
+
+  UiNotification.show();
+}
+
+export function setup(): void {
+  document.querySelectorAll(".markAllAsReadButton").forEach((el: HTMLElement) => {
+    el.addEventListener("click", (event) => {
+      event.preventDefault();
+
+      void markAllAsRead();
+    });
+  });
+}
diff --git a/ts/WoltLabSuite/Core/Conversation/Ui/MarkAsRead.ts b/ts/WoltLabSuite/Core/Conversation/Ui/MarkAsRead.ts
new file mode 100644 (file)
index 0000000..bf2e02c
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * Handles the mark as read button for single conversations.
+ *
+ * @author  Marcel Werk
+ * @copyright  2001-2022 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.0
+ */
+
+import { dboAction } from "WoltLabSuite/Core/Ajax";
+
+const unreadConversations = new WeakSet();
+
+async function markAsRead(conversation: HTMLElement): Promise<void> {
+  const conversationId = parseInt(conversation.dataset.conversationId!, 10);
+
+  await dboAction("markAsRead", "wcf\\data\\conversation\\ConversationAction").objectIds([conversationId]).dispatch();
+
+  conversation.classList.remove("new");
+  conversation.querySelector(".columnAvatar p")?.removeAttribute("title");
+}
+
+export function setup(): void {
+  document.querySelectorAll(".conversationList .new .columnAvatar").forEach((el: HTMLElement) => {
+    if (!unreadConversations.has(el)) {
+      unreadConversations.add(el);
+
+      el.addEventListener(
+        "dblclick",
+        (event) => {
+          event.preventDefault();
+
+          const conversation = el.closest<HTMLElement>(".conversation")!;
+          if (!conversation.classList.contains("new")) {
+            return;
+          }
+          void markAsRead(conversation);
+        },
+        { once: true },
+      );
+    }
+  });
+}
index 740f02625ba27c6d88edd1f36b5e193614eb9474..8f00c720a571e718722821f4394d4431e28e3833 100644 (file)
@@ -4,7 +4,6 @@
  * @author  Matthias Schmidt
  * @copyright 2001-2021 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module  WoltLabSuite/Core/Conversation/Ui/Message/Quote
  * @woltlabExcludeBundle tiny
  */
 
index 58368f658c5ae65bfcb64104f73646503e50057c..6330cb8f69da7b2de978c8e0e10963213d4a9a9c 100644 (file)
@@ -4,7 +4,6 @@
  * @author  Matthias Schmidt
  * @copyright  2001-2021 WoltLab GmbH
  * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module  WoltLabSuite/Core/Conversation/Ui/Object/Action/RemoveParticipant
  */
 
 import UiObjectActionHandler from "WoltLabSuite/Core/Ui/Object/Action/Handler";
index f5430901c059ef5063efe59afe1f58524890ec03..38d41019daad5da3e1a38b2cd7034a3df05b7672 100644 (file)
@@ -4,7 +4,6 @@
  * @author  Alexander Ebert
  * @copyright   2001-2021 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module  WoltLabSuite/Core/Conversation/Ui/Participant/Add
  */
 
 import * as Ajax from "WoltLabSuite/Core/Ajax";
index 04ca79723cb3d477a5e3d86a3693fc6ffe66108b..8c257dcfa3f32e08920414578b27793a6f67a4f9 100644 (file)
@@ -4,7 +4,6 @@
  * @author  Alexander Ebert
  * @copyright   2001-2021 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module  WoltLabSuite/Core/Conversation/Ui/Subject/Editor
  */
 import { DialogCallbackObject } from "WoltLabSuite/Core/Ui/Dialog/Data";
 import UiDialog from "WoltLabSuite/Core/Ui/Dialog";
@@ -116,7 +115,9 @@ class UiSubjectEditor implements AjaxCallbackObject, DialogCallbackObject {
           </dd>
         </dl>
         <div class="formSubmit">
-          <button class="buttonPrimary jsButtonSave">${Language.get("wcf.global.button.save")}</button>
+          <button type="button" class="button buttonPrimary jsButtonSave">${Language.get(
+            "wcf.global.button.save",
+          )}</button>
         </div>
       `,
     };
index 60ce55a264c4754491f3d283030cb44f3af9ad0d..6c2b7de4adbfb202e9dc9a542791275906c4a4b3 100644 (file)
@@ -4,7 +4,6 @@
  * @author Alexander Ebert
  * @copyright 2001-2021 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Ui/User/Menu/Data/Notification
  * @woltlabExcludeBundle tiny
  */
 
@@ -66,7 +65,7 @@ class UserMenuDataConversation implements UserMenuProvider {
     const buttons: UserMenuButton[] = [];
     if (this.options.canStartConversation) {
       buttons.push({
-        icon: '<span class="icon icon24 fa-plus"></span>',
+        icon: '<fa-icon size="24" name="plus"></fa-icon>',
         link: this.options.newConversationLink,
         name: "newConversation",
         title: this.options.newConversationTitle,
index 789895bd1691014559390fc5063cee9ceaa14662..9c30c52d3692cef68ec3039e64e94e2e21210925 100644 (file)
@@ -1,16 +1,17 @@
 {
   "include": [
-    "node_modules/@woltlab/wcf/global.d.ts",
+    "node_modules/@woltlab/d.ts/global.d.ts",
     "ts/**/*"
   ],
   "compilerOptions": {
-    "target": "es2017",
+    "target": "ES2022",
     "module": "amd",
     "rootDir": "ts/",
     "outDir": "files/js/",
     "lib": [
-      "dom",
-      "es2017"
+      "DOM",
+      "DOM.Iterable",
+      "ES2022"
     ],
     "strictNullChecks": true,
     "moduleResolution": "node",
@@ -20,7 +21,7 @@
     "baseUrl": ".",
     "paths": {
       "*": [
-        "node_modules/@woltlab/wcf/ts/*"
+        "node_modules/@woltlab/d.ts/*"
       ]
     },
     "importHelpers": true,