import { boolToString , randNumber , toBool } from "./utils" ; import { Application } from "../application" ; import { SystemConfig } from "@App/config" ; export interface ConfigItems extends Config { SetNamespace ( namespace ) : void ; SetNamespaceConfig ( namespace , key , val ) : Promise < any > ; GetNamespaceConfig ( namespace , key , defaultVal ? ) : string ; vtoken : string ; rand_answer : boolean ; auto : boolean ; video_mute : boolean ; answer_ignore : boolean ; video_cdn : string ; video_multiple : number ; interval : number ; topic_interval : number ; super_mode : boolean ; } let configDefaultValue = new Map < string , any > ( ) ; configDefaultValue . set ( "vtoken" , "" ) ; for ( let key in SystemConfig . config ) { for ( let i = 0 ; i < SystemConfig . config [ key ] . items . length ; i ++ ) { configDefaultValue . set ( key + "_" + SystemConfig . config [ key ] . items [ i ] . key , SystemConfig . config [ key ] . items [ i ] . value ) ; } } export class ChromeConfigItems implements ConfigItems { protected config : Config ; protected Namespace : string = "" ; protected localCache : { [ key ] : any ; } ; constructor ( config ) { this . config = config ; let list = [ ] ; configDefaultValue . forEach ( ( val , key ) => { list . push ( key ) ; } ) ; this . config . Watch ( list , ( key , val ) => { this . localCache [ key ] = val ; } ) ; this . localCache = localStorage ; } public SetNamespace ( namespace ) { this . Namespace = namespace + "_" ; } public ConfigList ( ) { return this . config . ConfigList ( ) ; } public SetNamespaceConfig ( namespace , key , val ) { return this . config . SetConfig ( namespace + "_" + key , val ) ; } public GetNamespaceConfig ( namespace , key , defaultVal ? ) { return this . config . GetConfig ( namespace + "_" + key , defaultVal ) ; } public GetConfig ( key , defaultVal ? ) { let val = this . config . GetConfig ( this . Namespace + key ) ; if ( val == undefined ) { return this . config . GetConfig ( key , defaultVal ) ; } return val || defaultVal ; } public Watch ( key , callback ) { this . config . Watch ( key , callback ) ; } public get super_mode ( ) { return toBool ( this . GetConfig ( "super_mode" , "true" ) ) ; } public get vtoken ( ) { return this . GetConfig ( "vtoken" , "" ) ; } public get rand_answer ( ) { return toBool ( this . GetConfig ( "rand_answer" , "false" ) ) ; } public get auto ( ) { return toBool ( this . GetConfig ( "auto" , "true" ) ) ; } public set auto ( val ) { this . SetConfig ( "auto" , boolToString ( val ) ) ; } public get video_mute ( ) { return toBool ( this . GetConfig ( "video_mute" , "true" ) ) ; } public get answer_ignore ( ) { return toBool ( this . GetConfig ( "answer_ignore" , "false" ) ) ; } public get video_cdn ( ) { let val = this . GetConfig ( "video_cdn" ) ; if ( val == "默认" ) { return "" ; } return val ; } public get video_multiple ( ) { return parseFloat ( this . GetConfig ( "video_multiple" ) ) ; } public get interval ( ) { let interval = parseFloat ( this . GetConfig ( "interval" , "0.1" ) ) ; interval = interval * 100 ; return Math . floor ( randNumber ( interval - interval / 2 , interval + interval / 2 ) ) / 100 ; } public SetConfig ( key , val ) { return this . config . SetConfig ( this . Namespace + key , val ) ; } public get topic_interval ( ) { return parseInt ( this . GetConfig ( "topic_interval" , "5" ) ) ; } public set topic_interval ( val ) { this . SetConfig ( "topic_interval" , val ) ; } } export interface Config { GetConfig ( key , defaultVal ? ) : string ; SetConfig ( key , val ) : Promise < any > ; ConfigList ( ) : any ; Watch ( key , callback ) : void ; } export interface ConfigWatchCallback { ( key , value ) : void ; } export function NewBackendConfig ( ) { return new Promise ( async ( resolve ) => { let ret = new backendConfig ( ) ; await ret . updateCache ( ) ; resolve ( ret ) ; } ) ; } class configWatch { protected watchCallback : Map < string , Array < ConfigWatchCallback > > ; constructor ( ) { this . watchCallback = new Map < string , Array < ConfigWatchCallback > > ( ) ; } public WatchEvent ( key , val ) { let list = this . watchCallback . get ( key ) ; if ( list != undefined ) { list . forEach ( ( v ) => { v ( key , val ) ; } ) ; } list = this . watchCallback . get ( "*" ) ; if ( list != undefined ) { list . forEach ( ( v ) => { v ( key , val ) ; } ) ; } } public Watch ( key , callback ) { if ( typeof key == "string" ) { this . setWatchMap ( key , callback ) ; return ; } key . forEach ( ( val , index ) => { this . setWatchMap ( val , callback ) ; } ) ; } protected setWatchMap ( key , callback ) { let list = this . watchCallback . get ( key ) ; if ( list == undefined ) { list = new Array < ConfigWatchCallback > ( ) ; } list . push ( callback ) ; this . watchCallback . set ( key , list ) ; } } class backendConfig implements Config { protected cache : { [ key ] : string ; } ; protected watch : configWatch ; constructor ( ) { this . watch = new configWatch ( ) ; chrome . runtime . onMessage . addListener ( ( request ) => { if ( request . type && request . type == "cxconfig" ) { this . cache [ request . key ] = request . value ; this . watch . WatchEvent ( request . key , request . value ) ; this . updateConfigStorage ( ) ; } } ) ; } protected updateConfigStorage ( ) { let txt = JSON . stringify ( this . cache ) ; chrome . storage . sync . set ( { "config_storage" : txt } ) ; } public updateCache ( ) { return new Promise ( resolve => { chrome . storage . sync . get ( "config_storage" , items => { if ( items [ "config_storage" ] ) { this . cache = JSON . parse ( items [ "config_storage" ] ) ; } else { this . cache = { } ; } configDefaultValue . forEach ( ( val , key ) => { if ( this . cache [ key ] === undefined ) { this . cache [ key ] = val ; } } ) ; this . updateConfigStorage ( ) ; resolve ( undefined ) ; } ) ; } ) ; } public GetConfig ( key , defaultVal ? ) { if ( this . cache == undefined ) { Application . App . log . Fatal ( "缓存失败!!!" ) ; return "" ; } return this . cache [ key ] || defaultVal ; } public Watch ( key , callback ) { return this . watch . Watch ( key , callback ) ; } public SetConfig ( key , val ) { return new Promise < any > ( resolve => { let info = { } ; info [ key ] = val ; this . cache [ key ] = val ; chrome . tabs . query ( { active : true , currentWindow : true } , function ( tabs ) { chrome . tabs . sendMessage ( tabs [ 0 ] . id , { type : "cxconfig" , key : key , value : val } ) ; } ) ; chrome . runtime . sendMessage ( { type : "cxconfig" , key : key , value : val } ) ; this . updateConfigStorage ( ) ; resolve ( undefined ) ; } ) ; } public ConfigList ( ) { return new Promise ( async ( resolve ) => { if ( this . cache ) { return resolve ( this . cache ) ; } await this . updateCache ( ) ; resolve ( this . cache ) ; } ) ; } } export function NewFrontendGetConfig ( ) { return new frontendGetConfig ( ) ; } class frontendGetConfig implements Config { protected cache : { [ key ] : string ; } ; protected watch : configWatch ; constructor ( ) { this . watch = new configWatch ( ) ; this . cache = ( < any > window ) . configData || localStorage ; window . addEventListener ( 'message' , ( event ) => { if ( event . data . type && event . data . type == "cxconfig" ) { Application . App . log . Info ( "配置更新:" + event . data . key + "=" + event . data . value ) ; this . cache [ event . data . key ] = event . data . value ; this . watch . WatchEvent ( event . data . key , event . data . value ) ; } } ) ; } public GetConfig ( key , defaultVal ? ) { if ( ( < any > window ) . GM_getValue ) { return ( < any > window ) . GM_getValue ( key , defaultVal ) ; } return this . cache [ key ] || defaultVal ; } public Watch ( key , callback ) { return this . watch . Watch ( key , callback ) ; } public async SetConfig ( key , val ) { this . cache [ key ] = val ; if ( ( < any > window ) . GM_setValue ) { return ( < any > window ) . GM_setValue ( key , val ) ; } return Application . App . Client . Send ( { type : "GM_setValue" , details : { key : key , val : val } , } ) ; } public ConfigList ( ) { return this . cache ; } }