refs #630 Handle delete event for user streaming

This commit is contained in:
AkiraFukushima 2019-05-29 23:32:16 +09:00
parent 8731f5f24b
commit cfb69f4d2e
8 changed files with 400 additions and 98 deletions

View File

@ -277,7 +277,7 @@ describe('TimelineSpace/Contents/Home', () => {
} }
}) })
it('should be deleted', () => { it('should be deleted', () => {
Home.mutations![MUTATION_TYPES.DELETE_TOOT](state, status1) Home.mutations![MUTATION_TYPES.DELETE_TOOT](state, status1.id)
expect(state.timeline).toEqual([status2]) expect(state.timeline).toEqual([status2])
}) })
}) })
@ -325,7 +325,7 @@ describe('TimelineSpace/Contents/Home', () => {
} }
}) })
it('should be deleted', () => { it('should be deleted', () => {
Home.mutations![MUTATION_TYPES.DELETE_TOOT](state, status1) Home.mutations![MUTATION_TYPES.DELETE_TOOT](state, status1.id)
expect(state.timeline).toEqual([status2]) expect(state.timeline).toEqual([status2])
}) })
}) })

View File

@ -45,7 +45,7 @@ const account2: Account = {
bot: false bot: false
} }
const status: Status = { const status1: Status = {
id: '1', id: '1',
uri: 'http://example.com', uri: 'http://example.com',
url: 'http://example.com', url: 'http://example.com',
@ -76,19 +76,81 @@ const status: Status = {
pinned: null pinned: null
} }
const status2: Status = {
id: '2',
uri: 'http://example.com',
url: 'http://example.com',
account: account1,
in_reply_to_id: null,
in_reply_to_account_id: null,
reblog: null,
content: 'hoge',
created_at: '2019-03-26T21:40:32',
emojis: [],
replies_count: 0,
reblogs_count: 0,
favourites_count: 0,
reblogged: null,
favourited: null,
muted: null,
sensitive: false,
spoiler_text: '',
visibility: 'public',
media_attachments: [],
mentions: [],
tags: [],
card: null,
application: {
name: 'Web'
} as Application,
language: null,
pinned: null
}
const rebloggedStatus: Status = {
id: '3',
uri: 'http://example.com',
url: 'http://example.com',
account: account1,
in_reply_to_id: null,
in_reply_to_account_id: null,
reblog: status2,
content: 'hoge',
created_at: '2019-03-26T21:40:32',
emojis: [],
replies_count: 0,
reblogs_count: 0,
favourites_count: 0,
reblogged: null,
favourited: null,
muted: null,
sensitive: false,
spoiler_text: '',
visibility: 'public',
media_attachments: [],
mentions: [],
tags: [],
card: null,
application: {
name: 'Web'
} as Application,
language: null,
pinned: null
}
const notification1: Notification = { const notification1: Notification = {
id: '1', id: '1',
account: account2, account: account2,
status: status, status: status1,
type: 'favourite', type: 'mention',
created_at: '2019-04-01T17:01:32' created_at: '2019-04-01T17:01:32'
} }
const notification2: Notification = { const notification2: Notification = {
id: '2', id: '2',
account: account2, account: account2,
status: status, status: rebloggedStatus,
type: 'reblog', type: 'mention',
created_at: '2019-04-01T17:01:32' created_at: '2019-04-01T17:01:32'
} }
@ -184,13 +246,46 @@ describe('TimelineSpace/Contents/Mentions', () => {
} }
}) })
it('should be updated', () => { it('should be updated', () => {
const favourited: Status = Object.assign(status, { const favourited: Status = Object.assign(status1, {
favourited: true favourited: true
}) })
Mentions.mutations![MUTATION_TYPES.UPDATE_TOOT](state, favourited) Mentions.mutations![MUTATION_TYPES.UPDATE_TOOT](state, favourited)
expect(state.mentions[0].status!.favourited).toEqual(true) expect(state.mentions[0].status!.favourited).toEqual(null)
expect(state.mentions[1].status!.favourited).toEqual(true) expect(state.mentions[1].status!.favourited).toEqual(true)
}) })
}) })
describe('deleteToot', () => {
describe('message is not reblogged', () => {
beforeEach(() => {
state = {
lazyLoading: false,
heading: true,
mentions: [notification2, notification1],
unreadMentions: [],
filter: ''
}
})
it('should be deleted', () => {
Mentions.mutations![MUTATION_TYPES.DELETE_TOOT](state, notification1.status!.id)
expect(state.mentions.length).toEqual(1)
})
})
describe('message is reblogged', () => {
beforeEach(() => {
state = {
lazyLoading: false,
heading: true,
mentions: [notification2, notification1],
unreadMentions: [],
filter: ''
}
})
it('should be deleted', () => {
Mentions.mutations![MUTATION_TYPES.DELETE_TOOT](state, notification2.status!.id)
expect(state.mentions.length).toEqual(1)
})
})
})
}) })
}) })

