mirror of
https://github.com/zero-peak/ZeroOmega.git
synced 2025-01-22 15:08:12 -05:00
Enhance your Gist sync experience with built-in browser sync
This commit is contained in:
parent
bc69662911
commit
f5f987253c
@ -452,6 +452,9 @@ msgstr "Syncing (Experimental)"
|
||||
msgid "options_syncEnable"
|
||||
msgstr "Enable Syncing"
|
||||
|
||||
msgid "options_useBuiltInSyncEnhance"
|
||||
msgstr "Enhance your Gist sync experience with built-in browser sync"
|
||||
|
||||
msgid "options_syncEnableForce"
|
||||
msgstr "Download from Syncing"
|
||||
|
||||
|
@ -413,6 +413,9 @@ msgstr "选项同步 (测试中)"
|
||||
msgid "options_syncEnable"
|
||||
msgstr "启用同步"
|
||||
|
||||
msgid "options_useBuiltInSyncEnhance"
|
||||
msgstr "使用浏览器内置同步功能增强 Gist 同步使用体验"
|
||||
|
||||
msgid "options_syncEnableForce"
|
||||
msgstr "下载云端版本"
|
||||
|
||||
|
@ -5,6 +5,9 @@ Promise.longStackTraces()
|
||||
OmegaTargetCurrent.Log = Object.create(OmegaTargetCurrent.Log)
|
||||
Log = OmegaTargetCurrent.Log
|
||||
|
||||
|
||||
BUILTINSYNCKEY = 'zeroOmegaSync'
|
||||
|
||||
# TODO 将来可能代码需要重构下,这里写得有点乱. (suziwen1@gmail.com)
|
||||
globalThis.isBrowserRestart = globalThis.startupCheck is undefined
|
||||
globalThis.hasStartupCheck = not globalThis.isBrowserRestart
|
||||
@ -212,7 +215,10 @@ zeroBackground = (zeroStorage, opts) ->
|
||||
|
||||
if chrome?.storage?.sync or browser?.storage?.sync
|
||||
syncStorage = new OmegaTargetCurrent.SyncStorage('sync', state)
|
||||
sync = new OmegaTargetCurrent.OptionsSync(syncStorage)
|
||||
builtInSyncStorage = new OmegaTargetCurrent.Storage('sync')
|
||||
sync = new OmegaTargetCurrent.OptionsSync(
|
||||
syncStorage, builtInSyncStorage, state
|
||||
)
|
||||
sync.transformValue = OmegaTargetCurrent.Options.transformValueForSync
|
||||
|
||||
proxyImpl = OmegaTargetCurrent.proxy.getProxyImpl(Log)
|
||||
@ -228,7 +234,46 @@ zeroBackground = (zeroStorage, opts) ->
|
||||
if chrome.runtime.id != OmegaTargetCurrent.SwitchySharp.extId and false
|
||||
options.switchySharp = new OmegaTargetCurrent.SwitchySharp()
|
||||
options.switchySharp.monitor()
|
||||
|
||||
if sync and options and builtInSyncStorage
|
||||
builtInSyncStorage.watch [
|
||||
BUILTINSYNCKEY
|
||||
], (changes, opts = {}) ->
|
||||
builtInSyncConfig = changes[BUILTINSYNCKEY]
|
||||
if builtInSyncConfig
|
||||
{gistId, gistToken, lastGistCommit} = builtInSyncConfig
|
||||
state.set({gistId, gistToken})
|
||||
if sync.enabled
|
||||
console.log('check gist change', lastGistCommit)
|
||||
sync.init({gistId, gistToken})
|
||||
state.get({
|
||||
'lastGistCommit': ''
|
||||
}).then((syncConfig) ->
|
||||
if syncConfig.lastGistCommit isnt lastGistCommit
|
||||
console.log(
|
||||
'no match last gist commit, will check change',
|
||||
syncConfig.lastGistCommit
|
||||
)
|
||||
sync.checkChange()
|
||||
)
|
||||
else
|
||||
# try to enable sync
|
||||
state.get({
|
||||
'syncOptions': ''
|
||||
'lastGistCommit': ''
|
||||
}).then((syncConfig) ->
|
||||
return if syncConfig.lastGistCommit is lastGistCommit
|
||||
if syncConfig.syncOptions in ['pristine', 'conflict']
|
||||
state.set({
|
||||
syncOptions: 'conflict'
|
||||
}).then( ->
|
||||
options.setOptionsSync(true, {
|
||||
gistId,
|
||||
gistToken,
|
||||
useBuiltInSync: true,
|
||||
force: true
|
||||
})
|
||||
)
|
||||
)
|
||||
tabs = new OmegaTargetCurrent.ChromeTabs(actionForUrl)
|
||||
tabs.watch()
|
||||
|
||||
|
@ -7,6 +7,7 @@ isPulling = false
|
||||
isPushing = false
|
||||
|
||||
state = null
|
||||
optionsSync = null
|
||||
|
||||
mainLetters = ['Z','e', 'r', 'o', 'O', 'm','e', 'g', 'a']
|
||||
optionFilename = mainLetters.concat(['.json']).join('')
|
||||
@ -97,7 +98,7 @@ processPush = (syncStore) ->
|
||||
processPush.sequence.push(syncStore)
|
||||
return if isPushing
|
||||
isPushing = true
|
||||
_processPush()
|
||||
setTimeout(_processPush, 600) # use timeout to merge push
|
||||
|
||||
processPush.sequence = []
|
||||
|
||||
@ -155,11 +156,16 @@ updateGist = (gistId, options) ->
|
||||
).then((data) ->
|
||||
if data.message
|
||||
throw data.message
|
||||
lastGistCommit = data.history[0]?.version
|
||||
state?.set({
|
||||
'lastGistCommit': data.history[0]?.version
|
||||
'lastGistCommit': lastGistCommit
|
||||
'lastGistState': 'success'
|
||||
'lastGistSync': Date.now()
|
||||
}).then( ->
|
||||
optionsSync?.updateBuiltInSyncConfigIf({
|
||||
lastGistCommit
|
||||
})
|
||||
)
|
||||
return data
|
||||
).catch((e) ->
|
||||
state?.set({
|
||||
@ -262,6 +268,8 @@ class ChromeSyncStorage extends OmegaTarget.Storage
|
||||
# param(withRemoteData) retrive gist file content
|
||||
##
|
||||
init: (args) ->
|
||||
optionsSync = args.optionsSync
|
||||
state = args.state
|
||||
gistId = args.gistId || ''
|
||||
if gistId.indexOf('/') >= 0
|
||||
# get gistId from url `https://gist.github.com/{username}/{gistId}`
|
||||
|
@ -101,8 +101,9 @@ class Options
|
||||
'gistToken': ''
|
||||
}).then(({syncOptions, gistId, gistToken}) =>
|
||||
unless gistId
|
||||
unless syncOptions is 'disabled'
|
||||
syncOptions = 'pristine'
|
||||
@_state.set({'syncOptions': 'pristine'})
|
||||
@_state.set({'syncOptions': syncOptions})
|
||||
@sync.enabled = syncOptions is 'sync'
|
||||
unless @sync.enabled
|
||||
@_storage.get(null)
|
||||
@ -182,6 +183,8 @@ class Options
|
||||
###
|
||||
init: (startupCheck = -> true) ->
|
||||
# startupCheck 一定要放在 isBrowserRestart 后面
|
||||
# startupProfileName 如果为空,就使用当前的 currentProfileName
|
||||
# 如果没有 currentProfileName, 就使用默认的 fallbackProfileName
|
||||
# TODO (suziwen1@gmail.com)
|
||||
# 1. 好像有 bug , 一直没法重现,但就是很不经意就能出现,概率很小的样子
|
||||
# 2. 有全局变量,容易污染代码,需要重构初始化流程
|
||||
@ -189,12 +192,17 @@ class Options
|
||||
if globalThis.isBrowserRestart and
|
||||
startupCheck() and
|
||||
@_options['-startupProfileName']
|
||||
console.log(
|
||||
'apply browser restart startup profile',
|
||||
@_options['-startupProfileName']
|
||||
)
|
||||
@applyProfile(@_options['-startupProfileName'])
|
||||
else
|
||||
@_state.get({
|
||||
'currentProfileName': @fallbackProfileName
|
||||
'isSystemProfile': false
|
||||
}).then (st) =>
|
||||
console.log('apply init startup profile', st)
|
||||
if st['isSystemProfile']
|
||||
@applyProfile('system')
|
||||
else
|
||||
@ -208,7 +216,7 @@ class Options
|
||||
).then => @getAll()
|
||||
|
||||
@ready.then =>
|
||||
@sync.requestPush(@_options) if @sync?.enabled
|
||||
#@sync.requestPush(@_options) if @sync?.enabled
|
||||
|
||||
@_state.get({'firstRun': ''}).then ({firstRun}) =>
|
||||
@onFirstRun(firstRun) if firstRun
|
||||
@ -296,14 +304,20 @@ class Options
|
||||
reset: (options) ->
|
||||
@log.method('Options#reset', this, arguments)
|
||||
options ?= @getDefaultOptions()
|
||||
@upgrade(@parseOptions(options)).then ([opt]) =>
|
||||
_options = @parseOptions(options)
|
||||
@upgrade(_options).then ([opt]) =>
|
||||
# Disable syncing when resetting to avoid affecting sync storage.
|
||||
@sync.enabled = false if @sync?
|
||||
@_state.remove(['syncOptions'])
|
||||
@_watchStop?()
|
||||
@_watchStop = null
|
||||
@_storage.remove().then(=>
|
||||
@_storage.set(opt)
|
||||
).then =>
|
||||
).then( =>
|
||||
@init()
|
||||
).then =>
|
||||
if _options['-startupProfileName']
|
||||
@applyProfile(_options['-startupProfileName'])
|
||||
|
||||
###*
|
||||
# Called on the first initialization of options.
|
||||
@ -1055,7 +1069,7 @@ class Options
|
||||
}).then ({syncOptions, lastGistCommit}) =>
|
||||
if not enabled
|
||||
if syncOptions == 'sync'
|
||||
@_state.set({'syncOptions': 'pristine'})
|
||||
@_state.set({'syncOptions': 'disabled'})
|
||||
@sync.enabled = false
|
||||
@_syncWatchStop?()
|
||||
@_syncWatchStop = null
|
||||
@ -1082,9 +1096,26 @@ class Options
|
||||
if syncOptions == 'conflict'
|
||||
# Try to re-init options from sync.
|
||||
@sync.enabled = false
|
||||
@_storage.remove().then =>
|
||||
@_watchStop?()
|
||||
@_watchStop = null
|
||||
@_storage.remove().then( =>
|
||||
if remoteOptions
|
||||
console.log('flush data')
|
||||
@sync.flush({data: remoteOptions})
|
||||
).then =>
|
||||
@sync.enabled = true
|
||||
@init()
|
||||
@init().then( =>
|
||||
if remoteOptions
|
||||
if remoteOptions['-startupProfileName']
|
||||
console.log('apply startup')
|
||||
@applyProfile(remoteOptions['-startupProfileName'])
|
||||
if args.useBuiltInSync
|
||||
@sync.toggleBuiltInSync(true)
|
||||
else
|
||||
@sync.toggleBuiltInSync(false)
|
||||
).then( =>
|
||||
@updateProfile()
|
||||
)
|
||||
else
|
||||
if remoteOptions?.schemaVersion
|
||||
@sync.flush({data: remoteOptions}).then( =>
|
||||
@ -1097,6 +1128,10 @@ class Options
|
||||
@_syncWatchStop?()
|
||||
@sync.requestPush(@_options)
|
||||
@_syncWatchStop = @sync.watchAndPull(@_storage)
|
||||
if args.useBuiltInSync
|
||||
@sync.toggleBuiltInSync(true)
|
||||
else
|
||||
@sync.toggleBuiltInSync(false)
|
||||
return
|
||||
)
|
||||
|
||||
|
@ -6,6 +6,9 @@ Log = require './log'
|
||||
jsondiffpatch = require 'jsondiffpatch'
|
||||
TokenBucket = require('limiter').TokenBucket
|
||||
|
||||
|
||||
BUILTINSYNCKEY = 'zeroOmegaSync'
|
||||
|
||||
class OptionsSync
|
||||
@TokenBucket: TokenBucket
|
||||
|
||||
@ -31,7 +34,15 @@ class OptionsSync
|
||||
###
|
||||
storage: null
|
||||
|
||||
constructor: (@storage, @_bucket) ->
|
||||
###*
|
||||
# Use browser built-in sync to enhance gist sync function
|
||||
# @type Storage
|
||||
###
|
||||
builtInSyncStorage: null
|
||||
|
||||
state: null
|
||||
|
||||
constructor: (@storage, @builtInSyncStorage, @state, @_bucket) ->
|
||||
@_pending = {}
|
||||
@_bucket ?= new TokenBucket(10, 10, 'minute', null)
|
||||
@_bucket.clear ?= =>
|
||||
@ -207,12 +218,45 @@ class OptionsSync
|
||||
doPull()
|
||||
else
|
||||
pullScheduled = setTimeout(doPull, @pullThrottle)
|
||||
toggleBuiltInSync: (useBuiltInSync) ->
|
||||
@getBuiltInSyncConfig().then((builtInSyncConfig) =>
|
||||
@state.get({
|
||||
'gistId': '',
|
||||
'gistToken': '',
|
||||
'lastGistCommit': ''
|
||||
}).then((syncConfig) =>
|
||||
if useBuiltInSync is undefined
|
||||
useBuiltInSync = !builtInSyncConfig
|
||||
if useBuiltInSync is true
|
||||
_obj = {}
|
||||
_obj[BUILTINSYNCKEY] = syncConfig
|
||||
@builtInSyncStorage.set(_obj)
|
||||
else
|
||||
@builtInSyncStorage.remove(BUILTINSYNCKEY)
|
||||
)
|
||||
)
|
||||
getBuiltInSyncConfig: ->
|
||||
@builtInSyncStorage.get(BUILTINSYNCKEY).then((_obj) ->
|
||||
return _obj[BUILTINSYNCKEY]
|
||||
)
|
||||
updateBuiltInSyncConfigIf: (_builtInSyncConfig) ->
|
||||
@getBuiltInSyncConfig().then((builtInSyncConfig) =>
|
||||
if !!builtInSyncConfig
|
||||
newBuiltInSyncConfig = Object.assign(
|
||||
{}, builtInSyncConfig, _builtInSyncConfig
|
||||
)
|
||||
_obj = {}
|
||||
_obj[BUILTINSYNCKEY] = newBuiltInSyncConfig
|
||||
@builtInSyncStorage.set(_obj)
|
||||
)
|
||||
checkChange: ->
|
||||
@storage.checkChange({
|
||||
immediately: true
|
||||
force: true
|
||||
})
|
||||
init: (args) ->
|
||||
args.optionsSync = this
|
||||
args.state = @state
|
||||
@storage.init(args)
|
||||
destroy: ->
|
||||
@storage.destroy()
|
||||
|
@ -2,6 +2,7 @@ angular.module('omega').controller 'IoCtrl', (
|
||||
$scope, $rootScope, $window, $http, omegaTarget, downloadFile
|
||||
) ->
|
||||
|
||||
$scope.useBuiltInSync = true
|
||||
getGistId = (gistUrl = '') ->
|
||||
# get gistId from url `https://gist.github.com/{username}/{gistId}`
|
||||
# or directly gistId
|
||||
@ -32,7 +33,7 @@ angular.module('omega').controller 'IoCtrl', (
|
||||
plainOptions = angular.fromJson(angular.toJson($rootScope.options))
|
||||
content = JSON.stringify(plainOptions)
|
||||
blob = new Blob [content], {type: "text/plain;charset=utf-8"}
|
||||
downloadFile(blob, "OmegaOptions.bak")
|
||||
downloadFile(blob, "Zero" + """OmegaOptions.bak""")
|
||||
|
||||
$scope.importSuccess = ->
|
||||
$rootScope.showAlert(
|
||||
@ -89,6 +90,7 @@ angular.module('omega').controller 'IoCtrl', (
|
||||
return
|
||||
args.gistId = $scope.gistId
|
||||
args.gistToken = $scope.gistToken
|
||||
args.useBuiltInSync = $scope.useBuiltInSync
|
||||
$scope.enableOptionsSyncing = true
|
||||
omegaTarget.setOptionsSync(true, args).then( ->
|
||||
$window.location.reload()
|
||||
|
@ -59,6 +59,10 @@ section.settings-group
|
||||
a(href="https://github.com/settings/tokens/new" role="button" target="_blank")
|
||||
| {{ 'Create a token that manages the Gist.(Only gist permission is required.)'}}
|
||||
div(ng-show='syncOptions == "pristine" || syncOptions == "disabled"')
|
||||
div.checkbox
|
||||
label
|
||||
input#use-built-in-sync-enhance(type='checkbox' ng-model='useBuiltInSync')
|
||||
span {{'options_useBuiltInSyncEnhance' | tr}}
|
||||
p.help-block(omega-html='"options_syncPristineHelp" | tr')
|
||||
p
|
||||
button.btn.btn-default(ng-click='enableOptionsSync()' ladda='enableOptionsSyncing' data-spinner-color="currentColor")
|
||||
@ -89,6 +93,10 @@ section.settings-group
|
||||
= ' '
|
||||
| {{'options_syncDisable' | tr}}
|
||||
div(ng-show='syncOptions == "conflict"')
|
||||
div.checkbox
|
||||
label
|
||||
input#use-built-in-sync-enhance(type='checkbox' ng-model='useBuiltInSync')
|
||||
span {{'options_useBuiltInSyncEnhance' | tr}}
|
||||
p.alert.alert-danger.width-limit
|
||||
span.glyphicon.glyphicon-info-sign
|
||||
= ' '
|
||||
|
Loading…
Reference in New Issue
Block a user