[refactor] Remove bookmarks store
This commit is contained in:
parent
2ed4e8d9e9
commit
abcea8f333
|
@ -30,10 +30,9 @@ import { useStore } from '@/store'
|
|||
import { useI18next } from 'vue3-i18next'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { Entity } from 'megalodon'
|
||||
import useReloadable from '@/components/utils/reloadable'
|
||||
import parse from 'parse-link-header'
|
||||
import generator, { Entity, MegalodonInterface } from 'megalodon'
|
||||
import Toot from '@/components/organisms/Toot.vue'
|
||||
import { ACTION_TYPES, MUTATION_TYPES } from '@/store/TimelineSpace/Contents/Bookmarks'
|
||||
import { MUTATION_TYPES as TIMELINE_MUTATION } from '@/store/TimelineSpace'
|
||||
import { MUTATION_TYPES as HEADER_MUTATION } from '@/store/TimelineSpace/HeaderMenu'
|
||||
import { LocalAccount } from '~/src/types/localAccount'
|
||||
|
@ -44,15 +43,14 @@ export default defineComponent({
|
|||
name: 'bookmarks',
|
||||
components: { Toot },
|
||||
setup() {
|
||||
const space = 'TimelineSpace/Contents/Bookmarks'
|
||||
const store = useStore()
|
||||
const route = useRoute()
|
||||
const i18n = useI18next()
|
||||
const { reloadable } = useReloadable(store, route, i18n)
|
||||
|
||||
const focusedId = ref<string | null>(null)
|
||||
const heading = ref<boolean>(true)
|
||||
const scroller = ref<any>()
|
||||
const loading = ref(false)
|
||||
const lazyLoading = ref(false)
|
||||
const { j, k, Ctrl_r } = useMagicKeys()
|
||||
|
||||
|
@ -63,12 +61,15 @@ export default defineComponent({
|
|||
account: null,
|
||||
server: null
|
||||
})
|
||||
const client = ref<MegalodonInterface | null>(null)
|
||||
|
||||
const bookmarks = computed(() => store.state.TimelineSpace.Contents.Bookmarks.bookmarks)
|
||||
const bookmarks = ref<Array<Entity.Status>>([])
|
||||
const nextMaxId = ref<string | null>(null)
|
||||
const startReload = computed(() => store.state.TimelineSpace.HeaderMenu.reload)
|
||||
const modalOpened = computed<boolean>(() => store.getters[`TimelineSpace/Modals/modalOpened`])
|
||||
const currentFocusedIndex = computed(() => bookmarks.value.findIndex(toot => focusedId.value === toot.uri))
|
||||
const shortcutEnabled = computed(() => !modalOpened.value)
|
||||
const userAgent = computed(() => store.state.App.userAgent)
|
||||
|
||||
onMounted(async () => {
|
||||
const [a, s]: [LocalAccount, LocalServer] = await win.ipcRenderer.invoke('get-local-account', id.value)
|
||||
|
@ -76,18 +77,27 @@ export default defineComponent({
|
|||
account.server = s
|
||||
|
||||
document.getElementById('scroller')?.addEventListener('scroll', onScroll)
|
||||
store.commit(`TimelineSpace/Contents/${TIMELINE_MUTATION.CHANGE_LOADING}`, true)
|
||||
store
|
||||
.dispatch(`${space}/${ACTION_TYPES.FETCH_BOOKMARKS}`, account)
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
message: i18n.t('message.bookmark_fetch_error'),
|
||||
type: 'error'
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
store.commit(`TimelineSpace/Contents/${TIMELINE_MUTATION.CHANGE_LOADING}`, false)
|
||||
|
||||
client.value = generator(s.sns, s.baseURL, a.accessToken, userAgent.value)
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await client.value.getBookmarks({ limit: 20 })
|
||||
bookmarks.value = res.data
|
||||
const link = parse(res.headers.link)
|
||||
if (link !== null && link.next) {
|
||||
nextMaxId.value = link.next.max_id
|
||||
} else {
|
||||
nextMaxId.value = null
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
ElMessage({
|
||||
message: i18n.t('message.bookmark_fetch_error'),
|
||||
type: 'error'
|
||||
})
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
watch(startReload, (newVal, oldVal) => {
|
||||
if (!oldVal && newVal) {
|
||||
|
@ -115,12 +125,23 @@ export default defineComponent({
|
|||
if (
|
||||
(event.target as HTMLElement)!.clientHeight + (event.target as HTMLElement)!.scrollTop >=
|
||||
document.getElementById('scroller')!.scrollHeight - 10 &&
|
||||
!lazyLoading.value
|
||||
!lazyLoading.value &&
|
||||
nextMaxId.value
|
||||
) {
|
||||
lazyLoading.value = true
|
||||
store
|
||||
.dispatch(`${space}/${ACTION_TYPES.LAZY_FETCH_BOOKMARKS}`, account)
|
||||
.catch(() => {
|
||||
client.value
|
||||
?.getBookmarks({ limit: 20, max_id: nextMaxId.value })
|
||||
.then(res => {
|
||||
bookmarks.value = [...bookmarks.value, ...res.data]
|
||||
const link = parse(res.headers.link)
|
||||
if (link !== null && link.next) {
|
||||
nextMaxId.value = link.next.max_id
|
||||
} else {
|
||||
nextMaxId.value = null
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err)
|
||||
ElMessage({
|
||||
message: i18n.t('message.bookmark_fetch_error'),
|
||||
type: 'error'
|
||||
|
@ -130,7 +151,7 @@ export default defineComponent({
|
|||
lazyLoading.value = false
|
||||
})
|
||||
}
|
||||
// for upper
|
||||
|
||||
if ((event.target as HTMLElement)!.scrollTop > 10 && heading.value) {
|
||||
heading.value = false
|
||||
} else if ((event.target as HTMLElement)!.scrollTop <= 10 && !heading.value) {
|
||||
|
@ -139,27 +160,40 @@ export default defineComponent({
|
|||
}
|
||||
const reload = async () => {
|
||||
store.commit(`TimelineSpace/${TIMELINE_MUTATION.CHANGE_LOADING}`, true)
|
||||
if (!client.value) return
|
||||
try {
|
||||
await reloadable()
|
||||
await store.dispatch(`${space}/${ACTION_TYPES.FETCH_BOOKMARKS}`, account).catch(() => {
|
||||
ElMessage({
|
||||
message: i18n.t('message.bookmark_fetch_error'),
|
||||
type: 'error'
|
||||
})
|
||||
})
|
||||
const res = await client.value.getBookmarks({ limit: 20 })
|
||||
bookmarks.value = res.data
|
||||
const link = parse(res.headers.link)
|
||||
if (link !== null && link.next) {
|
||||
nextMaxId.value = link.next.max_id
|
||||
} else {
|
||||
nextMaxId.value = null
|
||||
}
|
||||
} finally {
|
||||
store.commit(`TimelineSpace/${TIMELINE_MUTATION.CHANGE_LOADING}`, false)
|
||||
}
|
||||
}
|
||||
const updateToot = (message: Entity.Status) => {
|
||||
store.commit(`${space}/${MUTATION_TYPES.UPDATE_TOOT}`, message)
|
||||
bookmarks.value = bookmarks.value.map(status => {
|
||||
if (status.id === message.id) {
|
||||
return message
|
||||
} else if (status.reblog && status.reblog.id === message.id) {
|
||||
return Object.assign(status, {
|
||||
reblog: message
|
||||
})
|
||||
}
|
||||
return status
|
||||
})
|
||||
}
|
||||
const deleteToot = (message: Entity.Status) => {
|
||||
store.commit(`${space}/${MUTATION_TYPES.DELETE_TOOT}`, message)
|
||||
}
|
||||
const upper = () => {
|
||||
scroller.value.scrollToItem(0)
|
||||
focusedId.value = null
|
||||
const deleteToot = (id: string) => {
|
||||
bookmarks.value = bookmarks.value.filter(status => {
|
||||
if (status.reblog !== null && status.reblog.id === id) {
|
||||
return false
|
||||
} else {
|
||||
return status.id !== id
|
||||
}
|
||||
})
|
||||
}
|
||||
const focusNext = () => {
|
||||
if (currentFocusedIndex.value === -1) {
|
||||
|
@ -188,7 +222,6 @@ export default defineComponent({
|
|||
deleteToot,
|
||||
focusToot,
|
||||
heading,
|
||||
upper,
|
||||
account
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,10 +137,6 @@ export default defineComponent({
|
|||
store.commit(`${space}/${MUTATION_TYPES.DELETE_TOOT}`, { statusId: id, accountId: account.account.id })
|
||||
}
|
||||
}
|
||||
const upper = () => {
|
||||
scroller.value.scrollToItem(0)
|
||||
focusedId.value = null
|
||||
}
|
||||
const focusNext = () => {
|
||||
if (currentFocusedIndex.value === -1) {
|
||||
focusedId.value = timeline.value[0].uri + timeline.value[0].id
|
||||
|
@ -168,7 +164,6 @@ export default defineComponent({
|
|||
deleteToot,
|
||||
focusToot,
|
||||
heading,
|
||||
upper,
|
||||
account
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
:filters="[]"
|
||||
:account="account.account"
|
||||
:server="account.server"
|
||||
v-on:update="updateToot"
|
||||
v-on:delete="deleteToot"
|
||||
@selectToot="focusToot(item)"
|
||||
@update="updateToot"
|
||||
@delete="deleteToot"
|
||||
@select-toot="focusToot(item)"
|
||||
>
|
||||
</toot>
|
||||
</DynamicScrollerItem>
|
||||
|
@ -145,10 +145,6 @@ export default defineComponent({
|
|||
store.commit(`${space}/${MUTATION_TYPES.DELETE_TOOT}`, { statusId: message.id, accountId: account.account.id })
|
||||
}
|
||||
}
|
||||
const upper = () => {
|
||||
scroller.value.scrollToItem(0)
|
||||
focusedId.value = null
|
||||
}
|
||||
const focusNext = () => {
|
||||
if (currentFocusedIndex.value === -1) {
|
||||
focusedId.value = timeline.value[0].uri + timeline.value[0].id
|
||||
|
@ -175,8 +171,6 @@ export default defineComponent({
|
|||
updateToot,
|
||||
deleteToot,
|
||||
focusToot,
|
||||
heading,
|
||||
upper,
|
||||
account
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
:filters="filters"
|
||||
:account="account.account"
|
||||
:server="account.server"
|
||||
v-on:update="updateToot"
|
||||
@selectNotification="focusNotification(item)"
|
||||
@update="updateToot"
|
||||
@select-notification="focusNotification(item)"
|
||||
>
|
||||
</notification>
|
||||
</DynamicScrollerItem>
|
||||
|
@ -180,10 +180,7 @@ export default defineComponent({
|
|||
}, 500)
|
||||
})
|
||||
}
|
||||
const upper = () => {
|
||||
scroller.value.scrollToItem(0)
|
||||
focusedId.value = null
|
||||
}
|
||||
|
||||
const focusNext = () => {
|
||||
if (currentFocusedIndex.value === -1) {
|
||||
focusedId.value = notifications.value[0].id
|
||||
|
@ -213,9 +210,8 @@ export default defineComponent({
|
|||
focusNext,
|
||||
focusPrev,
|
||||
focusNotification,
|
||||
heading,
|
||||
upper,
|
||||
account
|
||||
account,
|
||||
scroller
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -208,7 +208,6 @@ export default defineComponent({
|
|||
updateToot,
|
||||
deleteToot,
|
||||
focusToot,
|
||||
heading,
|
||||
account,
|
||||
backgroundColor
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
import { Store } from 'vuex'
|
||||
import { RootState } from '@/store'
|
||||
import { RouteLocationNormalizedLoaded } from 'vue-router'
|
||||
import { i18n } from 'i18next'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { ACTION_TYPES } from '@/store/TimelineSpace'
|
||||
|
||||
export default function useReloadable(store: Store<RootState>, route: RouteLocationNormalizedLoaded, i18next: i18n) {
|
||||
async function reloadable() {
|
||||
const account = await store.dispatch(`TimelineSpace/${ACTION_TYPES.LOCAL_ACCOUNT}`, route.params.id).catch(err => {
|
||||
ElMessage({
|
||||
message: i18next.t<string>('message.account_load_error'),
|
||||
type: 'error'
|
||||
})
|
||||
throw err
|
||||
})
|
||||
return account
|
||||
}
|
||||
|
||||
return {
|
||||
reloadable
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
import Home, { HomeState } from './Contents/Home'
|
||||
import Notifications, { NotificationsState } from './Contents/Notifications'
|
||||
import Bookmarks, { BookmarksState } from './Contents/Bookmarks'
|
||||
import Local, { LocalState } from './Contents/Local'
|
||||
import Search, { SearchModuleState } from './Contents/Search'
|
||||
import Lists, { ListsModuleState } from './Contents/Lists'
|
||||
|
@ -17,7 +16,6 @@ type ContentsModule = {
|
|||
Home: HomeState
|
||||
Notifications: NotificationsState
|
||||
DirectMessages: DirectMessagesState
|
||||
Bookmarks: BookmarksState
|
||||
Local: LocalState
|
||||
Search: SearchModuleState
|
||||
Hashtag: HashtagModuleState
|
||||
|
@ -56,7 +54,6 @@ const Contents: Module<ContentsState, RootState> = {
|
|||
modules: {
|
||||
Home,
|
||||
Notifications,
|
||||
Bookmarks,
|
||||
Local,
|
||||
DirectMessages,
|
||||
Search,
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
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'
|
||||
import { LocalServer } from '~src/types/localServer'
|
||||
|
||||
export type BookmarksState = {
|
||||
bookmarks: Array<Entity.Status>
|
||||
maxId: string | null
|
||||
}
|
||||
|
||||
const state = (): BookmarksState => ({
|
||||
bookmarks: [],
|
||||
maxId: null
|
||||
})
|
||||
|
||||
export const MUTATION_TYPES = {
|
||||
UPDATE_BOOKMARKS: 'updateBookmarks',
|
||||
INSERT_BOOKMARKS: 'insertBookmarks',
|
||||
UPDATE_TOOT: 'updateToot',
|
||||
DELETE_TOOT: 'deleteToot',
|
||||
CHANGE_MAX_ID: 'changeMaxId'
|
||||
}
|
||||
|
||||
const mutations: MutationTree<BookmarksState> = {
|
||||
[MUTATION_TYPES.UPDATE_BOOKMARKS]: (state, bookmarks: Array<Entity.Status>) => {
|
||||
state.bookmarks = bookmarks
|
||||
},
|
||||
[MUTATION_TYPES.INSERT_BOOKMARKS]: (state, bookmarks: Array<Entity.Status>) => {
|
||||
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_MAX_ID]: (state, id: string | null) => {
|
||||
state.maxId = id
|
||||
}
|
||||
}
|
||||
|
||||
export const ACTION_TYPES = {
|
||||
FETCH_BOOKMARKS: 'fetchBookmarks',
|
||||
LAZY_FETCH_BOOKMARKS: 'lazyFetchBookmarks'
|
||||
}
|
||||
|
||||
const actions: ActionTree<BookmarksState, RootState> = {
|
||||
[ACTION_TYPES.FETCH_BOOKMARKS]: async (
|
||||
{ commit, rootState },
|
||||
req: { account: LocalAccount; server: LocalServer }
|
||||
): Promise<Array<Entity.Status>> => {
|
||||
const client = generator(req.server.sns, req.server.baseURL, req.account.accessToken, rootState.App.userAgent)
|
||||
const res = await client.getBookmarks({ limit: 20 })
|
||||
commit(MUTATION_TYPES.UPDATE_BOOKMARKS, res.data)
|
||||
// Parse link header
|
||||
try {
|
||||
const link = parse(res.headers.link)
|
||||
if (link !== null && link.next) {
|
||||
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
|
||||
},
|
||||
[ACTION_TYPES.LAZY_FETCH_BOOKMARKS]: async (
|
||||
{ state, commit, rootState },
|
||||
req: { account: LocalAccount; server: LocalServer }
|
||||
): Promise<Array<Entity.Status> | null> => {
|
||||
if (!state.maxId) {
|
||||
return Promise.resolve(null)
|
||||
}
|
||||
const client = generator(req.server.sns, req.server.baseURL, req.account.accessToken, rootState.App.userAgent)
|
||||
const res = await client.getFavourites({ max_id: state.maxId, limit: 20 })
|
||||
commit(MUTATION_TYPES.INSERT_BOOKMARKS, res.data)
|
||||
// Parse link header
|
||||
try {
|
||||
const link = parse(res.headers.link)
|
||||
if (link !== null && link.next) {
|
||||
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<BookmarksState, RootState> = {
|
||||
namespaced: true,
|
||||
state: state,
|
||||
mutations: mutations,
|
||||
actions: actions
|
||||
}
|
||||
|
||||
export default Bookmark
|
Loading…
Reference in New Issue