mirror of
https://github.com/zero-peak/ZeroOmega.git
synced 2025-03-13 08:28:13 -04:00
Refactor Options constructor into loadOptions and init methods.
This commit is contained in:
parent
a145d4f6a5
commit
29bebd458c
@ -136,5 +136,7 @@ angular.module('omegaTarget', []).factory 'omegaTarget', ($q) ->
|
||||
return d.promise
|
||||
openManage: ->
|
||||
chrome.tabs.create url: 'chrome://extensions/?id=' + chrome.runtime.id
|
||||
setOptionsSync: (enabled, args) ->
|
||||
callBackground('setOptionsSync', enabled, args)
|
||||
|
||||
return omegaTarget
|
||||
|
@ -237,13 +237,13 @@ class ChromeOptions extends OmegaTarget.Options
|
||||
else
|
||||
Promise.reject()
|
||||
|
||||
getOldOptions = getOldOptions.catch =>
|
||||
getOldOptions = getOldOptions.catch ->
|
||||
if options?['config']
|
||||
Promise.resolve options
|
||||
else if localStorage['config']
|
||||
Promise.resolve localStorage
|
||||
else
|
||||
Promise.reject new @NoOptionsError()
|
||||
Promise.reject new OmegaTarget.Options.NoOptionsError()
|
||||
|
||||
getOldOptions.then (oldOptions) =>
|
||||
i18n = {
|
||||
|
@ -55,48 +55,99 @@ class Options
|
||||
value = profile
|
||||
return value
|
||||
|
||||
constructor: (@_options, @_storage, @_state, @log, @sync) ->
|
||||
constructor: (options, @_storage, @_state, @log, @sync) ->
|
||||
@_storage ?= Storage()
|
||||
@_state ?= Storage()
|
||||
@log ?= Log
|
||||
if @_options?
|
||||
@ready = Promise.resolve(@_options)
|
||||
if not options?
|
||||
@init()
|
||||
else
|
||||
@ready = if @sync?.enabled then Promise.resolve() else @_storage.get(null)
|
||||
@ready = @ready.then (options) =>
|
||||
return options if not @sync?
|
||||
if options?['schemaVersion']
|
||||
@_state.get({'syncOptions': ''}).then ({syncOptions}) =>
|
||||
return if syncOptions
|
||||
@_state.set({'syncOptions': 'conflict'})
|
||||
@sync.storage.get('schemaVersion').then({schemaVersion}) =>
|
||||
@_state.set({'syncOptions': 'pristine'}) if not schemaVersion
|
||||
return options
|
||||
@ready = @_storage.remove().then(=>
|
||||
@_storage.set(options)
|
||||
).then =>
|
||||
@init()
|
||||
|
||||
###*
|
||||
# Attempt to load options from local and remote storage.
|
||||
# @param {?{}} args Extra arguments
|
||||
# @param {number=3} args.retry Number of retries before giving up.
|
||||
# @returns {Promise<OmegaOptions>} The loaded options
|
||||
###
|
||||
loadOptions: ({retry} = {}) ->
|
||||
retry ?= 3
|
||||
@_syncWatchStop?()
|
||||
@_syncWatchStop = null
|
||||
@_watchStop?()
|
||||
@_watchStop = null
|
||||
|
||||
loadRaw = if options? then Promise.resolve(options) else
|
||||
if not @sync?.enabled
|
||||
if not @sync?
|
||||
@_state.set({'syncOptions': 'unsupported'})
|
||||
@_storage.get(null)
|
||||
else
|
||||
@_state.set({'syncOptions': 'sync'})
|
||||
@sync.watchAndPull(@_storage)
|
||||
@_syncWatchStop = @sync.watchAndPull(@_storage)
|
||||
@sync.copyTo(@_storage).then =>
|
||||
@_storage.get(null)
|
||||
@ready = @ready.then((options) =>
|
||||
@upgrade(options).then(([options, changes]) =>
|
||||
modified = {}
|
||||
removed = []
|
||||
for own key, value of changes
|
||||
if typeof value == 'undefined'
|
||||
removed.push(value)
|
||||
else
|
||||
modified[key] = value
|
||||
@_storage.set(modified).then(=>
|
||||
@_storage.remove(removed)
|
||||
).return(options)
|
||||
).catch (ex) =>
|
||||
if not ex instanceof NoOptionsError
|
||||
@log.error(ex.stack)
|
||||
@reset().tap =>
|
||||
@_state.set({'firstRun': 'new', 'web.switchGuide': 'showOnFirstUse'})
|
||||
).then((options) =>
|
||||
|
||||
@optionsLoaded = loadRaw.then((options) =>
|
||||
@upgrade(options)
|
||||
).then(([options, changes]) =>
|
||||
@_storage.apply(changes: changes).return(options)
|
||||
).tap((options) =>
|
||||
@_options = options
|
||||
@_watch()
|
||||
).then(=>
|
||||
@_watchStop = @_watch()
|
||||
# Try to set syncOptions to some value if not initialized.
|
||||
@_state.get({'syncOptions': ''}).then ({syncOptions}) =>
|
||||
return if syncOptions
|
||||
@_state.set({'syncOptions': 'conflict'})
|
||||
@sync.storage.get('schemaVersion').then ({schemaVersion}) =>
|
||||
@_state.set({'syncOptions': 'pristine'}) if not schemaVersion
|
||||
).catch (e) =>
|
||||
return Promise.reject(e) unless retry > 0
|
||||
|
||||
getFallbackOptions = Promise.resolve().then =>
|
||||
if e instanceof NoOptionsError
|
||||
@_state.get({
|
||||
'firstRun': 'new'
|
||||
'web.switchGuide': 'showOnFirstUse'
|
||||
}).then (items) => @_state.set(items)
|
||||
return null unless @sync?
|
||||
# Try to fetch options from sync storage.
|
||||
return @sync.storage.get(null).then (options) =>
|
||||
if not options['schemaVersion']
|
||||
@_state.set({'syncOptions': 'pristine'})
|
||||
return null
|
||||
else
|
||||
@_state.set({'syncOptions': 'sync'})
|
||||
@sync.enabled = true
|
||||
@log.log('Options#loadOptions::fromSync', options)
|
||||
options
|
||||
else
|
||||
@log.error(e.stack)
|
||||
# Some serious error happened when loading options. Disable syncing
|
||||
# and use fallback options.
|
||||
@_state.remove(['syncOptions'])
|
||||
return null
|
||||
|
||||
getFallbackOptions.then (options) =>
|
||||
options ?= @parseOptions(@getDefaultOptions())
|
||||
if @sync?
|
||||
prevEnabled = @sync.enabled
|
||||
@sync.enabled = false
|
||||
@_storage.remove().then(=>
|
||||
@_storage.set(options)
|
||||
).then =>
|
||||
@sync.enabled = prevEnabled if @sync?
|
||||
@loadOptions({retry: retry - 1})
|
||||
|
||||
###*
|
||||
# Attempt to initialize (or reinitialize) options.
|
||||
# @returns {Promise<OmegaOptions>} A promise that is fulfilled on ready.
|
||||
###
|
||||
init: ->
|
||||
@ready = @loadOptions().then(=>
|
||||
if @_options['-startupProfileName']
|
||||
@applyProfile(@_options['-startupProfileName'])
|
||||
else
|
||||
@ -125,6 +176,8 @@ class Options
|
||||
if @_options['-downloadInterval'] > 0
|
||||
@updateProfile()
|
||||
|
||||
return @ready
|
||||
|
||||
toString: -> "<Options>"
|
||||
|
||||
###*
|
||||
@ -173,14 +226,11 @@ class Options
|
||||
Promise.reject new Error("Invalid schemaVerion #{version}!")
|
||||
|
||||
###*
|
||||
# Reset the options to the given options or initial options.
|
||||
# @param {?OmegaOptions} options The options to set. Defaults to initial.
|
||||
# @returns {Promise<OmegaOptions>} The options just applied
|
||||
# Parse options in various formats (including JSON & base64).
|
||||
# @param {OmegaOptions|string} options The options to parse
|
||||
# @returns {Promise<OmegaOptions>} The parsed options.
|
||||
###
|
||||
reset: (options) ->
|
||||
@log.method('Options#reset', this, arguments)
|
||||
if not options
|
||||
options = @getDefaultOptions()
|
||||
parseOptions: (options) ->
|
||||
if typeof options == 'string'
|
||||
if options[0] != '{'
|
||||
try
|
||||
@ -190,11 +240,26 @@ class Options
|
||||
options = null
|
||||
options = try JSON.parse(options)
|
||||
if not options
|
||||
return Promise.reject new Error('Invalid options!')
|
||||
@upgrade(options).then ([opt]) =>
|
||||
return throw new Error('Invalid options!')
|
||||
|
||||
return options
|
||||
|
||||
###*
|
||||
# Reset the options to the given options or initial options.
|
||||
# @param {?OmegaOptions} options The options to set. Defaults to initial.
|
||||
# @returns {Promise<OmegaOptions>} The options just applied
|
||||
###
|
||||
reset: (options) ->
|
||||
@log.method('Options#reset', this, arguments)
|
||||
options ?= getDefaultOptions()
|
||||
@upgrade(@parseOptions(options)).then ([opt]) =>
|
||||
# Disable syncing when resetting to avoid affecting sync storage.
|
||||
@sync.enabled = false if @sync?
|
||||
@_state.remove(['syncOptions'])
|
||||
@_storage.remove().then(=>
|
||||
@_storage.set(opt)
|
||||
).then -> opt
|
||||
).then =>
|
||||
@init()
|
||||
|
||||
###*
|
||||
# Called on the first initialization of options.
|
||||
@ -856,4 +921,44 @@ class Options
|
||||
@currentProfileChanged('external')
|
||||
return
|
||||
|
||||
###*
|
||||
# Switch options syncing on and off.
|
||||
# @param {boolean} enabled Whether to enable syncing
|
||||
# @param {?{}} args Extra arguments
|
||||
# @param {boolean=false} args.force If true, overwrite options when conflict
|
||||
# @returns {Promise} A promise which is fulfilled when the syncing is switched
|
||||
###
|
||||
setOptionsSync: (enabled, args) ->
|
||||
@log.method('Options#setOptionsSync', this, arguments)
|
||||
if not @sync?
|
||||
return Promise.reject(new Error('Options syncing is unsupported.'))
|
||||
@_state.get({'syncOptions': ''}).then ({syncOptions}) =>
|
||||
if not enabled
|
||||
if syncOptions == 'sync'
|
||||
@_state.set({'syncOptions': 'conflict'})
|
||||
@sync.enabled = false
|
||||
@_syncWatchStop?()
|
||||
@_syncWatchStop = null
|
||||
return
|
||||
|
||||
if syncOptions == 'conflict'
|
||||
if not args?.force
|
||||
return Promise.reject(new Error(
|
||||
'Syncing not enabled due to conflict. Retry with force to overwrite
|
||||
local options and enable syncing.'))
|
||||
return if syncOptions == 'sync'
|
||||
@_state.set({'syncOptions': 'sync'}).then =>
|
||||
if syncOptions == 'conflict'
|
||||
# Try to re-init options from sync.
|
||||
@sync.enabled = false
|
||||
@_storage.remove().then =>
|
||||
@sync.enabled = true
|
||||
@init()
|
||||
else
|
||||
@sync.enabled = true
|
||||
@_syncWatchStop?()
|
||||
@sync.requestPush(@_options)
|
||||
@_syncWatchStop = @sync.watchAndPull(@_storage)
|
||||
return
|
||||
|
||||
module.exports = Options
|
||||
|
Loading…
Reference in New Issue
Block a user