diff --git a/package-lock.json b/package-lock.json index 6dab7ad2..1b749bcd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2022,6 +2022,12 @@ "@types/node": "11.11.4" } }, + "@types/parse-link-header": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-link-header/-/parse-link-header-1.0.0.tgz", + "integrity": "sha512-fCA3btjE7QFeRLfcD0Sjg+6/CnmC66HpMBoRfRzd2raTaWMJV21CCZ0LO8MOqf8onl5n0EPfjq4zDhbyX8SVwA==", + "dev": true + }, "@types/request": { "version": "2.48.1", "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.1.tgz", diff --git a/package.json b/package.json index 2865afcc..ca435331 100644 --- a/package.json +++ b/package.json @@ -175,6 +175,7 @@ "@types/jest": "^24.0.11", "@types/lodash": "^4.14.123", "@types/node": "^11.11.4", + "@types/parse-link-header": "^1.0.0", "@typescript-eslint/eslint-plugin": "^1.5.0", "@typescript-eslint/parser": "^1.5.0", "@typescript-eslint/typescript-estree": "^1.5.0", diff --git a/src/renderer/store/TimelineSpace/Contents.ts b/src/renderer/store/TimelineSpace/Contents.ts index b4ab4153..3c11a8a8 100644 --- a/src/renderer/store/TimelineSpace/Contents.ts +++ b/src/renderer/store/TimelineSpace/Contents.ts @@ -1,7 +1,7 @@ import SideBar, { SideBarModuleState } from './Contents/SideBar' import Home, { HomeState } from './Contents/Home' import Notifications, { NotificationsState } from './Contents/Notifications' -import Favourites from './Contents/Favourites' +import Favourites, { FavouritesState } from './Contents/Favourites' import Local, { LocalState } from './Contents/Local' import Public, { PublicState } from './Contents/Public' import Search, { SearchModuleState } from './Contents/Search' @@ -20,6 +20,7 @@ export interface ContentsModuleState extends ContentsState { Notifications: NotificationsState, Mentions: MentionsState, DirectMessages: DirectMessagesState, + Favourites: FavouritesState, Local: LocalState, Public: PublicState, Search: SearchModuleState, diff --git a/src/renderer/store/TimelineSpace/Contents/Favourites.js b/src/renderer/store/TimelineSpace/Contents/Favourites.js deleted file mode 100644 index b8db3c2f..00000000 --- a/src/renderer/store/TimelineSpace/Contents/Favourites.js +++ /dev/null @@ -1,102 +0,0 @@ -import Mastodon from 'megalodon' -import parse from 'parse-link-header' - -const Favourites = { - namespaced: true, - state: { - favourites: [], - lazyLoading: false, - filter: '', - maxId: null - }, - mutations: { - updateFavourites (state, favourites) { - state.favourites = favourites - }, - insertFavourites (state, favourites) { - state.favourites = state.favourites.concat(favourites) - }, - updateToot (state, message) { - state.favourites = state.favourites.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 - } - }) - }, - deleteToot (state, message) { - state.timeline = state.timeline.filter((toot) => { - if (toot.reblog !== null && toot.reblog.id === message.id) { - return false - } else { - return toot.id !== message.id - } - }) - }, - changeLazyLoading (state, value) { - state.lazyLoading = value - }, - changeFilter (state, filter) { - state.filter = filter - }, - changeMaxId (state, id) { - state.maxId = id - } - }, - actions: { - async fetchFavourites ({ commit }, account) { - const client = new Mastodon( - account.accessToken, - account.baseURL + '/api/v1' - ) - const res = await client.get('/favourites', { limit: 40 }) - commit('updateFavourites', res.data) - // Parse link header - try { - const link = parse(res.headers.link) - commit('changeMaxId', link.next.max_id) - } catch (err) { - commit('changeMaxId', null) - console.error(err) - } - return res.data - }, - async lazyFetchFavourites ({ state, commit, rootState }) { - if (state.lazyLoading) { - return Promise.resolve(null) - } - if (!state.maxId) { - return null - } - commit('changeLazyLoading', true) - const client = new Mastodon( - rootState.TimelineSpace.account.accessToken, - rootState.TimelineSpace.account.baseURL + '/api/v1' - ) - const res = await client.get('/favourites', { max_id: state.maxId, limit: 40 }) - .finally(() => { - commit('changeLazyLoading', false) - }) - commit('insertFavourites', res.data) - // Parse link header - try { - const link = parse(res.headers.link) - commit('changeMaxId', link.next.max_id) - } catch (err) { - commit('changeMaxId', null) - console.error(err) - } - return res.data - } - } -} - -export default Favourites diff --git a/src/renderer/store/TimelineSpace/Contents/Favourites.ts b/src/renderer/store/TimelineSpace/Contents/Favourites.ts new file mode 100644 index 00000000..15695803 --- /dev/null +++ b/src/renderer/store/TimelineSpace/Contents/Favourites.ts @@ -0,0 +1,136 @@ +import Mastodon, { Status, Response } from 'megalodon' +import parse from 'parse-link-header' +import { Module, MutationTree, ActionTree } from 'vuex' +import { RootState } from '@/store' +import AccountType from '~/src/types/account' + +export interface FavouritesState { + favourites: Array, + lazyLoading: boolean, + filter: string, + maxId: number | null +} + +const state = (): FavouritesState => ({ + favourites: [], + lazyLoading: false, + filter: '', + maxId: null +}) + +export const MUTATION_TYPES = { + UPDATE_FAVOURITES: 'updateFavourites', + INSERT_FAVOURITES: 'insertFavourites', + UPDATE_TOOT: 'updateToot', + DELETE_TOOT: 'deleteToot', + CHANGE_LAZY_LOADING: 'changeLazyLoading', + CHANGE_FILTER: 'changeFilter', + CHANGE_MAX_ID: 'changeMaxId' +} + +const mutations: MutationTree = { + [MUTATION_TYPES.UPDATE_FAVOURITES]: (state, favourites: Array) => { + state.favourites = favourites + }, + [MUTATION_TYPES.INSERT_FAVOURITES]: (state, favourites: Array) => { + state.favourites = state.favourites.concat(favourites) + }, + [MUTATION_TYPES.UPDATE_TOOT]: (state, message: Status) => { + state.favourites = state.favourites.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: Status) => { + state.favourites = state.favourites.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_FILTER]: (state, filter: string) => { + state.filter = filter + }, + [MUTATION_TYPES.CHANGE_MAX_ID]: (state, id: number | null) => { + state.maxId = id + } +} + +const actions: ActionTree = { + fetchFavourites: async ({ commit }, account: AccountType): Promise> => { + const client = new Mastodon( + account.accessToken!, + account.baseURL + '/api/v1' + ) + const res: Response> = await client.get>('/favourites', { limit: 40 }) + commit(MUTATION_TYPES.UPDATE_FAVOURITES, res.data) + // Parse link header + try { + const link = parse(res.headers.link) + if (link !== null) { + commit(MUTATION_TYPES.CHANGE_MAX_ID, parseInt(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 + }, + lazyFetchFavourites: 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 = new Mastodon( + rootState.TimelineSpace.account.accessToken!, + rootState.TimelineSpace.account.baseURL + '/api/v1' + ) + const res: Response> = await client.get>('/favourites', { max_id: state.maxId, limit: 40 }) + .finally(() => { + commit(MUTATION_TYPES.CHANGE_LAZY_LOADING, false) + }) + commit(MUTATION_TYPES.INSERT_FAVOURITES, res.data) + // Parse link header + try { + const link = parse(res.headers.link) + if (link !== null) { + commit(MUTATION_TYPES.CHANGE_MAX_ID, parseInt(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 Favourites: Module = { + namespaced: true, + state: state, + mutations: mutations, + actions: actions +} + +export default Favourites