aboutsummaryrefslogtreecommitdiff
path: root/src/components/thread_tree
diff options
context:
space:
mode:
authorHJ <30-hj@users.noreply.git.pleroma.social>2022-03-13 17:31:46 +0000
committerHJ <30-hj@users.noreply.git.pleroma.social>2022-03-13 17:31:46 +0000
commite34d71fc1f64fde73e435262979e5e93ebd37df2 (patch)
tree8b43c0e6f070c7f5a5fd72d1fcc986ca52524ed2 /src/components/thread_tree
parent89efb0d2f4ab41eb020e6a6b7bb14dbe20e53157 (diff)
parent551b8f3690bab1f53ec22ccf6963009a30fa45d0 (diff)
Merge branch 'from/develop/tusooa/tree-threading' into 'develop'
Add the option to display threads as trees See merge request pleroma/pleroma-fe!1407
Diffstat (limited to 'src/components/thread_tree')
-rw-r--r--src/components/thread_tree/thread_tree.js90
-rw-r--r--src/components/thread_tree/thread_tree.vue127
2 files changed, 217 insertions, 0 deletions
diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js
new file mode 100644
index 00000000..71e63725
--- /dev/null
+++ b/src/components/thread_tree/thread_tree.js
@@ -0,0 +1,90 @@
+import Status from '../status/status.vue'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+ faAngleDoubleDown,
+ faAngleDoubleRight
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+ faAngleDoubleDown,
+ faAngleDoubleRight
+)
+
+const ThreadTree = {
+ components: {
+ Status
+ },
+ name: 'ThreadTree',
+ props: {
+ depth: Number,
+ status: Object,
+ inProfile: Boolean,
+ conversation: Array,
+ collapsable: Boolean,
+ isExpanded: Boolean,
+ pinnedStatusIdsObject: Object,
+ profileUserId: String,
+
+ focused: Function,
+ highlight: String,
+ getReplies: Function,
+ setHighlight: Function,
+ toggleExpanded: Function,
+
+ simple: Boolean,
+ // to control display of the whole thread forest
+ toggleThreadDisplay: Function,
+ threadDisplayStatus: Object,
+ showThreadRecursively: Function,
+ totalReplyCount: Object,
+ totalReplyDepth: Object,
+ statusContentProperties: Object,
+ setStatusContentProperty: Function,
+ toggleStatusContentProperty: Function,
+ dive: Function
+ },
+ computed: {
+ suspendable () {
+ const selfSuspendable = this.$refs.statusComponent ? this.$refs.statusComponent.suspendable : true
+ if (this.$refs.childComponent) {
+ return selfSuspendable && this.$refs.childComponent.every(s => s.suspendable)
+ }
+ return selfSuspendable
+ },
+ reverseLookupTable () {
+ return this.conversation.reduce((table, status, index) => {
+ table[status.id] = index
+ return table
+ }, {})
+ },
+ currentReplies () {
+ return this.getReplies(this.status.id).map(({ id }) => this.statusById(id))
+ },
+ threadShowing () {
+ return this.threadDisplayStatus[this.status.id] === 'showing'
+ },
+ currentProp () {
+ return this.statusContentProperties[this.status.id]
+ }
+ },
+ methods: {
+ statusById (id) {
+ return this.conversation[this.reverseLookupTable[id]]
+ },
+ collapseThread () {
+ },
+ showThread () {
+ },
+ showAllSubthreads () {
+ },
+ toggleCurrentProp (name) {
+ this.toggleStatusContentProperty(this.status.id, name)
+ },
+ setCurrentProp (name, newVal) {
+ this.setStatusContentProperty(this.status.id, name)
+ }
+ }
+}
+
+export default ThreadTree
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
new file mode 100644
index 00000000..e64455e0
--- /dev/null
+++ b/src/components/thread_tree/thread_tree.vue
@@ -0,0 +1,127 @@
+<template>
+ <div class="thread-tree panel-body">
+ <status
+ :key="status.id"
+ ref="statusComponent"
+ :inline-expanded="collapsable && isExpanded"
+ :statusoid="status"
+ :expandable="!isExpanded"
+ :show-pinned="pinnedStatusIdsObject && pinnedStatusIdsObject[status.id]"
+ :focused="focused(status.id)"
+ :in-conversation="isExpanded"
+ :highlight="highlight"
+ :replies="getReplies(status.id)"
+ :in-profile="inProfile"
+ :profile-user-id="profileUserId"
+ class="conversation-status conversation-status-treeview status-fadein panel-body"
+
+ :simple-tree="simple"
+ :controlled-thread-display-status="threadDisplayStatus[status.id]"
+ :controlled-toggle-thread-display="() => toggleThreadDisplay(status.id)"
+
+ :controlled-showing-tall="currentProp.showingTall"
+ :controlled-expanding-subject="currentProp.expandingSubject"
+ :controlled-showing-long-subject="currentProp.showingLongSubject"
+ :controlled-replying="currentProp.replying"
+ :controlled-media-playing="currentProp.mediaPlaying"
+ :controlled-toggle-showing-tall="() => toggleCurrentProp('showingTall')"
+ :controlled-toggle-expanding-subject="() => toggleCurrentProp('expandingSubject')"
+ :controlled-toggle-showing-long-subject="() => toggleCurrentProp('showingLongSubject')"
+ :controlled-toggle-replying="() => toggleCurrentProp('replying')"
+ :controlled-set-media-playing="(newVal) => setCurrentProp('mediaPlaying', newVal)"
+ :dive="dive ? () => dive(status.id) : undefined"
+
+ @goto="setHighlight"
+ @toggleExpanded="toggleExpanded"
+ />
+ <div
+ v-if="currentReplies.length && threadShowing"
+ class="thread-tree-replies"
+ >
+ <thread-tree
+ v-for="replyStatus in currentReplies"
+ :key="replyStatus.id"
+ ref="childComponent"
+ :depth="depth + 1"
+ :status="replyStatus"
+
+ :in-profile="inProfile"
+ :conversation="conversation"
+ :collapsable="collapsable"
+ :is-expanded="isExpanded"
+ :pinned-status-ids-object="pinnedStatusIdsObject"
+ :profile-user-id="profileUserId"
+
+ :focused="focused"
+ :get-replies="getReplies"
+ :highlight="highlight"
+ :set-highlight="setHighlight"
+ :toggle-expanded="toggleExpanded"
+
+ :simple="simple"
+ :toggle-thread-display="toggleThreadDisplay"
+ :thread-display-status="threadDisplayStatus"
+ :show-thread-recursively="showThreadRecursively"
+ :total-reply-count="totalReplyCount"
+ :total-reply-depth="totalReplyDepth"
+ :status-content-properties="statusContentProperties"
+ :set-status-content-property="setStatusContentProperty"
+ :toggle-status-content-property="toggleStatusContentProperty"
+ :dive="dive"
+ />
+ </div>
+ <div
+ v-if="currentReplies.length && !threadShowing"
+ class="thread-tree-replies thread-tree-replies-hidden"
+ >
+ <i18n
+ v-if="simple"
+ tag="button"
+ path="status.thread_follow_with_icon"
+ class="button-unstyled -link thread-tree-show-replies-button"
+ @click.prevent="dive(status.id)"
+ >
+ <FAIcon
+ place="icon"
+ icon="angle-double-right"
+ />
+ <span place="text">
+ {{ $tc('status.thread_follow', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id] }) }}
+ </span>
+ </i18n>
+ <i18n
+ v-else
+ tag="button"
+ path="status.thread_show_full_with_icon"
+ class="button-unstyled -link thread-tree-show-replies-button"
+ @click.prevent="showThreadRecursively(status.id)"
+ >
+ <FAIcon
+ place="icon"
+ icon="angle-double-down"
+ />
+ <span place="text">
+ {{ $tc('status.thread_show_full', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }}
+ </span>
+ </i18n>
+ </div>
+ </div>
+</template>
+
+<script src="./thread_tree.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+.thread-tree-replies {
+ margin-left: var(--status-margin, $status-margin);
+ border-left: 2px solid var(--border, $fallback--border);
+}
+
+.thread-tree-replies-hidden {
+ padding: var(--status-margin, $status-margin);
+ /* Make the button stretch along the whole row */
+ display: flex;
+ align-items: stretch;
+ flex-direction: column;
+}
+</style>