Remove unread timeline and fix scroll position in tags

This commit is contained in:
AkiraFukushima 2021-07-25 23:36:40 +09:00
parent 477593e932
commit 66ad195560
No known key found for this signature in database
GPG Key ID: B6E51BAC4DE1A957
4 changed files with 35 additions and 66 deletions

View File

@ -118,8 +118,7 @@ let state = (): TagState => {
return { return {
lazyLoading: false, lazyLoading: false,
heading: true, heading: true,
timeline: [], timeline: []
unreadTimeline: []
} }
} }
@ -180,8 +179,7 @@ describe('Home', () => {
return { return {
lazyLoading: false, lazyLoading: false,
heading: true, heading: true,
timeline: [status1], timeline: [status1]
unreadTimeline: []
} }
} }
}) })

View File

@ -136,8 +136,7 @@ describe('TimelineSpace/Contents/Hashtag/Tag', () => {
state = { state = {
lazyLoading: false, lazyLoading: false,
heading: true, heading: true,
timeline: [status2, status1], timeline: [status2, status1]
unreadTimeline: []
} }
}) })
it('should be deleted', () => { it('should be deleted', () => {
@ -151,8 +150,7 @@ describe('TimelineSpace/Contents/Hashtag/Tag', () => {
state = { state = {
lazyLoading: false, lazyLoading: false,
heading: true, heading: true,
timeline: [status2, rebloggedStatus], timeline: [status2, rebloggedStatus]
unreadTimeline: []
} }
}) })
it('should be deleted', () => { it('should be deleted', () => {
@ -169,14 +167,12 @@ describe('TimelineSpace/Contents/Hashtag/Tag', () => {
state = { state = {
lazyLoading: false, lazyLoading: false,
heading: true, heading: true,
timeline: [status2, status1], timeline: [status2, status1]
unreadTimeline: []
} }
}) })
it('should be updated timeline', () => { it('should be updated timeline', () => {
Tag.mutations![MUTATION_TYPES.APPEND_TIMELINE](state, rebloggedStatus) Tag.mutations![MUTATION_TYPES.APPEND_TIMELINE](state, rebloggedStatus)
expect(state.timeline).toEqual([rebloggedStatus, status2, status1]) expect(state.timeline).toEqual([rebloggedStatus, status2, status1])
expect(state.unreadTimeline).toEqual([])
}) })
}) })
@ -185,14 +181,12 @@ describe('TimelineSpace/Contents/Hashtag/Tag', () => {
state = { state = {
lazyLoading: false, lazyLoading: false,
heading: true, heading: true,
timeline: [rebloggedStatus, status2, status1], timeline: [rebloggedStatus, status2, status1]
unreadTimeline: []
} }
}) })
it('should not be updated timeline', () => { it('should not be updated timeline', () => {
Tag.mutations![MUTATION_TYPES.APPEND_TIMELINE](state, rebloggedStatus) Tag.mutations![MUTATION_TYPES.APPEND_TIMELINE](state, rebloggedStatus)
expect(state.timeline).toEqual([rebloggedStatus, status2, status1]) expect(state.timeline).toEqual([rebloggedStatus, status2, status1])
expect(state.unreadTimeline).toEqual([])
}) })
}) })
}) })
@ -203,14 +197,12 @@ describe('TimelineSpace/Contents/Hashtag/Tag', () => {
state = { state = {
lazyLoading: false, lazyLoading: false,
heading: false, heading: false,
timeline: [status2, status1], timeline: [status2, status1]
unreadTimeline: []
} }
}) })
it('should be updated timeline', () => { it('should be updated timeline', () => {
Tag.mutations![MUTATION_TYPES.APPEND_TIMELINE](state, rebloggedStatus) Tag.mutations![MUTATION_TYPES.APPEND_TIMELINE](state, rebloggedStatus)
expect(state.timeline).toEqual([status2, status1]) expect(state.timeline).toEqual([rebloggedStatus, status2, status1])
expect(state.unreadTimeline).toEqual([rebloggedStatus])
}) })
}) })
@ -219,14 +211,12 @@ describe('TimelineSpace/Contents/Hashtag/Tag', () => {
state = { state = {
lazyLoading: false, lazyLoading: false,
heading: false, heading: false,
timeline: [rebloggedStatus, status2, status1], timeline: [rebloggedStatus, status2, status1]
unreadTimeline: []
} }
}) })
it('should not be updated timeline', () => { it('should not be updated timeline', () => {
Tag.mutations![MUTATION_TYPES.APPEND_TIMELINE](state, rebloggedStatus) Tag.mutations![MUTATION_TYPES.APPEND_TIMELINE](state, rebloggedStatus)
expect(state.timeline).toEqual([rebloggedStatus, status2, status1]) expect(state.timeline).toEqual([rebloggedStatus, status2, status1])
expect(state.unreadTimeline).toEqual([])
}) })
}) })
}) })

