From 68686d756495ccdd1bf395e640d646dbd0570831 Mon Sep 17 00:00:00 2001 From: AkiraFukushima Date: Sun, 25 Oct 2020 19:53:45 +0900 Subject: [PATCH] refs #1804 Add posts and replies column under account timeline --- package.json | 2 +- .../SideBar/AccountProfile/Timeline.vue | 6 +- .../Timeline/PostsAndReplies.vue | 148 ++++++++++++++++++ .../Contents/SideBar/AccountProfile.ts | 3 +- .../SideBar/AccountProfile/Timeline.ts | 5 +- .../SideBar/AccountProfile/Timeline/Posts.ts | 2 +- .../Timeline/PostsAndReplies.ts | 111 +++++++++++++ yarn.lock | 8 +- 8 files changed, 275 insertions(+), 10 deletions(-) create mode 100644 src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies.vue create mode 100644 src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies.ts diff --git a/package.json b/package.json index da177e16..ece5f022 100644 --- a/package.json +++ b/package.json @@ -181,7 +181,7 @@ "emojilib": "^2.4.0", "i18next": "^19.6.3", "lodash": "^4.17.20", - "megalodon": "3.3.0", + "megalodon": "3.3.1", "moment": "^2.28.0", "mousetrap": "^1.6.5", "nedb": "^1.8.0", diff --git a/src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.vue b/src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.vue index 8115eb09..d24a2a31 100644 --- a/src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.vue +++ b/src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.vue @@ -2,7 +2,7 @@
- Posts and replies + Media
@@ -10,12 +10,14 @@ + + diff --git a/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile.ts b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile.ts index a29ae6cc..d240730b 100644 --- a/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile.ts +++ b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile.ts @@ -127,7 +127,8 @@ const actions: ActionTree = { commit(MUTATION_TYPES.CHANGE_LOADING, true) Promise.all([ dispatch('fetchRelationship', state.account), - dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/fetchTimeline', state.account, { root: true }), + dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts/fetchTimeline', state.account, { root: true }), + dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies/fetchTimeline', state.account, { root: true }), dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Followers/fetchFollowers', state.account, { root: true }), dispatch('TimelineSpace/Contents/SideBar/AccountProfile/Follows/fetchFollows', state.account, { root: true }) ]).finally(() => { diff --git a/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.ts b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.ts index 6425dc4b..052c987d 100644 --- a/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.ts +++ b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.ts @@ -2,11 +2,13 @@ import { Module } from 'vuex' import { RootState } from '@/store' import Posts, { PostsState } from './Timeline/Posts' +import PostsAndReplies, { PostsAndRepliesState } from './Timeline/PostsAndReplies' export type TimelineState = {} type TimelineModule = { Posts: PostsState + PostsAndReplies: PostsAndRepliesState } export type TimelineModuleState = TimelineModule & TimelineState @@ -16,7 +18,8 @@ const state = (): TimelineState => ({}) const Timeline: Module = { namespaced: true, modules: { - Posts + Posts, + PostsAndReplies }, state: state } diff --git a/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts.ts b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts.ts index f08f702a..e2259174 100644 --- a/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts.ts +++ b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Posts.ts @@ -91,7 +91,7 @@ const actions: ActionTree = { rootState.TimelineSpace.account.accessToken, rootState.App.userAgent ) - const pinned = await client.getAccountStatuses(account.id, { pinned: true, limit: 10 }) + const pinned = await client.getAccountStatuses(account.id, { pinned: true, limit: 10, exclude_replies: true }) commit(MUTATION_TYPES.UPDATE_PINNED_TOOTS, pinned.data) const res = await client.getAccountStatuses(account.id, { limit: 40, pinned: false }) commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false, { root: true }) diff --git a/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies.ts b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies.ts new file mode 100644 index 00000000..50659f91 --- /dev/null +++ b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/PostsAndReplies.ts @@ -0,0 +1,111 @@ +import generator, { Entity } from 'megalodon' +import { Module, MutationTree, ActionTree } from 'vuex' +import { RootState } from '@/store' +import { LoadPositionWithAccount } from '@/types/loadPosition' + +export type PostsAndRepliesState = { + timeline: Array + lazyLoading: boolean +} + +const state = (): PostsAndRepliesState => ({ + timeline: [], + lazyLoading: false +}) + +export const MUTATION_TYPES = { + UPDATE_TIMELINE: 'updateTimeline', + INSERT_TIMELINE: 'insertTimeline', + CHANGE_LAZY_LOADING: 'changeLazyLoading', + UPDATE_TOOT: 'updateToot', + DELETE_TOOT: 'deleteToot' +} + +const mutations: MutationTree = { + [MUTATION_TYPES.UPDATE_TIMELINE]: (state, timeline: Array) => { + state.timeline = timeline + }, + [MUTATION_TYPES.INSERT_TIMELINE]: (state, message: Array) => { + state.timeline = state.timeline.concat(message) + }, + [MUTATION_TYPES.CHANGE_LAZY_LOADING]: (state, value: boolean) => { + state.lazyLoading = value + }, + [MUTATION_TYPES.UPDATE_TOOT]: (state, message: Entity.Status) => { + // Replace target message in timeline + state.timeline = state.timeline.map(toot => { + if (toot.id === message.id) { + return message + } else if (toot.reblog !== null && toot.reblog.id === message.id) { + // When user reblog/favourite a reblogged toot, target message is a original toot. + // So, a message which is received now is original toot. + const reblog = { + reblog: message + } + return Object.assign(toot, reblog) + } else { + return toot + } + }) + }, + [MUTATION_TYPES.DELETE_TOOT]: (state, message: Entity.Status) => { + state.timeline = state.timeline.filter(toot => { + if (toot.reblog !== null && toot.reblog.id === message.id) { + return false + } else { + return toot.id !== message.id + } + }) + } +} + +const actions: ActionTree = { + fetchTimeline: async ({ commit, rootState }, account: Account) => { + commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true, { root: true }) + const client = generator( + rootState.TimelineSpace.sns, + rootState.TimelineSpace.account.baseURL, + rootState.TimelineSpace.account.accessToken, + rootState.App.userAgent + ) + const res = await client.getAccountStatuses(account.id, { limit: 40, pinned: false }) + commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false, { root: true }) + commit(MUTATION_TYPES.UPDATE_TIMELINE, res.data) + return res.data + }, + lazyFetchTimeline: async ({ state, commit, rootState }, loadPosition: LoadPositionWithAccount): Promise => { + if (state.lazyLoading) { + return Promise.resolve(null) + } + commit(MUTATION_TYPES.CHANGE_LAZY_LOADING, true) + const client = generator( + rootState.TimelineSpace.sns, + rootState.TimelineSpace.account.baseURL, + rootState.TimelineSpace.account.accessToken, + rootState.App.userAgent + ) + try { + const res = await client.getAccountStatuses(loadPosition.account.id, { + max_id: loadPosition.status.id, + limit: 40, + pinned: false + }) + commit(MUTATION_TYPES.INSERT_TIMELINE, res.data) + } finally { + commit(MUTATION_TYPES.CHANGE_LAZY_LOADING, false) + } + return null + }, + clearTimeline: ({ commit }) => { + commit(MUTATION_TYPES.UPDATE_TIMELINE, []) + } +} + +const PostsAndReplies: Module = { + namespaced: true, + state: state, + mutations: mutations, + actions: actions +} + +export default PostsAndReplies diff --git a/yarn.lock b/yarn.lock index 45603975..e2fb44df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8530,10 +8530,10 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -megalodon@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/megalodon/-/megalodon-3.3.0.tgz#d8b6aef2858c26196fec9bc8d8e8ee976d5e944a" - integrity sha512-YDspzWuJ6lqsxaCoEaE4bILNrK8nuk+7rDd+ythNoBcVksJ/2SFqSIeRdkIGPchc7VfKpCn1vpe8URx9FrPnuw== +megalodon@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/megalodon/-/megalodon-3.3.1.tgz#0e62c006049790269b0d6ab6ea8f6ca919b4a447" + integrity sha512-vdCW6xCc0yp47eZ8SLrTzQKACoIzd3LnYEk62NSyHUzTzpMP6N5s0BuTfBAWnSn8m6Zx1q6865rNp/tBrKTpww== dependencies: "@types/oauth" "^0.9.0" "@types/ws" "^7.2.0"