-
Notifications
You must be signed in to change notification settings - Fork 287
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
apply new sync / auth logic & migrate functions
- Loading branch information
Showing
17 changed files
with
306 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
export const PICKED_TAB_PROPS = ['url', 'title', 'favIconUrl', 'pinned'] | ||
export const PICKED_LIST_RPOPS = ['_id', 'tabs', 'title', 'time', 'pinned', 'expand', 'color'] | ||
export const SYNCED_LIST_PROPS = ['_id', 'tabs', 'title', 'time', 'pinned', 'color'] | ||
|
||
export const TOKEN_KEY = 'token' | ||
export const AUTH_HEADER = 'auth' | ||
|
||
export const END_FRONT = 'front' | ||
export const END_BACKGROUND = 'background' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,124 @@ | ||
import _ from 'lodash' | ||
import browser from 'webextension-polyfill' | ||
import { | ||
SYNCED_LIST_PROPS, | ||
END_FRONT, | ||
END_BACKGROUND, | ||
} from './constants' | ||
|
||
const cache = { lists: null, ops: null } | ||
const getStorage = async () => { | ||
if (cache.lists && cache.ops) return cache | ||
const {lists, ops} = await browser.storage.local.get(['lists', 'ops']) | ||
cache.lists = lists | ||
cache.ops = ops | ||
cache.lists = lists || [] | ||
cache.ops = ops || [] | ||
return cache | ||
} | ||
const compressOps = ops => { | ||
const removed = [] | ||
const updated = {} | ||
const finalOps = [] | ||
console.log(ops) | ||
for (let i = ops.length - 1; i > -1; i -= 1) { | ||
const op = ops[i] | ||
// ignore all actions for the list if that list will be removed finally | ||
if (op.args && typeof op.args[0] === 'object' && removed.includes(op.args[0]._id) | ||
|| typeof op.args[0] === 'string' && removed.includes(op.args[0])) continue | ||
|
||
if (op.method === 'removeListById') { | ||
removed.push(op.args[0]) | ||
finalOps.unshift(op) | ||
} else if (op.method === 'updateListById') { | ||
// keep the final result of every property if a list will be updated | ||
if (updated[op.args[0]]) { | ||
for (const key in op.args[1]) { | ||
if (key in updated[op.args[0]]) continue | ||
updated[op.args[0]][key] = op.args[1][key] | ||
} | ||
continue | ||
} else { | ||
updated[op.args[0]] = Object.assign({}, op.args[1]) | ||
finalOps.unshift({method: 'updateListById', args: [op.args[0], updated[op.args[0]]]}) | ||
} | ||
} else if (op.method === 'changeListOrderRelatively') { | ||
// combine the value if a list is reordered continuously | ||
if (i > 0 && ops[i - 1].method === 'changeListOrderRelatively' && op.args[0] === ops[i - 1].args[0]) { | ||
ops[i - 1].args[1] += ops[i].args[1] | ||
} else finalOps.unshift(op) | ||
} else { | ||
// do nothing if add a list | ||
finalOps.unshift(op) | ||
} | ||
} | ||
return finalOps | ||
} | ||
const saveStorage = _.debounce(async () => { | ||
cache.ops = compressOps(cache.ops) | ||
await browser.storage.local.set(cache) | ||
cache.lists = cache.ops = null | ||
await browser.runtime.sendMessage({refresh: true}) | ||
}, 5000) | ||
const manager = {} | ||
manager.modifier = { | ||
// lists modifier (return true if need to add ops) | ||
manager.modifiers = { | ||
addList(lists, [list]) { | ||
lists.unshift(list) | ||
return true | ||
}, | ||
updateListById(lists, [listId, newList]) { | ||
const normal = SYNCED_LIST_PROPS.some(k => Object.keys(newList).includes(k)) | ||
for (const list of lists) { | ||
if (list._id !== listId) continue | ||
for (const [k, v] of Object.entries(newList)) { | ||
list[k] = v | ||
} | ||
return | ||
return normal | ||
} | ||
}, | ||
removeListById(lists, [listId]) { | ||
const index = lists.findIndex(list => list._id === listId) | ||
lists.splice(index, 1) | ||
return true | ||
}, | ||
changeListOrderRelatively(lists, [listId, diff]) { | ||
const index = lists.findIndex(list => list._id === listId) | ||
const [list] = lists.splice(index, 1) | ||
lists.splice(index + diff, 0, list) | ||
return true | ||
}, | ||
} | ||
const addEventListener = () => browser.runtime.onMessage.addListener(({listModifed}) => { | ||
const addEventListener = (receiveFrom, callback) => browser.runtime.onMessage.addListener(({listModifed, from}) => { | ||
if (receiveFrom !== from) return | ||
if (!listModifed) return | ||
const {method, args} = listModifed | ||
manager[method](args) | ||
return callback(method, args) | ||
}) | ||
const genMethods = isBackground => { | ||
for (const [name, func] of Object.entries(manager.methods)) { | ||
manager[name] = isBackground ? async (...args) => { | ||
for (const [name, func] of Object.entries(manager.modifiers)) { | ||
manager[name] = isBackground ? async (...args) => { // for background | ||
console.debug('[list manager] modify list:', name, ...args) | ||
const {lists, ops} = await getStorage() | ||
ops.push({method: name, args, time: Date.now()}) | ||
func(lists, args) | ||
if (func(lists, args)) ops.push({method: name, args, time: Date.now()}) | ||
saveStorage() | ||
} : async (...args) => { | ||
await browser.runtime.sendMessage({listModifed: {method: name, args}}) | ||
await browser.runtime.sendMessage({listModifed: {method: name, args}, from: END_BACKGROUND}) | ||
} : async (...args) => { // for front end | ||
console.debug('[list manager] call to modify list:', name, ...args) | ||
await browser.runtime.sendMessage({listModifed: {method: name, args}, from: END_FRONT}) | ||
} | ||
} | ||
} | ||
manager.init = async () => { | ||
if (manager.inited) return | ||
const background = await browser.runtime.getBackgroundPage() | ||
const isBackground = window === background | ||
if (isBackground) await addEventListener() | ||
if (isBackground) await addEventListener(END_FRONT, (method, args) => manager[method](...args)) | ||
genMethods(isBackground) | ||
manager.inited = true | ||
} | ||
const receiver = [] | ||
manager.receiveBackgroundModified = async lists => { | ||
if (receiver.includes(lists)) return | ||
receiver.push(lists) | ||
await addEventListener(END_BACKGROUND, (method, args) => manager.modifiers[method](lists, args)) | ||
} | ||
export default manager |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import _ from 'lodash' | ||
import {normalize} from './list' | ||
import options from './options' | ||
import {genObjectId} from './utils' | ||
import listManager from './listManager' | ||
import browser from 'webextension-polyfill' | ||
listManager.init() | ||
const migrate = async () => { | ||
const {version} = await browser.storage.local.get('version') | ||
const {version: currentVersion} = browser.runtime.getManifest() | ||
if (version !== currentVersion) await browser.storage.local.set({version: currentVersion}) | ||
if (version >= '1.4.0') return | ||
// every list need an ID | ||
const {lists} = await browser.storage.local.get('lists') | ||
const {0: listsWithoutId, 1: listsWithId} = _.groupBy(lists.map(normalize), list => +!!list._id) | ||
await browser.storage.local.set({lists: listsWithId}) | ||
|
||
for (const list of listsWithoutId.reverse()) { | ||
list._id = genObjectId() | ||
await listManager.addList(list) | ||
} | ||
// remove depracated options | ||
const {opts} = await browser.storage.local.get('opts') | ||
if (opts) { | ||
await browser.storage.local.set({opts: _.pick(opts, _.keys(options.getDefaultOptions()))}) | ||
} | ||
} | ||
|
||
export default migrate |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.