From dc6f3664cb3d7a94eac817a6017e5fb67660f889 Mon Sep 17 00:00:00 2001 From: AkiraFukushima Date: Tue, 27 Oct 2020 13:37:39 +0900 Subject: [PATCH] refs #1804 Add media column under account timeline --- package.json | 2 +- .../SideBar/AccountProfile/Timeline.vue | 6 +- .../SideBar/AccountProfile/Timeline/Media.vue | 146 ++++++++++++++++++ .../Contents/SideBar/AccountProfile.ts | 1 + .../SideBar/AccountProfile/Timeline.ts | 5 +- .../SideBar/AccountProfile/Timeline/Media.ts | 112 ++++++++++++++ yarn.lock | 17 +- 7 files changed, 280 insertions(+), 9 deletions(-) create mode 100644 src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media.vue create mode 100644 src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media.ts diff --git a/package.json b/package.json index ece5f022..6459d908 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.1", + "megalodon": "3.3.2", "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 d24a2a31..71772661 100644 --- a/src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.vue +++ b/src/renderer/components/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.vue @@ -3,7 +3,7 @@ - Media + @@ -11,13 +11,15 @@ + + diff --git a/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile.ts b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile.ts index d240730b..ed9c9037 100644 --- a/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile.ts +++ b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile.ts @@ -129,6 +129,7 @@ const actions: ActionTree = { dispatch('fetchRelationship', state.account), 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/Timeline/Media/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 052c987d..f0407f05 100644 --- a/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.ts +++ b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline.ts @@ -3,12 +3,14 @@ import { RootState } from '@/store' import Posts, { PostsState } from './Timeline/Posts' import PostsAndReplies, { PostsAndRepliesState } from './Timeline/PostsAndReplies' +import Media, { MediaState } from './Timeline/Media' export type TimelineState = {} type TimelineModule = { Posts: PostsState PostsAndReplies: PostsAndRepliesState + Media: MediaState } export type TimelineModuleState = TimelineModule & TimelineState @@ -19,7 +21,8 @@ const Timeline: Module = { namespaced: true, modules: { Posts, - PostsAndReplies + PostsAndReplies, + Media }, state: state } diff --git a/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media.ts b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media.ts new file mode 100644 index 00000000..a69b9332 --- /dev/null +++ b/src/renderer/store/TimelineSpace/Contents/SideBar/AccountProfile/Timeline/Media.ts @@ -0,0 +1,112 @@ +import { RootState } from '@/store' +import generator, { Entity } from 'megalodon' +import { Module, MutationTree, ActionTree } from 'vuex' +import { LoadPositionWithAccount } from '@/types/loadPosition' + +export type MediaState = { + timeline: Array + lazyLoading: boolean +} + +const state = (): MediaState => ({ + 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, only_media: true }) + 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, + only_media: true + }) + 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 Media: Module = { + namespaced: true, + state: state, + mutations: mutations, + actions: actions +} + +export default Media diff --git a/yarn.lock b/yarn.lock index e2fb44df..712e9df6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2297,6 +2297,13 @@ axios@^0.20.0: dependencies: follow-redirects "^1.10.0" +axios@^0.21.0: + version "0.21.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.0.tgz#26df088803a2350dff2c27f96fef99fe49442aca" + integrity sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw== + dependencies: + follow-redirects "^1.10.0" + babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -8530,14 +8537,14 @@ 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.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/megalodon/-/megalodon-3.3.1.tgz#0e62c006049790269b0d6ab6ea8f6ca919b4a447" - integrity sha512-vdCW6xCc0yp47eZ8SLrTzQKACoIzd3LnYEk62NSyHUzTzpMP6N5s0BuTfBAWnSn8m6Zx1q6865rNp/tBrKTpww== +megalodon@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/megalodon/-/megalodon-3.3.2.tgz#20737f47589feb8209f8129a921c3308be10d7b0" + integrity sha512-lmqkwEL4Yrb459gL2SUM7mFpdzZDxmXMG8xb7RWNeo93OuVY+jukqI8mZI/g4v4WoVHYfSaVlB7Tqm0DwuqXIw== dependencies: "@types/oauth" "^0.9.0" "@types/ws" "^7.2.0" - axios "^0.20.0" + axios "^0.21.0" https-proxy-agent "^5.0.0" moment "^2.24.0" oauth "^0.9.15"