View File

@ -0,0 +1,185 @@
import { Account, Notification, Status, Application } from 'megalodon'
import Notifications, { NotificationsState, MUTATION_TYPES } from '@/store/TimelineSpace/Contents/Notifications'
const account1: Account = {
id: '1',
username: 'h3poteto',
acct: 'h3poteto@pleroma.io',
display_name: 'h3poteto',
locked: false,
created_at: '2019-03-26T21:30:32',
followers_count: 10,
following_count: 10,
statuses_count: 100,
note: 'engineer',
url: 'https://pleroma.io',
avatar: '',
avatar_static: '',
header: '',
header_static: '',
emojis: [],
moved: null,
fields: null,
bot: false
}
const account2: Account = {
id: '2',
username: 'h3poteto',
acct: 'h3poteto@mstdn.io',
display_name: 'h3poteto',
locked: false,
created_at: '2019-03-26T21:30:32',
followers_count: 10,
following_count: 10,
statuses_count: 100,
note: 'engineer',
url: 'https://mstdn.io',
avatar: '',
avatar_static: '',
header: '',
header_static: '',
emojis: [],
moved: null,
fields: null,
bot: false
}
const status1: Status = {
id: '1',
uri: 'http://example.com',
url: 'http://example.com',
account: account1,
in_reply_to_id: null,
in_reply_to_account_id: null,
reblog: null,
content: 'hoge',
created_at: '2019-03-26T21:40:32',
emojis: [],
replies_count: 0,
reblogs_count: 0,
favourites_count: 0,
reblogged: null,
favourited: null,
muted: null,
sensitive: false,
spoiler_text: '',
visibility: 'public',
media_attachments: [],
mentions: [],
tags: [],
card: null,
application: {
name: 'Web'
} as Application,
language: null,
pinned: null
}
const status2: Status = {
id: '2',
uri: 'http://example.com',
url: 'http://example.com',
account: account1,
in_reply_to_id: null,
in_reply_to_account_id: null,
reblog: null,
content: 'hoge',
created_at: '2019-03-26T21:40:32',
emojis: [],
replies_count: 0,
reblogs_count: 0,
favourites_count: 0,
reblogged: null,
favourited: null,
muted: null,
sensitive: false,
spoiler_text: '',
visibility: 'public',
media_attachments: [],
mentions: [],
tags: [],
card: null,
application: {
name: 'Web'
} as Application,
language: null,
pinned: null
}
const rebloggedStatus: Status = {
id: '3',
uri: 'http://example.com',
url: 'http://example.com',
account: account1,
in_reply_to_id: null,
in_reply_to_account_id: null,
reblog: status2,
content: 'hoge',
created_at: '2019-03-26T21:40:32',
emojis: [],
replies_count: 0,
reblogs_count: 0,
favourites_count: 0,
reblogged: null,
favourited: null,
muted: null,
sensitive: false,
spoiler_text: '',
visibility: 'public',
media_attachments: [],
mentions: [],
tags: [],
card: null,
application: {
name: 'Web'
} as Application,
language: null,
pinned: null
}
const notification1: Notification = {
id: '1',
account: account2,
status: status1,
type: 'favourite',
created_at: '2019-04-01T17:01:32'
}
const notification2: Notification = {
id: '2',
account: account2,
status: rebloggedStatus,
type: 'mention',
created_at: '2019-04-01T17:01:32'
}
describe('TimelineSpace/Contents/Notifications', () => {
describe('mutations', () => {
let state: NotificationsState
describe('deleteToot', () => {
beforeEach(() => {
state = {
lazyLoading: false,
heading: true,
notifications: [notification2, notification1],
unreadNotifications: [],
filter: ''
}
})
describe('message is not reblogged', () => {
it('should be deleted', () => {
Notifications.mutations![MUTATION_TYPES.DELETE_TOOT](state, notification1.status!.id)
expect(state.notifications.length).toEqual(1)
})
})
describe('message is reblogged', () => {
it('should be deleted', () => {
Notifications.mutations![MUTATION_TYPES.DELETE_TOOT](state, notification2.status!.id)
expect(state.notifications.length).toEqual(1)
})
})
})
})
})

