Enhance your Gist sync experience with built-in browser sync

This commit is contained in:
proxy.zeroomega 2024-10-05 14:22:41 +08:00
parent bc69662911
commit f5f987253c
8 changed files with 163 additions and 15 deletions

View File

@ -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"

View File

@ -413,6 +413,9 @@ msgstr "选项同步 (测试中)"
msgid "options_syncEnable"
msgstr "启用同步"
msgid "options_useBuiltInSyncEnhance"
msgstr "使用浏览器内置同步功能增强 Gist 同步使用体验"
msgid "options_syncEnableForce"
msgstr "下载云端版本"

View File

@ -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()

View File

@ -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}`

View File

@ -101,8 +101,9 @@ class Options
'gistToken': ''
}).then(({syncOptions, gistId, gistToken}) =>
unless gistId
syncOptions = 'pristine'
@_state.set({'syncOptions': 'pristine'})
unless syncOptions is 'disabled'
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
)

View File

@ -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()

View File

@ -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()

View File

@ -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
= ' '