import generator , { Entity } from 'megalodon' ; import { Module , MutationTree , ActionTree } from 'vuex' ; import { RootState } from '@/store' ; import { LoadPositionWithTag } from '@/types/loadPosition' ; import { MyWindow } from '~/src/types/global' ; const win = ( window as any ) as MyWindow ; export type TagState = { timeline : Array < Entity . Status > ; lazyLoading : boolean ; heading : boolean ; scrolling : boolean ; } ; const state = ( ) : TagState => ( { timeline : [ ] , lazyLoading : false , heading : true , scrolling : false } ) ; export const MUTATION_TYPES = { CHANGE_HEADING : 'changeHeading' , APPEND_TIMELINE : 'appendTimeline' , UPDATE_TIMELINE : 'updateTimeline' , INSERT_TIMELINE : 'insertTimeline' , ARCHIVE_TIMELINE : 'archiveTimeline' , CLEAR_TIMELINE : 'clearTimeline' , UPDATE_TOOT : 'updateToot' , DELETE_TOOT : 'deleteToot' , CHANGE_LAZY_LOADING : 'changeLazyLoading' , CHANGE_SCROLLING : 'changeScrolling' } ; const mutations = { [ MUTATION_TYPES . CHANGE_HEADING ] : ( state , value ) => { state . heading = value ; } , [ MUTATION_TYPES . APPEND_TIMELINE ] : ( state , update ) => { if ( ! state . timeline . find ( item => item . id === update . id ) ) { state . timeline = [ update ] . concat ( state . timeline ) ; } } , [ MUTATION_TYPES . UPDATE_TIMELINE ] : ( state , timeline ) => { state . timeline = timeline ; } , [ MUTATION_TYPES . INSERT_TIMELINE ] : ( state , messages ) => { state . timeline = state . timeline . concat ( messages ) ; } , [ MUTATION_TYPES . ARCHIVE_TIMELINE ] : state => { state . timeline = state . timeline . slice ( 0 , 40 ) ; } , [ MUTATION_TYPES . CLEAR_TIMELINE ] : state => { state . timeline = [ ] ; } , [ MUTATION_TYPES . UPDATE_TOOT ] : ( state , message ) => { state . timeline = state . timeline . map ( toot => { if ( toot . id === message . id ) { return message ; } else if ( toot . reblog !== null && toot . reblog . id === message . id ) { const reblog = { reblog : message } ; return Object . assign ( toot , reblog ) ; } else { return toot ; } } ) ; } , [ MUTATION_TYPES . DELETE_TOOT ] : ( state , id ) => { state . timeline = state . timeline . filter ( toot => { if ( toot . reblog !== null && toot . reblog . id === id ) { return false ; } else { return toot . id !== id ; } } ) ; } , [ MUTATION_TYPES . CHANGE_LAZY_LOADING ] : ( state , value ) => { state . lazyLoading = value ; } , [ MUTATION_TYPES . CHANGE_SCROLLING ] : ( state , value ) => { state . scrolling = value ; } } ; const actions = { fetch : async ( { commit , rootState } , tag ) : Promise < Array < Entity . Status > > => { const client = generator ( rootState . TimelineSpace . sns , rootState . TimelineSpace . account . baseURL , rootState . TimelineSpace . account . accessToken , rootState . App . userAgent ) ; const res = await client . getTagTimeline ( encodeURIComponent ( tag ) , { limit : 40 } ) ; commit ( MUTATION_TYPES . UPDATE_TIMELINE , res . data ) ; return res . data ; } , startStreaming : ( { state , commit , rootState } , tag ) => { win . ipcRenderer . on ( 'update-start-tag-streaming' , ( _ , update ) => { commit ( MUTATION_TYPES . APPEND_TIMELINE , update ) ; if ( state . heading && Math . random ( ) > 0.8 ) { commit ( MUTATION_TYPES . ARCHIVE_TIMELINE ) ; } } ) ; win . ipcRenderer . on ( 'delete-start-tag-streaming' , ( _ , id ) => { commit ( MUTATION_TYPES . DELETE_TOOT , id ) ; } ) ; return new Promise ( ( resolve , reject ) => { win . ipcRenderer . send ( 'start-tag-streaming' , { tag : encodeURIComponent ( tag ) , account : rootState . TimelineSpace . account } ) ; win . ipcRenderer . once ( 'error-start-tag-streaming' , ( _ , err ) => { reject ( err ) ; } ) ; } ) ; } , stopStreaming : ( ) => { return new Promise ( resolve => { win . ipcRenderer . removeAllListeners ( 'error-start-tag-streaming' ) ; win . ipcRenderer . removeAllListeners ( 'update-start-tag-streaming' ) ; win . ipcRenderer . removeAllListeners ( 'delete-start-tag-streaming' ) ; win . ipcRenderer . send ( 'stop-tag-streaming' ) ; resolve ( null ) ; } ) ; } , lazyFetchTimeline : async ( { state , commit , rootState } , loadPosition ) : Promise < Array < Entity . Status > | null > => { 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 ) ; return client . getTagTimeline ( loadPosition . tag , { max_id : loadPosition . status . id , limit : 40 } ) . then ( res => { commit ( MUTATION_TYPES . INSERT_TIMELINE , res . data ) ; return res . data ; } ) . finally ( ( ) => { commit ( MUTATION_TYPES . CHANGE_LAZY_LOADING , false ) ; } ) ; } } ; const Tag = { namespaced : true , state : state , mutations : mutations , actions : actions } ; export default Tag ;