Add simple tree style navigation
This commit is contained in:
parent
8c0deb905e
commit
d9a9f97751
8 changed files with 113 additions and 20 deletions
|
@ -80,7 +80,10 @@ const conversation = {
|
||||||
return this.$store.state.config.conversationDisplay
|
return this.$store.state.config.conversationDisplay
|
||||||
},
|
},
|
||||||
isTreeView () {
|
isTreeView () {
|
||||||
return this.displayStyle === 'tree'
|
return this.displayStyle === 'tree' || this.displayStyle === 'simple_tree'
|
||||||
|
},
|
||||||
|
treeViewIsSimple () {
|
||||||
|
return this.displayStyle === 'simple_tree'
|
||||||
},
|
},
|
||||||
isLinearView () {
|
isLinearView () {
|
||||||
return this.displayStyle === 'linear'
|
return this.displayStyle === 'linear'
|
||||||
|
@ -297,6 +300,14 @@ const conversation = {
|
||||||
},
|
},
|
||||||
canDive () {
|
canDive () {
|
||||||
return this.isTreeView && this.isExpanded
|
return this.isTreeView && this.isExpanded
|
||||||
|
},
|
||||||
|
focused () {
|
||||||
|
return (id) => {
|
||||||
|
return (this.isExpanded) && id === this.highlight
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maybeHighlight () {
|
||||||
|
return this.isExpanded ? this.highlight : null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
@ -316,6 +327,9 @@ const conversation = {
|
||||||
expanded (value) {
|
expanded (value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
this.fetchConversation()
|
this.fetchConversation()
|
||||||
|
} else {
|
||||||
|
// if we collapse it, we should reset the dive
|
||||||
|
this._diven = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
virtualHidden (value) {
|
virtualHidden (value) {
|
||||||
|
@ -323,6 +337,9 @@ const conversation = {
|
||||||
'setVirtualHeight',
|
'setVirtualHeight',
|
||||||
{ statusId: this.statusId, height: `${this.$el.clientHeight}px` }
|
{ statusId: this.statusId, height: `${this.$el.clientHeight}px` }
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
highlight (value, old) {
|
||||||
|
console.log('highlight:', old, ' => ', value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -341,7 +358,8 @@ const conversation = {
|
||||||
'this.threadDisplayStatus ', this.threadDisplayStatus,
|
'this.threadDisplayStatus ', this.threadDisplayStatus,
|
||||||
'this.statusId', this.statusId)
|
'this.statusId', this.statusId)
|
||||||
if (this.threadDisplayStatus[this.statusId] === 'hidden') {
|
if (this.threadDisplayStatus[this.statusId] === 'hidden') {
|
||||||
this.diveIntoStatus(parentOrSelf)
|
this.diveIntoStatus(parentOrSelf, /* preventScroll */ true)
|
||||||
|
this.tryScrollTo(this.statusId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -365,18 +383,16 @@ const conversation = {
|
||||||
getReplies (id) {
|
getReplies (id) {
|
||||||
return this.replies[id] || []
|
return this.replies[id] || []
|
||||||
},
|
},
|
||||||
focused (id) {
|
getHighlight () {
|
||||||
return (this.isExpanded) && id === this.statusId
|
return this.isExpanded ? this.highlight : null
|
||||||
},
|
},
|
||||||
setHighlight (id) {
|
setHighlight (id) {
|
||||||
|
console.log('setHighlight', id)
|
||||||
if (!id) return
|
if (!id) return
|
||||||
this.highlight = id
|
this.highlight = id
|
||||||
this.$store.dispatch('fetchFavsAndRepeats', id)
|
this.$store.dispatch('fetchFavsAndRepeats', id)
|
||||||
this.$store.dispatch('fetchEmojiReactionsBy', id)
|
this.$store.dispatch('fetchEmojiReactionsBy', id)
|
||||||
},
|
},
|
||||||
getHighlight () {
|
|
||||||
return this.isExpanded ? this.highlight : null
|
|
||||||
},
|
|
||||||
toggleExpanded () {
|
toggleExpanded () {
|
||||||
this.expanded = !this.expanded
|
this.expanded = !this.expanded
|
||||||
},
|
},
|
||||||
|
@ -420,14 +436,52 @@ const conversation = {
|
||||||
toggleStatusContentProperty (id, name) {
|
toggleStatusContentProperty (id, name) {
|
||||||
this.setStatusContentProperty(id, name, !this.statusContentProperties[id][name])
|
this.setStatusContentProperty(id, name, !this.statusContentProperties[id][name])
|
||||||
},
|
},
|
||||||
diveIntoStatus (id) {
|
leastShowingAncestor (id) {
|
||||||
|
let cur = id
|
||||||
|
let parent = this.parentOf(cur)
|
||||||
|
while (cur) {
|
||||||
|
// if the parent is showing it means cur is visible
|
||||||
|
if (this.threadDisplayStatus[parent] === 'showing') {
|
||||||
|
return cur
|
||||||
|
}
|
||||||
|
parent = this.parentOf(parent)
|
||||||
|
cur = this.parentOf(cur)
|
||||||
|
}
|
||||||
|
// nothing found, fall back to toplevel
|
||||||
|
return topLevel[0].id
|
||||||
|
},
|
||||||
|
diveIntoStatus (id, preventScroll) {
|
||||||
this.diveHistory = [...this.diveHistory, id]
|
this.diveHistory = [...this.diveHistory, id]
|
||||||
|
if (!preventScroll) {
|
||||||
|
this.goToCurrent()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
diveBack () {
|
diveBack () {
|
||||||
|
const oldHighlight = this.highlight
|
||||||
this.diveHistory = [...this.diveHistory.slice(0, this.diveHistory.length - 1)]
|
this.diveHistory = [...this.diveHistory.slice(0, this.diveHistory.length - 1)]
|
||||||
|
if (oldHighlight) {
|
||||||
|
this.tryScrollTo(this.leastShowingAncestor(oldHighlight))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
undive () {
|
undive () {
|
||||||
|
const oldHighlight = this.highlight
|
||||||
this.diveHistory = []
|
this.diveHistory = []
|
||||||
|
if (oldHighlight) {
|
||||||
|
this.tryScrollTo(this.leastShowingAncestor(oldHighlight))
|
||||||
|
} else {
|
||||||
|
this.goToCurrent()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tryScrollTo (id) {
|
||||||
|
if (this.isPage) {
|
||||||
|
// set statusId
|
||||||
|
this.$router.push({ name: 'conversation', params: { id } })
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setHighlight(id)
|
||||||
|
},
|
||||||
|
goToCurrent () {
|
||||||
|
this.tryScrollTo(this.diveRoot || this.topLevel[0].id)
|
||||||
},
|
},
|
||||||
statusById (id) {
|
statusById (id) {
|
||||||
return this.statusMap[id]
|
return this.statusMap[id]
|
||||||
|
|
|
@ -61,10 +61,11 @@
|
||||||
|
|
||||||
:focused="focused"
|
:focused="focused"
|
||||||
:get-replies="getReplies"
|
:get-replies="getReplies"
|
||||||
:get-highlight="getHighlight"
|
:highlight="maybeHighlight"
|
||||||
:set-highlight="setHighlight"
|
:set-highlight="setHighlight"
|
||||||
:toggle-expanded="toggleExpanded"
|
:toggle-expanded="toggleExpanded"
|
||||||
|
|
||||||
|
:simple="treeViewIsSimple"
|
||||||
:toggle-thread-display="toggleThreadDisplay"
|
:toggle-thread-display="toggleThreadDisplay"
|
||||||
:thread-display-status="threadDisplayStatus"
|
:thread-display-status="threadDisplayStatus"
|
||||||
:show-thread-recursively="showThreadRecursively"
|
:show-thread-recursively="showThreadRecursively"
|
||||||
|
|
|
@ -20,7 +20,7 @@ const GeneralTab = {
|
||||||
value: mode,
|
value: mode,
|
||||||
label: this.$t(`settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`)
|
label: this.$t(`settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`)
|
||||||
})),
|
})),
|
||||||
conversationDisplayOptions: ['tree', 'linear'].map(mode => ({
|
conversationDisplayOptions: ['tree', 'simple_tree', 'linear'].map(mode => ({
|
||||||
key: mode,
|
key: mode,
|
||||||
value: mode,
|
value: mode,
|
||||||
label: this.$t(`settings.conversation_display_${mode}`)
|
label: this.$t(`settings.conversation_display_${mode}`)
|
||||||
|
|
|
@ -97,6 +97,7 @@ const Status = {
|
||||||
'inProfile',
|
'inProfile',
|
||||||
'profileUserId',
|
'profileUserId',
|
||||||
|
|
||||||
|
'simpleTree',
|
||||||
'controlledThreadDisplayStatus',
|
'controlledThreadDisplayStatus',
|
||||||
'controlledToggleThreadDisplay',
|
'controlledToggleThreadDisplay',
|
||||||
|
|
||||||
|
@ -379,10 +380,9 @@ const Status = {
|
||||||
},
|
},
|
||||||
toggleThreadDisplay () {
|
toggleThreadDisplay () {
|
||||||
this.controlledToggleThreadDisplay()
|
this.controlledToggleThreadDisplay()
|
||||||
}
|
},
|
||||||
},
|
scrollIfHighlighted (highlightId) {
|
||||||
watch: {
|
const id = highlightId
|
||||||
'highlight': function (id) {
|
|
||||||
if (this.status.id === id) {
|
if (this.status.id === id) {
|
||||||
let rect = this.$el.getBoundingClientRect()
|
let rect = this.$el.getBoundingClientRect()
|
||||||
if (rect.top < 100) {
|
if (rect.top < 100) {
|
||||||
|
@ -396,6 +396,14 @@ const Status = {
|
||||||
window.scrollBy(0, rect.bottom - window.innerHeight + 50)
|
window.scrollBy(0, rect.bottom - window.innerHeight + 50)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.scrollIfHighlighted(this.highlight)
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'highlight': function (id) {
|
||||||
|
this.scrollIfHighlighted(id)
|
||||||
},
|
},
|
||||||
'status.repeat_num': function (num) {
|
'status.repeat_num': function (num) {
|
||||||
// refetch repeats when repeat_num is changed in any way
|
// refetch repeats when repeat_num is changed in any way
|
||||||
|
|
|
@ -220,7 +220,7 @@
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="inThreadForest && replies && replies.length && toggleThreadDisplay"
|
v-if="inThreadForest && replies && replies.length && !simpleTree"
|
||||||
class="button-unstyled"
|
class="button-unstyled"
|
||||||
:title="threadShowing ? $t('status.thread_hide') : $t('status.thread_show')"
|
:title="threadShowing ? $t('status.thread_hide') : $t('status.thread_show')"
|
||||||
:aria-expanded="threadShowing ? 'true' : 'false'"
|
:aria-expanded="threadShowing ? 'true' : 'false'"
|
||||||
|
@ -233,7 +233,7 @@
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="dive"
|
v-if="dive && !simpleTree"
|
||||||
class="button-unstyled"
|
class="button-unstyled"
|
||||||
:title="$t('status.show_only_conversation_under_this')"
|
:title="$t('status.show_only_conversation_under_this')"
|
||||||
@click.prevent="dive"
|
@click.prevent="dive"
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
import Status from '../status/status.vue'
|
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 debug = console.log
|
// const debug = console.log
|
||||||
const debug = () => {}
|
const debug = () => {}
|
||||||
|
|
||||||
|
@ -19,11 +30,12 @@ const ThreadTree = {
|
||||||
profileUserId: String,
|
profileUserId: String,
|
||||||
|
|
||||||
focused: Function,
|
focused: Function,
|
||||||
getHighlight: Function,
|
highlight: String,
|
||||||
getReplies: Function,
|
getReplies: Function,
|
||||||
setHighlight: Function,
|
setHighlight: Function,
|
||||||
toggleExpanded: Function,
|
toggleExpanded: Function,
|
||||||
|
|
||||||
|
simple: Boolean,
|
||||||
// to control display of the whole thread forest
|
// to control display of the whole thread forest
|
||||||
toggleThreadDisplay: Function,
|
toggleThreadDisplay: Function,
|
||||||
threadDisplayStatus: Object,
|
threadDisplayStatus: Object,
|
||||||
|
|
|
@ -9,12 +9,13 @@
|
||||||
:show-pinned="pinnedStatusIdsObject && pinnedStatusIdsObject[status.id]"
|
:show-pinned="pinnedStatusIdsObject && pinnedStatusIdsObject[status.id]"
|
||||||
:focused="focused(status.id)"
|
:focused="focused(status.id)"
|
||||||
:in-conversation="isExpanded"
|
:in-conversation="isExpanded"
|
||||||
:highlight="getHighlight()"
|
:highlight="highlight"
|
||||||
:replies="getReplies(status.id)"
|
:replies="getReplies(status.id)"
|
||||||
:in-profile="inProfile"
|
:in-profile="inProfile"
|
||||||
:profile-user-id="profileUserId"
|
:profile-user-id="profileUserId"
|
||||||
class="conversation-status conversation-status-treeview status-fadein panel-body"
|
class="conversation-status conversation-status-treeview status-fadein panel-body"
|
||||||
|
|
||||||
|
:simple-tree="simple"
|
||||||
:controlled-thread-display-status="threadDisplayStatus[status.id]"
|
:controlled-thread-display-status="threadDisplayStatus[status.id]"
|
||||||
:controlled-toggle-thread-display="() => toggleThreadDisplay(status.id)"
|
:controlled-toggle-thread-display="() => toggleThreadDisplay(status.id)"
|
||||||
|
|
||||||
|
@ -49,10 +50,11 @@
|
||||||
|
|
||||||
:focused="focused"
|
:focused="focused"
|
||||||
:get-replies="getReplies"
|
:get-replies="getReplies"
|
||||||
:get-highlight="getHighlight"
|
:highlight="highlight"
|
||||||
:set-highlight="setHighlight"
|
:set-highlight="setHighlight"
|
||||||
:toggle-expanded="toggleExpanded"
|
:toggle-expanded="toggleExpanded"
|
||||||
|
|
||||||
|
:simple="simple"
|
||||||
:toggle-thread-display="toggleThreadDisplay"
|
:toggle-thread-display="toggleThreadDisplay"
|
||||||
:thread-display-status="threadDisplayStatus"
|
:thread-display-status="threadDisplayStatus"
|
||||||
:show-thread-recursively="showThreadRecursively"
|
:show-thread-recursively="showThreadRecursively"
|
||||||
|
@ -69,6 +71,22 @@
|
||||||
class="thread-tree-replies thread-tree-replies-hidden"
|
class="thread-tree-replies thread-tree-replies-hidden"
|
||||||
>
|
>
|
||||||
<i18n
|
<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"
|
tag="button"
|
||||||
path="status.thread_show_full_with_icon"
|
path="status.thread_show_full_with_icon"
|
||||||
class="button-unstyled -link thread-tree-show-replies-button"
|
class="button-unstyled -link thread-tree-show-replies-button"
|
||||||
|
|
|
@ -53,7 +53,7 @@ const defaultState = {
|
||||||
theme: 'pleroma-dark',
|
theme: 'pleroma-dark',
|
||||||
virtualScrolling: true,
|
virtualScrolling: true,
|
||||||
sensitiveByDefault: false,
|
sensitiveByDefault: false,
|
||||||
conversationDisplay: 'tree',
|
conversationDisplay: 'simple_tree',
|
||||||
|
|
||||||
// Nasty stuff
|
// Nasty stuff
|
||||||
customEmoji: [],
|
customEmoji: [],
|
||||||
|
|
Loading…
Reference in a new issue