From bd4bb90870fc3c49f19efa3f93a476b974f432d9 Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Mon, 24 Aug 2020 19:33:55 +0900
Subject: [PATCH] refs #1714 Create bookmarks timeline
---
src/config/locales/en/translation.json | 1 +
.../TimelineSpace/Contents/Bookmarks.vue | 213 ++++++++++++++++++
.../components/TimelineSpace/HeaderMenu.vue | 7 +-
src/renderer/router/index.ts | 6 +
src/renderer/store/TimelineSpace/Contents.ts | 3 +
.../store/TimelineSpace/Contents/Bookmarks.ts | 128 +++++++++++
6 files changed, 357 insertions(+), 1 deletion(-)
create mode 100644 src/renderer/components/TimelineSpace/Contents/Bookmarks.vue
create mode 100644 src/renderer/store/TimelineSpace/Contents/Bookmarks.ts
diff --git a/src/config/locales/en/translation.json b/src/config/locales/en/translation.json
index 1da900c7..cd3c0ee8 100644
--- a/src/config/locales/en/translation.json
+++ b/src/config/locales/en/translation.json
@@ -65,6 +65,7 @@
"notification": "Notification",
"mention": "Mention",
"favourite": "Favourite",
+ "bookmark": "Bookmark",
"follow_requests": "Follow Requests",
"direct_messages": "Direct Messages",
"local": "Local timeline",
diff --git a/src/renderer/components/TimelineSpace/Contents/Bookmarks.vue b/src/renderer/components/TimelineSpace/Contents/Bookmarks.vue
new file mode 100644
index 00000000..399e4945
--- /dev/null
+++ b/src/renderer/components/TimelineSpace/Contents/Bookmarks.vue
@@ -0,0 +1,213 @@
+
+
+
+
+
+
+
diff --git a/src/renderer/components/TimelineSpace/HeaderMenu.vue b/src/renderer/components/TimelineSpace/HeaderMenu.vue
index 71c4e266..9b39f08e 100644
--- a/src/renderer/components/TimelineSpace/HeaderMenu.vue
+++ b/src/renderer/components/TimelineSpace/HeaderMenu.vue
@@ -74,7 +74,7 @@ export default {
this.$store.dispatch('TimelineSpace/HeaderMenu/setupLoading')
},
watch: {
- $route: function() {
+ $route: function () {
this.channelName()
this.loadFilter()
}
@@ -94,6 +94,9 @@ export default {
case 'favourites':
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.favourite'))
break
+ case 'bookmarks':
+ this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.bookmark'))
+ break
case 'mentions':
this.$store.commit('TimelineSpace/HeaderMenu/updateTitle', this.$t('header_menu.mention'))
break
@@ -142,6 +145,7 @@ export default {
case 'notifications':
case 'mentions':
case 'favourites':
+ case 'bookmarks':
case 'local':
case 'public':
case 'tag':
@@ -159,6 +163,7 @@ export default {
case 'notifications':
case 'mentions':
case 'favourites':
+ case 'bookmarks':
case 'local':
case 'public':
case 'tag':
diff --git a/src/renderer/router/index.ts b/src/renderer/router/index.ts
index 0a278c72..0b15b505 100644
--- a/src/renderer/router/index.ts
+++ b/src/renderer/router/index.ts
@@ -30,6 +30,7 @@ import TimelineSpaceContentsListsIndex from '@/components/TimelineSpace/Contents
import TimelineSpaceContentsListsEdit from '@/components/TimelineSpace/Contents/Lists/Edit.vue'
import TimelineSpaceContentsListsShow from '@/components/TimelineSpace/Contents/Lists/Show.vue'
import TimelineSpaceContentsFollowRequests from '@/components/TimelineSpace/Contents/FollowRequests.vue'
+import TimelineSpaceContentsBookmarks from '@/components/TimelineSpace/Contents/Bookmarks.vue'
Vue.use(Router)
@@ -132,6 +133,11 @@ const router = new Router({
name: 'favourites',
component: TimelineSpaceContentsFavourites
},
+ {
+ path: 'bookmarks',
+ name: 'bookmarks',
+ component: TimelineSpaceContentsBookmarks
+ },
{
path: 'local',
name: 'local',
diff --git a/src/renderer/store/TimelineSpace/Contents.ts b/src/renderer/store/TimelineSpace/Contents.ts
index 3d44456d..e461051e 100644
--- a/src/renderer/store/TimelineSpace/Contents.ts
+++ b/src/renderer/store/TimelineSpace/Contents.ts
@@ -2,6 +2,7 @@ import SideBar, { SideBarModuleState } from './Contents/SideBar'
import Home, { HomeState } from './Contents/Home'
import Notifications, { NotificationsState } from './Contents/Notifications'
import Favourites, { FavouritesState } from './Contents/Favourites'
+import Bookmarks, { BookmarksState } from './Contents/Bookmarks'
import Local, { LocalState } from './Contents/Local'
import Public, { PublicState } from './Contents/Public'
import Search, { SearchModuleState } from './Contents/Search'
@@ -24,6 +25,7 @@ type ContentsModule = {
Mentions: MentionsState
DirectMessages: DirectMessagesState
Favourites: FavouritesState
+ Bookmarks: BookmarksState
Local: LocalState
Public: PublicState
Search: SearchModuleState
@@ -61,6 +63,7 @@ const Contents: Module = {
Home,
Notifications,
Favourites,
+ Bookmarks,
Local,
DirectMessages,
Mentions,
diff --git a/src/renderer/store/TimelineSpace/Contents/Bookmarks.ts b/src/renderer/store/TimelineSpace/Contents/Bookmarks.ts
new file mode 100644
index 00000000..f16edc4f
--- /dev/null
+++ b/src/renderer/store/TimelineSpace/Contents/Bookmarks.ts
@@ -0,0 +1,128 @@
+import generator, { Entity } from 'megalodon'
+import parse from 'parse-link-header'
+import { Module, MutationTree, ActionTree } from 'vuex'
+import { RootState } from '@/store'
+import { LocalAccount } from '~/src/types/localAccount'
+
+export type BookmarksState = {
+ bookmarks: Array
+ lazyLoading: boolean
+ maxId: string | null
+}
+
+const state = (): BookmarksState => ({
+ bookmarks: [],
+ lazyLoading: false,
+ maxId: null
+})
+
+export const MUTATION_TYPES = {
+ UPDATE_BOOKMARKS: 'updateBookmarks',
+ INSERT_BOOKMARKS: 'insertBookmarks',
+ UPDATE_TOOT: 'updateToot',
+ DELETE_TOOT: 'deleteToot',
+ CHANGE_LAZY_LOADING: 'changeLazyLoading',
+ CHANGE_MAX_ID: 'changeMaxId'
+}
+
+const mutations: MutationTree = {
+ [MUTATION_TYPES.UPDATE_BOOKMARKS]: (state, bookmarks: Array) => {
+ state.bookmarks = bookmarks
+ },
+ [MUTATION_TYPES.INSERT_BOOKMARKS]: (state, bookmarks: Array) => {
+ state.bookmarks = state.bookmarks.concat(bookmarks)
+ },
+ [MUTATION_TYPES.UPDATE_TOOT]: (state, message: Entity.Status) => {
+ state.bookmarks = state.bookmarks.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.bookmarks = state.bookmarks.filter(toot => {
+ if (toot.reblog !== null && toot.reblog.id === message.id) {
+ return false
+ } else {
+ return toot.id !== message.id
+ }
+ })
+ },
+ [MUTATION_TYPES.CHANGE_LAZY_LOADING]: (state, value: boolean) => {
+ state.lazyLoading = value
+ },
+ [MUTATION_TYPES.CHANGE_MAX_ID]: (state, id: string | null) => {
+ state.maxId = id
+ }
+}
+
+const actions: ActionTree = {
+ fetchBookmarks: async ({ commit, rootState }, account: LocalAccount): Promise> => {
+ const client = generator(rootState.TimelineSpace.sns, account.baseURL, account.accessToken, rootState.App.userAgent)
+ const res = await client.getBookmarks({ limit: 40 })
+ commit(MUTATION_TYPES.UPDATE_BOOKMARKS, res.data)
+ // Parse link header
+ try {
+ const link = parse(res.headers.link)
+ if (link !== null) {
+ commit(MUTATION_TYPES.CHANGE_MAX_ID, link.next.max_id)
+ } else {
+ commit(MUTATION_TYPES.CHANGE_MAX_ID, null)
+ }
+ } catch (err) {
+ commit(MUTATION_TYPES.CHANGE_MAX_ID, null)
+ console.error(err)
+ }
+ return res.data
+ },
+ laxyFetchBookmarks: async ({ state, commit, rootState }): Promise | null> => {
+ if (state.lazyLoading) {
+ return Promise.resolve(null)
+ }
+ if (!state.maxId) {
+ 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
+ )
+ const res = await client.getFavourites({ max_id: state.maxId, limit: 40 }).finally(() => {
+ commit(MUTATION_TYPES.CHANGE_LAZY_LOADING, false)
+ })
+ commit(MUTATION_TYPES.INSERT_BOOKMARKS, res.data)
+ // Parse link header
+ try {
+ const link = parse(res.headers.link)
+ if (link !== null) {
+ commit(MUTATION_TYPES.CHANGE_MAX_ID, link.next.max_id)
+ } else {
+ commit(MUTATION_TYPES.CHANGE_MAX_ID, null)
+ }
+ } catch (err) {
+ commit(MUTATION_TYPES.CHANGE_MAX_ID, null)
+ console.error(err)
+ }
+ return res.data
+ }
+}
+
+const Bookmark: Module = {
+ namespaced: true,
+ state: state,
+ mutations: mutations,
+ actions: actions
+}
+
+export default Bookmark