View File

@ -1,8 +1,7 @@
<template> <template>
<div name="tag" class="tag-timeline" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey"> <div name="tag" class="tag-timeline" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div class="unread">{{ unread.length > 0 ? unread.length : '' }}</div>
<div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div> <div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
<DynamicScroller :items="timeline" :min-item-size="60" id="scroller" class="scroller" ref="scroller"> <DynamicScroller :items="timeline" :min-item-size="86" id="scroller" class="scroller" ref="scroller">
<template v-slot="{ item, index, active }"> <template v-slot="{ item, index, active }">
<DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true"> <DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.uri]" :data-index="index" :watchData="true">
<toot <toot
@ -32,6 +31,7 @@ import { mapState, mapGetters } from 'vuex'
import Toot from '~/src/renderer/components/organisms/Toot' import Toot from '~/src/renderer/components/organisms/Toot'
import reloadable from '~/src/renderer/components/mixins/reloadable' import reloadable from '~/src/renderer/components/mixins/reloadable'
import { Event } from '~/src/renderer/components/event' import { Event } from '~/src/renderer/components/event'
import { ScrollPosition } from '~/src/renderer/components/utils/scroll'
export default { export default {
name: 'tag', name: 'tag',
@ -40,7 +40,8 @@ export default {
props: ['tag'], props: ['tag'],
data() { data() {
return { return {
focusedId: null focusedId: null,
scroll: null
} }
}, },
computed: { computed: {
@ -50,8 +51,7 @@ export default {
startReload: state => state.TimelineSpace.HeaderMenu.reload, startReload: state => state.TimelineSpace.HeaderMenu.reload,
timeline: state => state.TimelineSpace.Contents.Hashtag.Tag.timeline, timeline: state => state.TimelineSpace.Contents.Hashtag.Tag.timeline,
lazyLoading: state => state.TimelineSpace.Contents.Hashtag.Tag.lazyLoading, lazyLoading: state => state.TimelineSpace.Contents.Hashtag.Tag.lazyLoading,
heading: state => state.TimelineSpace.Contents.Hashtag.Tag.heading, heading: state => state.TimelineSpace.Contents.Hashtag.Tag.heading
unread: state => state.TimelineSpace.Contents.Hashtag.Tag.unreadTimeline
}), }),
...mapGetters('TimelineSpace/Modals', ['modalOpened']), ...mapGetters('TimelineSpace/Modals', ['modalOpened']),
shortcutEnabled: function () { shortcutEnabled: function () {
@ -81,6 +81,21 @@ export default {
this.focusedId = previousFocusedId this.focusedId = previousFocusedId
}) })
}) })
const el = document.getElementById('scroller')
this.scroll = new ScrollPosition(el)
this.scroll.prepare()
},
beforeUpdate() {
if (!this.heading && !this.lazyLoading) {
const el = document.getElementById('scroller')
this.scroll = new ScrollPosition(el)
this.scroll.prepare()
}
},
updated() {
if (this.scroll && !this.heading && !this.lazyLoading) {
this.scroll.restore()
}
}, },
watch: { watch: {
tag: function (newTag, _oldTag) { tag: function (newTag, _oldTag) {
@ -102,7 +117,6 @@ export default {
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', false) this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', false)
} else if (newState === null && !this.heading) { } else if (newState === null && !this.heading) {
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true) this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/mergeTimeline')
} }
} }
}, },
@ -129,7 +143,6 @@ export default {
}, },
reset() { reset() {
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true) this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true)
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/mergeTimeline')
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/archiveTimeline') this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/archiveTimeline')
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/clearTimeline') this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/clearTimeline')
if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) { if (document.getElementById('scroller') !== undefined && document.getElementById('scroller') !== null) {
@ -153,17 +166,12 @@ export default {
status: this.timeline[this.timeline.length - 1] status: this.timeline[this.timeline.length - 1]
}) })
} }
// for unread control
if (event.target.scrollTop > 5 && this.heading) { if (event.target.scrollTop > 10 && this.heading) {
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', false) this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', false)
} else if (event.target.scrollTop <= 5 && !this.heading) { } else if (event.target.scrollTop <= 10 && !this.heading) {
const currentPos = this.unread.length
if (currentPos === 0) {
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true) this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/changeHeading', true)
} }
this.$store.commit('TimelineSpace/Contents/Hashtag/Tag/mergeTimeline')
this.$refs.scroller.scrollToItem(currentPos)
}
}, },
async reload() { async reload() {
const tag = this.tag const tag = this.tag
@ -234,21 +242,6 @@ export default {
height: 100%; height: 100%;
} }
.unread {
position: fixed;
right: 24px;
top: 48px;
background-color: rgba(0, 0, 0, 0.7);
color: #ffffff;
padding: 4px 8px;
border-radius: 0 0 2px 2px;
z-index: 1;
&:empty {
display: none;
}
}
.upper { .upper {
position: fixed; position: fixed;
bottom: 20px; bottom: 20px;

View File

@ -8,14 +8,12 @@ const win = (window as any) as MyWindow
export type TagState = { export type TagState = {
timeline: Array<Entity.Status> timeline: Array<Entity.Status>
unreadTimeline: Array<Entity.Status>
lazyLoading: boolean lazyLoading: boolean
heading: boolean heading: boolean
} }
const state = (): TagState => ({ const state = (): TagState => ({
timeline: [], timeline: [],
unreadTimeline: [],
lazyLoading: false, lazyLoading: false,
heading: true heading: true
}) })
@ -24,7 +22,6 @@ export const MUTATION_TYPES = {
CHANGE_HEADING: 'changeHeading', CHANGE_HEADING: 'changeHeading',
APPEND_TIMELINE: 'appendTimeline', APPEND_TIMELINE: 'appendTimeline',
UPDATE_TIMELINE: 'updateTimeline', UPDATE_TIMELINE: 'updateTimeline',
MERGE_TIMELINE: 'mergeTimeline',
INSERT_TIMELINE: 'insertTimeline', INSERT_TIMELINE: 'insertTimeline',
ARCHIVE_TIMELINE: 'archiveTimeline', ARCHIVE_TIMELINE: 'archiveTimeline',
CLEAR_TIMELINE: 'clearTimeline', CLEAR_TIMELINE: 'clearTimeline',
@ -39,21 +36,13 @@ const mutations: MutationTree<TagState> = {
}, },
[MUTATION_TYPES.APPEND_TIMELINE]: (state, update: Entity.Status) => { [MUTATION_TYPES.APPEND_TIMELINE]: (state, update: Entity.Status) => {
// Reject duplicated status in timeline // Reject duplicated status in timeline
if (!state.timeline.find(item => item.id === update.id) && !state.unreadTimeline.find(item => item.id === update.id)) { if (!state.timeline.find(item => item.id === update.id)) {
if (state.heading) {
state.timeline = [update].concat(state.timeline) state.timeline = [update].concat(state.timeline)
} else {
state.unreadTimeline = [update].concat(state.unreadTimeline)
}
} }
}, },
[MUTATION_TYPES.UPDATE_TIMELINE]: (state, timeline: Array<Entity.Status>) => { [MUTATION_TYPES.UPDATE_TIMELINE]: (state, timeline: Array<Entity.Status>) => {
state.timeline = timeline state.timeline = timeline
}, },
[MUTATION_TYPES.MERGE_TIMELINE]: state => {
state.timeline = state.unreadTimeline.slice(0, 80).concat(state.timeline)
state.unreadTimeline = []
},
[MUTATION_TYPES.INSERT_TIMELINE]: (state, messages: Array<Entity.Status>) => { [MUTATION_TYPES.INSERT_TIMELINE]: (state, messages: Array<Entity.Status>) => {
state.timeline = state.timeline.concat(messages) state.timeline = state.timeline.concat(messages)
}, },
@ -62,7 +51,6 @@ const mutations: MutationTree<TagState> = {
}, },
[MUTATION_TYPES.CLEAR_TIMELINE]: state => { [MUTATION_TYPES.CLEAR_TIMELINE]: state => {
state.timeline = [] state.timeline = []
state.unreadTimeline = []
}, },
[MUTATION_TYPES.UPDATE_TOOT]: (state, message: Entity.Status) => { [MUTATION_TYPES.UPDATE_TOOT]: (state, message: Entity.Status) => {
state.timeline = state.timeline.map(toot => { state.timeline = state.timeline.map(toot => {