View File

@ -1,32 +1,29 @@
<template> <template>
<div id="home" v-shortkey="shortcutEnabled ? {next: ['j']} : {}" @shortkey="handleKey"> <div id="home" v-shortkey="shortcutEnabled ? { next: ['j'] } : {}" @shortkey="handleKey">
<div class="unread">{{ unread.length > 0 ? unread.length : '' }}</div> <div class="unread">{{ unread.length > 0 ? unread.length : '' }}</div>
<div v-shortkey="{linux: ['ctrl', 'r'], mac: ['meta', 'r']}" @shortkey="reload()"> <div v-shortkey="{ linux: ['ctrl', 'r'], mac: ['meta', 'r'] }" @shortkey="reload()"></div>
</div> <transition-group name="timeline" tag="div">
<transition-group name="timeline" tag="div"> <div class="home-timeline" v-for="message in filteredTimeline" :key="message.uri + message.id">
<div class="home-timeline" v-for="message in filteredTimeline" :key="message.uri + message.id"> <toot
<toot :message="message"
:message="message" :filter="filter"
:filter="filter" :focused="message.uri + message.id === focusedId"
:focused="message.uri + message.id === focusedId" :overlaid="modalOpened"
:overlaid="modalOpened" v-on:update="updateToot"
v-on:update="updateToot" v-on:delete="deleteToot"
v-on:delete="deleteToot" @focusNext="focusNext"
@focusNext="focusNext" @focusPrev="focusPrev"
@focusPrev="focusPrev" @focusRight="focusSidebar"
@focusRight="focusSidebar" @selectToot="focusToot(message)"
@selectToot="focusToot(message)"
> >
</toot> </toot>
</div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor"></div>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle> </el-button>
</div> </div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div> </div>
<div :class="openSideBar ? 'upper-with-side-bar' : 'upper'" v-show="!heading">
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle>
</el-button>
</div>
</div>
</template> </template>
<script> <script>
@ -40,7 +37,7 @@ export default {
name: 'home', name: 'home',
components: { Toot }, components: { Toot },
mixins: [reloadable], mixins: [reloadable],
data () { data() {
return { return {
focusedId: null focusedId: null
} }
@ -58,10 +55,8 @@ export default {
showReblogs: state => state.TimelineSpace.Contents.Home.showReblogs, showReblogs: state => state.TimelineSpace.Contents.Home.showReblogs,
showReplies: state => state.TimelineSpace.Contents.Home.showReplies showReplies: state => state.TimelineSpace.Contents.Home.showReplies
}), }),
...mapGetters('TimelineSpace/Modals', [ ...mapGetters('TimelineSpace/Modals', ['modalOpened']),
'modalOpened' shortcutEnabled: function() {
]),
shortcutEnabled: function () {
if (this.modalOpened) { if (this.modalOpened) {
return false return false
} }
@ -72,8 +67,8 @@ export default {
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id) const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
return currentIndex === -1 return currentIndex === -1
}, },
filteredTimeline () { filteredTimeline() {
return this.timeline.filter((toot) => { return this.timeline.filter(toot => {
if (toot.in_reply_to_id) { if (toot.in_reply_to_id) {
return this.showReplies return this.showReplies
} else if (toot.reblog) { } else if (toot.reblog) {
@ -84,27 +79,27 @@ export default {
}) })
} }
}, },
mounted () { mounted() {
this.$store.commit('TimelineSpace/SideMenu/changeUnreadHomeTimeline', false) this.$store.commit('TimelineSpace/SideMenu/changeUnreadHomeTimeline', false)
document.getElementById('scrollable').addEventListener('scroll', this.onScroll) document.getElementById('scrollable').addEventListener('scroll', this.onScroll)
Event.$on('focus-timeline', () => { Event.$on('focus-timeline', () => {
// If focusedId does not change, we have to refresh focusedId because Toot component watch change events. // If focusedId does not change, we have to refresh focusedId because Toot component watch change events.
const previousFocusedId = this.focusedId const previousFocusedId = this.focusedId
this.focusedId = 0 this.focusedId = 0
this.$nextTick(function () { this.$nextTick(function() {
this.focusedId = previousFocusedId this.focusedId = previousFocusedId
}) })
}) })
}, },
beforeUpdate () { beforeUpdate() {
if (this.$store.state.TimelineSpace.SideMenu.unreadHomeTimeline && this.heading) { if (this.$store.state.TimelineSpace.SideMenu.unreadHomeTimeline && this.heading) {
this.$store.commit('TimelineSpace/SideMenu/changeUnreadHomeTimeline', false) this.$store.commit('TimelineSpace/SideMenu/changeUnreadHomeTimeline', false)
} }
}, },
beforeDestroy () { beforeDestroy() {
Event.$off('focus-timeline') Event.$off('focus-timeline')
}, },
destroyed () { destroyed() {
this.$store.commit('TimelineSpace/Contents/Home/changeHeading', true) this.$store.commit('TimelineSpace/Contents/Home/changeHeading', true)
this.$store.commit('TimelineSpace/Contents/Home/mergeTimeline') this.$store.commit('TimelineSpace/Contents/Home/mergeTimeline')
this.$store.commit('TimelineSpace/Contents/Home/archiveTimeline') this.$store.commit('TimelineSpace/Contents/Home/archiveTimeline')
@ -114,15 +109,14 @@ export default {
} }
}, },
watch: { watch: {
startReload: function (newState, oldState) { startReload: function(newState, oldState) {
if (!oldState && newState) { if (!oldState && newState) {
this.reload() this.reload().finally(() => {
.finally(() => { this.$store.commit('TimelineSpace/HeaderMenu/changeReload', false)
this.$store.commit('TimelineSpace/HeaderMenu/changeReload', false) })
})
} }
}, },
focusedId: function (newState, _oldState) { focusedId: function(newState, _oldState) {
if (newState && this.heading) { if (newState && this.heading) {
this.$store.commit('TimelineSpace/Contents/Home/changeHeading', false) this.$store.commit('TimelineSpace/Contents/Home/changeHeading', false)
} else if (newState === null && !this.heading) { } else if (newState === null && !this.heading) {
@ -132,32 +126,31 @@ export default {
} }
}, },
methods: { methods: {
onScroll (event) { onScroll(event) {
// for lazyLoading // for lazyLoading
if (((event.target.clientHeight + event.target.scrollTop) >= document.getElementById('home').clientHeight - 10) && !this.lazyloading) { if (event.target.clientHeight + event.target.scrollTop >= document.getElementById('home').clientHeight - 10 && !this.lazyloading) {
this.$store.dispatch('TimelineSpace/Contents/Home/lazyFetchTimeline', this.timeline[this.timeline.length - 1]) this.$store.dispatch('TimelineSpace/Contents/Home/lazyFetchTimeline', this.timeline[this.timeline.length - 1]).catch(() => {
.catch(() => { this.$message({
this.$message({ message: this.$t('message.timeline_fetch_error'),
message: this.$t('message.timeline_fetch_error'), type: 'error'
type: 'error'
})
}) })
})
} }
// for unread control // for unread control
if ((event.target.scrollTop > 10) && this.heading) { if (event.target.scrollTop > 10 && this.heading) {
this.$store.commit('TimelineSpace/Contents/Home/changeHeading', false) this.$store.commit('TimelineSpace/Contents/Home/changeHeading', false)
} else if ((event.target.scrollTop <= 10) && !this.heading) { } else if (event.target.scrollTop <= 10 && !this.heading) {
this.$store.commit('TimelineSpace/Contents/Home/changeHeading', true) this.$store.commit('TimelineSpace/Contents/Home/changeHeading', true)
this.$store.commit('TimelineSpace/Contents/Home/mergeTimeline') this.$store.commit('TimelineSpace/Contents/Home/mergeTimeline')
} }
}, },
updateToot (message) { updateToot(message) {
this.$store.commit('TimelineSpace/Contents/Home/updateToot', message) this.$store.commit('TimelineSpace/Contents/Home/updateToot', message)
}, },
deleteToot (message) { deleteToot(message) {
this.$store.commit('TimelineSpace/Contents/Home/deleteToot', message) this.$store.commit('TimelineSpace/Contents/Home/deleteToot', message.id)
}, },
async reload () { async reload() {
this.$store.commit('TimelineSpace/changeLoading', true) this.$store.commit('TimelineSpace/changeLoading', true)
try { try {
await this.reloadable() await this.reloadable()
@ -165,14 +158,11 @@ export default {
this.$store.commit('TimelineSpace/changeLoading', false) this.$store.commit('TimelineSpace/changeLoading', false)
} }
}, },
upper () { upper() {
scrollTop( scrollTop(document.getElementById('scrollable'), 0)
document.getElementById('scrollable'),
0
)
this.focusedId = null this.focusedId = null
}, },
focusNext () { focusNext() {
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id) const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === -1) { if (currentIndex === -1) {
this.focusedId = this.timeline[0].uri + this.timeline[0].id this.focusedId = this.timeline[0].uri + this.timeline[0].id
@ -180,7 +170,7 @@ export default {
this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id this.focusedId = this.timeline[currentIndex + 1].uri + this.timeline[currentIndex + 1].id
} }
}, },
focusPrev () { focusPrev() {
const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id) const currentIndex = this.timeline.findIndex(toot => this.focusedId === toot.uri + toot.id)
if (currentIndex === 0) { if (currentIndex === 0) {
this.focusedId = null this.focusedId = null
@ -188,13 +178,13 @@ export default {
this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id this.focusedId = this.timeline[currentIndex - 1].uri + this.timeline[currentIndex - 1].id
} }
}, },
focusToot (message) { focusToot(message) {
this.focusedId = message.uri + message.id this.focusedId = message.uri + message.id
}, },
focusSidebar () { focusSidebar() {
Event.$emit('focus-sidebar') Event.$emit('focus-sidebar')
}, },
handleKey (event) { handleKey(event) {
switch (event.srcKey) { switch (event.srcKey) {
case 'next': case 'next':
this.focusedId = this.timeline[0].uri + this.timeline[0].id this.focusedId = this.timeline[0].uri + this.timeline[0].id

View File

@ -334,6 +334,11 @@ const actions: ActionTree<TimelineSpaceState, RootState> = {
} }
commit('TimelineSpace/SideMenu/changeUnreadMentions', true, { root: true }) commit('TimelineSpace/SideMenu/changeUnreadMentions', true, { root: true })
}) })
ipcRenderer.on('delete-start-user-streaming', (_, id: string) => {
commit('TimelineSpace/Contents/Home/deleteToot', id, { root: true })
commit('TimelineSpace/Contents/Notifications/deleteToot', id, { root: true })
commit('TimelineSpace/Contents/Mentions/deleteToot', id, { root: true })
})
}, },
startUserStreaming: ({ state }): Promise<{}> => { startUserStreaming: ({ state }): Promise<{}> => {
// @ts-ignore // @ts-ignore
@ -418,6 +423,7 @@ const actions: ActionTree<TimelineSpaceState, RootState> = {
ipcRenderer.removeAllListeners('update-start-user-streaming') ipcRenderer.removeAllListeners('update-start-user-streaming')
ipcRenderer.removeAllListeners('mention-start-user-streaming') ipcRenderer.removeAllListeners('mention-start-user-streaming')
ipcRenderer.removeAllListeners('notification-start-user-streaming') ipcRenderer.removeAllListeners('notification-start-user-streaming')
ipcRenderer.removeAllListeners('delete-start-user-streaming')
ipcRenderer.removeAllListeners('error-start-user-streaming') ipcRenderer.removeAllListeners('error-start-user-streaming')
}, },
stopUserStreaming: () => { stopUserStreaming: () => {

View File

@ -86,12 +86,12 @@ const mutations: MutationTree<HomeState> = {
} }
}) })
}, },
[MUTATION_TYPES.DELETE_TOOT]: (state, message: Status) => { [MUTATION_TYPES.DELETE_TOOT]: (state, messageId: string) => {
state.timeline = state.timeline.filter(toot => { state.timeline = state.timeline.filter(toot => {
if (toot.reblog !== null && toot.reblog.id === message.id) { if (toot.reblog !== null && toot.reblog.id === messageId) {
return false return false
} else { } else {
return toot.id !== message.id return toot.id !== messageId
} }
}) })
}, },

