import emojidata from 'unicode-emoji-json/data-by-emoji.json' ; import generator , { MegalodonInterface } from 'megalodon' ; import { Module , MutationTree , ActionTree , GetterTree } from 'vuex' ; import { RootState } from '@/store/index' ; import { LocalTag } from '~/src/types/localTag' ; import { InsertAccountCache } from '~/src/types/insertAccountCache' ; import { CachedAccount } from '~/src/types/cachedAccount' ; import { MyWindow } from '~/src/types/global' ; const win = ( window as any ) as MyWindow ; type Suggest = { name : string ; image ? : string | null ; code ? : string | null ; } ; type SuggestAccount = Suggest ; type SuggestHashtag = Suggest ; type SuggestEmoji = Suggest ; export type StatusState = { filteredSuggestion : Array < Suggest > ; filteredAccounts : Array < SuggestAccount > ; filteredHashtags : Array < SuggestHashtag > ; filteredEmojis : Array < SuggestEmoji > ; openSuggest : boolean ; startIndex : number | null ; matchWord : string | null ; client : MegalodonInterface | null ; } ; const state = ( ) : StatusState => ( { filteredSuggestion : [ ] , filteredAccounts : [ ] , filteredHashtags : [ ] , filteredEmojis : [ ] , openSuggest : false , startIndex : null , matchWord : null , client : null } ) ; export const MUTATION_TYPES = { APPEND_FILTERED_ACCOUNTS : 'appendFilteredAccounts' , CLEAR_FILTERED_ACCOUNTS : 'clearFilteredAccounts' , APPEND_FILTERED_HASHTAGS : 'appendFilteredHashtags' , CLEAR_FILTERED_HASHTAGS : 'clearFilteredHashtags' , UPDATE_FILTERED_EMOJIS : 'updateFilteredEmojis' , CLEAR_FILTERED_EMOJIS : 'clearFilteredEmojis' , CHANGE_OPEN_SUGGEST : 'changeOpenSuggest' , CHANGE_START_INDEX : 'changeStartIndex' , CHANGE_MATCH_WORD : 'changeMatchWord' , FILTERED_SUGGESTION_FROM_HASHTAGS : 'filteredSuggestionFromHashtags' , FILTERED_SUGGESTION_FROM_ACCOUNTS : 'filteredSuggestionFromAccounts' , FILTERED_SUGGESTION_FROM_EMOJIS : 'filteredSuggestionFromEmojis' , CLEAR_FILTERED_SUGGESTION : 'clearFilteredSuggestion' , SET_CLIENT : 'setClient' , CLEAR_CLIENT : 'clearClient' } ; const mutations = { [ MUTATION_TYPES . APPEND_FILTERED_ACCOUNTS ] : ( state , accounts ) => { const suggestion = accounts . map ( a => ( { name : `@${ a }` , image : null } ) ) ; const appended = state . filteredAccounts . concat ( suggestion ) ; const unique = appended . filter ( ( v1 , i1 , a1 ) => { return ( a1 . findIndex ( v2 => { return v1 . name === v2 . name ; } ) === i1 ) ; } ) ; state . filteredAccounts = unique . sort ( ( a , b ) => { if ( a . name < b . name ) return - 1 ; if ( a . name > b . name ) return 1 ; return 0 ; } ) ; } , [ MUTATION_TYPES . CLEAR_FILTERED_ACCOUNTS ] : state => { state . filteredAccounts = [ ] ; } , [ MUTATION_TYPES . APPEND_FILTERED_HASHTAGS ] : ( state , tags ) => { const suggestion = tags . map ( t => ( { name : `#${ t }` , image : null } ) ) ; const appended = state . filteredHashtags . concat ( suggestion ) ; const unique = appended . filter ( ( v1 , i1 , a1 ) => { return ( a1 . findIndex ( v2 => { return v1 . name === v2 . name ; } ) === i1 ) ; } ) ; Array . from ( new Set ( appended ) ) ; state . filteredHashtags = unique . sort ( ( a , b ) => { if ( a . name < b . name ) return - 1 ; if ( a . name > b . name ) return 1 ; return 0 ; } ) ; } , [ MUTATION_TYPES . CLEAR_FILTERED_HASHTAGS ] : state => { state . filteredHashtags = [ ] ; } , [ MUTATION_TYPES . UPDATE_FILTERED_EMOJIS ] : ( state , emojis ) => { state . filteredEmojis = emojis ; } , [ MUTATION_TYPES . CHANGE_OPEN_SUGGEST ] : ( state , value ) => { state . openSuggest = value ; } , [ MUTATION_TYPES . CHANGE_START_INDEX ] : ( state , index ) => { state . startIndex = index ; } , [ MUTATION_TYPES . CHANGE_MATCH_WORD ] : ( state , word ) => { state . matchWord = word ; } , [ MUTATION_TYPES . FILTERED_SUGGESTION_FROM_HASHTAGS ] : state => { state . filteredSuggestion = state . filteredHashtags ; } , [ MUTATION_TYPES . FILTERED_SUGGESTION_FROM_ACCOUNTS ] : state => { state . filteredSuggestion = state . filteredAccounts ; } , [ MUTATION_TYPES . FILTERED_SUGGESTION_FROM_EMOJIS ] : state => { state . filteredSuggestion = state . filteredEmojis ; } , [ MUTATION_TYPES . CLEAR_FILTERED_SUGGESTION ] : state => { state . filteredSuggestion = [ ] ; } , [ MUTATION_TYPES . SET_CLIENT ] : ( state , client ) => { state . client = client ; } , [ MUTATION_TYPES . CLEAR_CLIENT ] : state => { state . client = null ; } } ; type WordStart = { word : string ; start : number ; } ; const actions = { suggestAccount : async ( { commit , rootState , dispatch } , wordStart ) => { dispatch ( 'cancelRequest' ) ; commit ( MUTATION_TYPES . CLEAR_FILTERED_ACCOUNTS ) ; commit ( MUTATION_TYPES . FILTERED_SUGGESTION_FROM_ACCOUNTS ) ; const { word , start } = wordStart ; const searchCache = async ( ) => { const target = word . replace ( '@' , '' ) ; const accounts = await win . ipcRenderer . invoke ( 'get-cache-accounts' , rootState . TimelineSpace . account . _id ) ; const matched = accounts . map ( account => account . acct ) . filter ( acct => acct . includes ( target ) ) ; if ( matched . length === 0 ) throw new Error ( 'Empty' ) ; commit ( MUTATION_TYPES . APPEND_FILTERED_ACCOUNTS , matched ) ; commit ( MUTATION_TYPES . CHANGE_OPEN_SUGGEST , true ) ; commit ( MUTATION_TYPES . CHANGE_START_INDEX , start ) ; commit ( MUTATION_TYPES . CHANGE_MATCH_WORD , word ) ; commit ( MUTATION_TYPES . FILTERED_SUGGESTION_FROM_ACCOUNTS ) ; return matched ; } ; const searchAPI = async ( ) => { const client = generator ( rootState . TimelineSpace . sns , rootState . TimelineSpace . account . baseURL , rootState . TimelineSpace . account . accessToken , rootState . App . userAgent ) ; commit ( MUTATION_TYPES . SET_CLIENT , client ) ; const res = await client . searchAccount ( word ) ; if ( res . data . length === 0 ) throw new Error ( 'Empty' ) ; commit ( MUTATION_TYPES . APPEND_FILTERED_ACCOUNTS , res . data . map ( account => account . acct ) ) ; await win . ipcRenderer . invoke ( 'insert-cache-accounts' , { ownerID : rootState . TimelineSpace . account . _id ! , accts : res . data . map ( a => a . acct ) } as InsertAccountCache ) ; commit ( MUTATION_TYPES . CHANGE_OPEN_SUGGEST , true ) ; commit ( MUTATION_TYPES . CHANGE_START_INDEX , start ) ; commit ( MUTATION_TYPES . CHANGE_MATCH_WORD , word ) ; commit ( MUTATION_TYPES . FILTERED_SUGGESTION_FROM_ACCOUNTS ) ; return res . data ; } ; await Promise . all ( [ searchCache ( ) , searchAPI ( ) ] ) ; } , suggestHashtag : async ( { commit , rootState , dispatch } , wordStart ) => { dispatch ( 'cancelRequest' ) ; commit ( MUTATION_TYPES . CLEAR_FILTERED_HASHTAGS ) ; commit ( MUTATION_TYPES . FILTERED_SUGGESTION_FROM_HASHTAGS ) ; const { word , start } = wordStart ; const searchCache = async ( ) => { const target = word . replace ( '#' , '' ) ; const tags = await win . ipcRenderer . invoke ( 'get-cache-hashtags' ) ; const matched = tags . map ( tag => tag . tagName ) . filter ( tag => tag . includes ( target ) ) ; if ( matched . length === 0 ) throw new Error ( 'Empty' ) ; commit ( MUTATION_TYPES . APPEND_FILTERED_HASHTAGS , matched ) ; commit ( MUTATION_TYPES . CHANGE_OPEN_SUGGEST , true ) ; commit ( MUTATION_TYPES . CHANGE_START_INDEX , start ) ; commit ( MUTATION_TYPES . CHANGE_MATCH_WORD , word ) ; commit ( MUTATION_TYPES . FILTERED_SUGGESTION_FROM_HASHTAGS ) ; return matched ; } ; const searchAPI = async ( ) => { const client = generator ( rootState . TimelineSpace . sns , rootState . TimelineSpace . account . baseURL , rootState . TimelineSpace . account . accessToken , rootState . App . userAgent ) ; commit ( MUTATION_TYPES . SET_CLIENT , client ) ; const res = await client . search ( word , 'hashtags' ) ; if ( res . data . hashtags . length === 0 ) throw new Error ( 'Empty' ) ; commit ( MUTATION_TYPES . APPEND_FILTERED_HASHTAGS , res . data . hashtags . map ( tag => tag . name ) ) ; await win . ipcRenderer . invoke ( 'insert-cache-hashtags' , res . data . hashtags . map ( tag => tag . name ) ) ; commit ( MUTATION_TYPES . CHANGE_OPEN_SUGGEST , true ) ; commit ( MUTATION_TYPES . CHANGE_START_INDEX , start ) ; commit ( MUTATION_TYPES . CHANGE_MATCH_WORD , word ) ; commit ( MUTATION_TYPES . FILTERED_SUGGESTION_FROM_HASHTAGS ) ; return res . data . hashtags ; } ; await Promise . all ( [ searchCache ( ) , searchAPI ( ) ] ) ; } , suggestEmoji : ( { commit , rootState } , wordStart ) => { const { word , start } = wordStart ; const filteredEmojiName = Object . keys ( emojidata ) . filter ( ( emoji ) => `:${ emojidata [ emoji ] . name }:` . includes ( word ) ) ; const filteredNativeEmoji = filteredEmojiName . map ( ( emoji ) => { return { name : `:${ emojidata [ emoji ] . name }:` , code : emoji } ; } ) ; const filteredCustomEmoji = rootState . TimelineSpace . emojis . map ( emoji => { return { name : `:${ emoji . shortcode }:` , image : emoji . url } ; } ) . filter ( emoji => emoji . name . includes ( word ) ) ; const filtered = filteredNativeEmoji . concat ( filteredCustomEmoji ) ; if ( filtered . length === 0 ) throw new Error ( 'Empty' ) ; commit ( MUTATION_TYPES . UPDATE_FILTERED_EMOJIS , filtered . filter ( ( e , i , array ) => { return array . findIndex ( ar => e . name === ar . name ) === i ; } ) ) ; commit ( MUTATION_TYPES . CHANGE_OPEN_SUGGEST , true ) ; commit ( MUTATION_TYPES . CHANGE_START_INDEX , start ) ; commit ( MUTATION_TYPES . CHANGE_MATCH_WORD , word ) ; commit ( MUTATION_TYPES . FILTERED_SUGGESTION_FROM_EMOJIS ) ; return filtered ; } , cancelRequest : ( { state } ) => { if ( state . client ) { state . client . cancel ( ) ; } } , closeSuggest : ( { commit , dispatch } ) => { dispatch ( 'cancelRequest' ) ; commit ( MUTATION_TYPES . CHANGE_OPEN_SUGGEST , false ) ; commit ( MUTATION_TYPES . CHANGE_START_INDEX , null ) ; commit ( MUTATION_TYPES . CHANGE_MATCH_WORD , null ) ; commit ( MUTATION_TYPES . CLEAR_FILTERED_SUGGESTION ) ; commit ( MUTATION_TYPES . CLEAR_FILTERED_ACCOUNTS ) ; commit ( MUTATION_TYPES . CLEAR_FILTERED_HASHTAGS ) ; commit ( MUTATION_TYPES . CLEAR_CLIENT ) ; } } ; const getters = { pickerEmojis : ( _state , _getters , rootState ) => { return rootState . TimelineSpace . emojis . map ( emoji => { return { name : `:${ emoji . shortcode }:` , image : emoji . url } ; } ) . filter ( ( e , i , array ) => { return array . findIndex ( ar => e . name === ar . name ) === i ; } ) . map ( e => { return { name : e . name , short_names : [ e . name ] , text : e . name , emoticons : [ ] , keywords : [ e . name ] , imageUrl : e . image } ; } ) ; } } ; const Status = { namespaced : true , state : state , mutations : mutations , actions : actions , getters : getters } ; export default Status ;