diff --git a/src/client/app/desktop/views/components/notes.vue b/src/client/app/desktop/views/components/notes.vue index 3fad7c9226..9044ad3478 100644 --- a/src/client/app/desktop/views/components/notes.vue +++ b/src/client/app/desktop/views/components/notes.vue @@ -123,7 +123,7 @@ export default Vue.extend({ }, fetchMore() { - if (!this.more || this.moreFetching) return; + if (!this.more || this.moreFetching || this.notes.length === 0) return; this.moreFetching = true; this.makePromise(this.notes[this.notes.length - 1].id).then(x => { this.notes = this.notes.concat(x.notes); diff --git a/src/client/app/desktop/views/components/user-list-timeline.vue b/src/client/app/desktop/views/components/user-list-timeline.vue index 0cbe5ff05a..4437b838f2 100644 --- a/src/client/app/desktop/views/components/user-list-timeline.vue +++ b/src/client/app/desktop/views/components/user-list-timeline.vue @@ -18,10 +18,12 @@ export default Vue.extend({ data() { return { connection: null, + date: null, makePromise: cursor => this.$root.api('notes/user-list-timeline', { listId: this.list.id, limit: fetchLimit + 1, untilId: cursor ? cursor : undefined, + untilDate: cursor ? undefined : (this.date ? this.date.getTime() : undefined), includeMyRenotes: this.$store.state.settings.showMyRenotes, includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes, includeLocalRenotes: this.$store.state.settings.showLocalRenotes @@ -46,6 +48,10 @@ export default Vue.extend({ }, mounted() { this.init(); + this.$root.$on('warp', this.warp); + this.$once('hook:beforeDestroy', () => { + this.$root.$off('warp', this.warp); + }); }, beforeDestroy() { this.connection.dispose(); @@ -68,6 +74,10 @@ export default Vue.extend({ }, onUserRemoved() { (this.$refs.timeline as any).reload(); + }, + warp(date) { + this.date = date; + (this.$refs.timeline as any).reload(); } } }); diff --git a/src/client/app/desktop/views/home/user/user.timeline.vue b/src/client/app/desktop/views/home/user/user.timeline.vue index 086ad6a329..0435d67dc7 100644 --- a/src/client/app/desktop/views/home/user/user.timeline.vue +++ b/src/client/app/desktop/views/home/user/user.timeline.vue @@ -36,6 +36,7 @@ export default Vue.extend({ includeReplies: this.mode == 'with-replies', includeMyRenotes: this.mode != 'my-posts', withFiles: this.mode == 'with-media', + untilDate: cursor ? undefined : (this.date ? this.date.getTime() : undefined), untilId: cursor ? cursor : undefined }).then(notes => { if (notes.length == fetchLimit + 1) { @@ -62,10 +63,11 @@ export default Vue.extend({ mounted() { document.addEventListener('keydown', this.onDocumentKeydown); - }, - - beforeDestroy() { - document.removeEventListener('keydown', this.onDocumentKeydown); + this.$root.$on('warp', this.warp); + this.$once('hook:beforeDestroy', () => { + this.$root.$off('warp', this.warp); + document.removeEventListener('keydown', this.onDocumentKeydown); + }); }, methods: { diff --git a/src/client/app/mobile/views/components/notes.vue b/src/client/app/mobile/views/components/notes.vue index 5f3f5633d4..2e42300717 100644 --- a/src/client/app/mobile/views/components/notes.vue +++ b/src/client/app/mobile/views/components/notes.vue @@ -124,7 +124,7 @@ export default Vue.extend({ }, fetchMore() { - if (!this.more || this.moreFetching) return; + if (!this.more || this.moreFetching || this.notes.length === 0) return; this.moreFetching = true; this.makePromise(this.notes[this.notes.length - 1].id).then(x => { this.notes = this.notes.concat(x.notes); diff --git a/src/client/app/mobile/views/components/user-list-timeline.vue b/src/client/app/mobile/views/components/user-list-timeline.vue index c3f09c9b15..73bc6f3034 100644 --- a/src/client/app/mobile/views/components/user-list-timeline.vue +++ b/src/client/app/mobile/views/components/user-list-timeline.vue @@ -15,10 +15,12 @@ export default Vue.extend({ data() { return { connection: null, + date: null, makePromise: cursor => this.$root.api('notes/user-list-timeline', { listId: this.list.id, limit: fetchLimit + 1, untilId: cursor ? cursor : undefined, + untilDate: cursor ? undefined : (this.date ? this.date.getTime() : undefined), includeMyRenotes: this.$store.state.settings.showMyRenotes, includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes, includeLocalRenotes: this.$store.state.settings.showLocalRenotes @@ -45,6 +47,11 @@ export default Vue.extend({ mounted() { this.init(); + + this.$root.$on('warp', this.warp); + this.$once('hook:beforeDestroy', () => { + this.$root.$off('warp', this.warp); + }); }, beforeDestroy() { @@ -73,6 +80,11 @@ export default Vue.extend({ onUserRemoved() { (this.$refs.timeline as any).reload(); + }, + + warp(date) { + this.date = date; + (this.$refs.timeline as any).reload(); } } }); diff --git a/src/client/app/mobile/views/components/user-timeline.vue b/src/client/app/mobile/views/components/user-timeline.vue index 70016a49e3..8c7c8c6d7d 100644 --- a/src/client/app/mobile/views/components/user-timeline.vue +++ b/src/client/app/mobile/views/components/user-timeline.vue @@ -17,10 +17,12 @@ export default Vue.extend({ data() { return { + date: null, makePromise: cursor => this.$root.api('users/notes', { userId: this.user.id, limit: fetchLimit + 1, withFiles: this.withMedia, + untilDate: cursor ? undefined : (this.date ? this.date.getTime() : undefined), untilId: cursor ? cursor : undefined }).then(notes => { if (notes.length == fetchLimit + 1) { @@ -37,6 +39,20 @@ export default Vue.extend({ } }) }; + }, + + created() { + this.$root.$on('warp', this.warp); + this.$once('hook:beforeDestroy', () => { + this.$root.$off('warp', this.warp); + }); + }, + + methods: { + warp(date) { + this.date = date; + (this.$refs.timeline as any).reload(); + } } }); diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts index d3f17bd787..4691a99394 100644 --- a/src/server/api/endpoints/users/notes.ts +++ b/src/server/api/endpoints/users/notes.ts @@ -142,7 +142,7 @@ export default define(meta, async (ps, me) => { }); //#region Construct query - const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId) + const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .andWhere('note.userId = :userId', { userId: user.id }) .leftJoinAndSelect('note.user', 'user');