View File

@ -3,10 +3,10 @@ import { Module, MutationTree, ActionTree, GetterTree } from 'vuex'
import { RootState } from '@/store' import { RootState } from '@/store'
export interface MentionsState { export interface MentionsState {
lazyLoading: boolean, lazyLoading: boolean
heading: boolean, heading: boolean
mentions: Array<Notification>, mentions: Array<Notification>
unreadMentions: Array<Notification>, unreadMentions: Array<Notification>
filter: string filter: string
} }
@ -28,6 +28,7 @@ export const MUTATION_TYPES = {
ARCHIVE_MENTIONS: 'archiveMentions', ARCHIVE_MENTIONS: 'archiveMentions',
CLEAR_MENTIONS: 'clearMentions', CLEAR_MENTIONS: 'clearMentions',
UPDATE_TOOT: 'updateToot', UPDATE_TOOT: 'updateToot',
DELETE_TOOT: 'deleteToot',
CHANGE_FILTER: 'changeFilter' CHANGE_FILTER: 'changeFilter'
} }
@ -48,22 +49,22 @@ const mutations: MutationTree<MentionsState> = {
[MUTATION_TYPES.UPDATE_MENTIONS]: (state, messages: Array<Notification>) => { [MUTATION_TYPES.UPDATE_MENTIONS]: (state, messages: Array<Notification>) => {
state.mentions = messages state.mentions = messages
}, },
[MUTATION_TYPES.MERGE_MENTIONS]: (state) => { [MUTATION_TYPES.MERGE_MENTIONS]: state => {
state.mentions = state.unreadMentions.slice(0, 80).concat(state.mentions) state.mentions = state.unreadMentions.slice(0, 80).concat(state.mentions)
state.unreadMentions = [] state.unreadMentions = []
}, },
[MUTATION_TYPES.INSERT_MENTIONS]: (state, messages: Array<Notification>) => { [MUTATION_TYPES.INSERT_MENTIONS]: (state, messages: Array<Notification>) => {
state.mentions = state.mentions.concat(messages) state.mentions = state.mentions.concat(messages)
}, },
[MUTATION_TYPES.ARCHIVE_MENTIONS]: (state) => { [MUTATION_TYPES.ARCHIVE_MENTIONS]: state => {
state.mentions = state.mentions.slice(0, 40) state.mentions = state.mentions.slice(0, 40)
}, },
[MUTATION_TYPES.CLEAR_MENTIONS]: (state) => { [MUTATION_TYPES.CLEAR_MENTIONS]: state => {
state.mentions = [] state.mentions = []
state.unreadMentions = [] state.unreadMentions = []
}, },
[MUTATION_TYPES.UPDATE_TOOT]: (state, message: Notification) => { [MUTATION_TYPES.UPDATE_TOOT]: (state, message: Notification) => {
state.mentions = state.mentions.map((mention) => { state.mentions = state.mentions.map(mention => {
if (mention.status !== null && mention.status.id === message.id) { if (mention.status !== null && mention.status.id === message.id) {
const status = { const status = {
status: message status: message
@ -74,6 +75,19 @@ const mutations: MutationTree<MentionsState> = {
} }
}) })
}, },
[MUTATION_TYPES.DELETE_TOOT]: (state, id: string) => {
state.mentions = state.mentions.filter(mention => {
if (mention.status) {
if (mention.status.reblog && mention.status.reblog.id === id) {
return false
} else {
return mention.status.id !== id
}
} else {
return true
}
})
},
[MUTATION_TYPES.CHANGE_FILTER]: (state, filter: string) => { [MUTATION_TYPES.CHANGE_FILTER]: (state, filter: string) => {
state.filter = filter state.filter = filter
} }
@ -81,11 +95,11 @@ const mutations: MutationTree<MentionsState> = {
const actions: ActionTree<MentionsState, RootState> = { const actions: ActionTree<MentionsState, RootState> = {
fetchMentions: async ({ commit, rootState }): Promise<Array<Notification>> => { fetchMentions: async ({ commit, rootState }): Promise<Array<Notification>> => {
const client = new Mastodon( const client = new Mastodon(rootState.TimelineSpace.account.accessToken!, rootState.TimelineSpace.account.baseURL + '/api/v1')
rootState.TimelineSpace.account.accessToken!, const res: Response<Array<Notification>> = await client.get<Array<Notification>>('/notifications', {
rootState.TimelineSpace.account.baseURL + '/api/v1' limit: 30,
) exclude_types: ['follow', 'favourite', 'reblog']
const res: Response<Array<Notification>> = await client.get<Array<Notification>>('/notifications', { limit: 30, exclude_types: ['follow', 'favourite', 'reblog'] }) })
commit(MUTATION_TYPES.UPDATE_MENTIONS, res.data) commit(MUTATION_TYPES.UPDATE_MENTIONS, res.data)
return res.data return res.data
}, },
@ -94,11 +108,9 @@ const actions: ActionTree<MentionsState, RootState> = {
return Promise.resolve(null) return Promise.resolve(null)
} }
commit(MUTATION_TYPES.CHANGE_LAZY_LOADING, true) commit(MUTATION_TYPES.CHANGE_LAZY_LOADING, true)
const client = new Mastodon( const client = new Mastodon(rootState.TimelineSpace.account.accessToken!, rootState.TimelineSpace.account.baseURL + '/api/v1')
rootState.TimelineSpace.account.accessToken!, return client
rootState.TimelineSpace.account.baseURL + '/api/v1' .get<Array<Notification>>('/notifications', { max_id: lastMention.id, limit: 30, exclude_types: ['follow', 'favourite', 'reblog'] })
)
return client.get<Array<Notification>>('/notifications', { max_id: lastMention.id, limit: 30, exclude_types: ['follow', 'favourite', 'reblog'] })
.then(res => { .then(res => {
commit(MUTATION_TYPES.INSERT_MENTIONS, res.data) commit(MUTATION_TYPES.INSERT_MENTIONS, res.data)
return res.data return res.data
@ -110,7 +122,7 @@ const actions: ActionTree<MentionsState, RootState> = {
} }
const getters: GetterTree<MentionsState, RootState> = { const getters: GetterTree<MentionsState, RootState> = {
mentions: (state) => { mentions: state => {
return state.mentions.filter(mention => mention.type === 'mention') return state.mentions.filter(mention => mention.type === 'mention')
} }
} }

View File

@ -27,6 +27,7 @@ export const MUTATION_TYPES = {
MERGE_NOTIFICATIONS: 'mergeNotifications', MERGE_NOTIFICATIONS: 'mergeNotifications',
INSERT_NOTIFICATIONS: 'insertNotifications', INSERT_NOTIFICATIONS: 'insertNotifications',
UPDATE_TOOT: 'updateToot', UPDATE_TOOT: 'updateToot',
DELETE_TOOT: 'deleteToot',
CLEAR_NOTIFICATIONS: 'clearNotifications', CLEAR_NOTIFICATIONS: 'clearNotifications',
ARCHIVE_NOTIFICATIONS: 'archiveNotifications', ARCHIVE_NOTIFICATIONS: 'archiveNotifications',
CHANGE_FILTER: 'changeFilter' CHANGE_FILTER: 'changeFilter'
@ -70,6 +71,19 @@ const mutations: MutationTree<NotificationsState> = {
} }
}) })
}, },
[MUTATION_TYPES.DELETE_TOOT]: (state, id: string) => {
state.notifications = state.notifications.filter(notification => {
if (notification.status) {
if (notification.status.reblog && notification.status.reblog.id === id) {
return false
} else {
return notification.status.id !== id
}
} else {
return true
}
})
},
[MUTATION_TYPES.CLEAR_NOTIFICATIONS]: state => { [MUTATION_TYPES.CLEAR_NOTIFICATIONS]: state => {
state.notifications = [] state.notifications = []
}, },