From 87ae3446774f04cb1fe0fb79eff256353b516fe1 Mon Sep 17 00:00:00 2001 From: "proxy.zeroomega" Date: Sun, 1 Sep 2024 10:25:23 +0800 Subject: [PATCH] report issuses from context menu;migrate data upgrade; --- .../overlay/x-background.js | 5 +- .../src/coffee/background.coffee | 31 +++ .../src/coffee/background_preload.coffee | 13 ++ .../src/coffee/omega_debug.coffee | 2 +- omega-web/lib/compare-versions.js | 219 ++++++++++++++++++ 5 files changed, 267 insertions(+), 3 deletions(-) create mode 100644 omega-web/lib/compare-versions.js diff --git a/omega-target-chromium-extension/overlay/x-background.js b/omega-target-chromium-extension/overlay/x-background.js index 2fa0002..3003e6c 100644 --- a/omega-target-chromium-extension/overlay/x-background.js +++ b/omega-target-chromium-extension/overlay/x-background.js @@ -2,14 +2,15 @@ import zeroLocalStorage from "./localstorage-polyfill.js" import ZeroLogFactory from './log.js' import ZeroIndexedDBFactory from './indexedDB.js' +import "./lib/compare-versions.js" import "./js/background_preload.js" import "./lib/idb-keyval.js" import "./lib/moment-with-locales.js" import "./lib/csso.js" import "./js/log_error.js" -import "./log.js" +//import "./log.js" //import "./lib/FileSaver/FileSaver.min.js" -//import "./js/omega_debug.js" +import "./js/omega_debug.js" import "./js/omega_pac.min.js" import "./js/omega_target.min.js" import "./js/omega_target_chromium_extension.min.js" diff --git a/omega-target-chromium-extension/src/coffee/background.coffee b/omega-target-chromium-extension/src/coffee/background.coffee index 8475da9..db21023 100644 --- a/omega-target-chromium-extension/src/coffee/background.coffee +++ b/omega-target-chromium-extension/src/coffee/background.coffee @@ -7,11 +7,42 @@ Log = OmegaTargetCurrent.Log # TODO 将来可能代码需要重构下,这里写得有点乱. (suziwen1@gmail.com) globalThis.isBrowserRestart = globalThis.startupCheck is undefined +globalThis.hasStartupCheck = not globalThis.isBrowserRestart startupCheck = globalThis.startupCheck ?= -> true +options = null chrome.runtime.onStartup.addListener -> globalThis.isBrowserRestart = true +upgradeMigrateFn = (details) -> + if details.reason is 'update' + manifest = chrome.runtime.getManifest() + currentVersion = manifest.version + previousVersion = details.previousVersion + if compareVersions.compare currentVersion, previousVersion, '>' + if compareVersions.compare '3.3.0', currentVersion, '>' + options.ready.then( -> + chrome.storage.sync.clear() + chrome.storage.local.clear() + idbKeyval.clear() + ) + else + switch currentVersion + when '3.3.10' + options.ready.then( -> + # TODO check + true + ) + when '3.3.11' + options.ready.then( -> + # TODO clear all disabled syncOptions + true + ) +chrome.runtime.onInstalled.addListener( (details) -> + setTimeout(-> + upgradeMigrateFn(details) + , 2) +) dispName = (name) -> chrome.i18n.getMessage('profile_' + name) || name diff --git a/omega-target-chromium-extension/src/coffee/background_preload.coffee b/omega-target-chromium-extension/src/coffee/background_preload.coffee index 9d4a17b..5ffe53b 100644 --- a/omega-target-chromium-extension/src/coffee/background_preload.coffee +++ b/omega-target-chromium-extension/src/coffee/background_preload.coffee @@ -14,6 +14,13 @@ createContextMenu = -> contexts: ["action"] }) + chrome.contextMenus?.create({ + id: 'reportIssue' + title: chrome.i18n.getMessage('popup_reportIssues') + contexts: ["action"] + }) + + chrome.runtime.onInstalled.addListener( -> # We don't need this API. However its presence indicates that Chrome >= 35 # which provides info.checked we need in contextMenu callback. @@ -25,3 +32,9 @@ chrome.runtime.onInstalled.addListener( -> if browser?.proxy?.onRequest? #firefox bug fix? createContextMenu() + +chrome.contextMenus?.onClicked.addListener((info, tab) -> + switch info.menuItemId + when 'reportIssue' + OmegaDebug.reportIssue() +) diff --git a/omega-target-chromium-extension/src/coffee/omega_debug.coffee b/omega-target-chromium-extension/src/coffee/omega_debug.coffee index f7caa99..b8f8173 100644 --- a/omega-target-chromium-extension/src/coffee/omega_debug.coffee +++ b/omega-target-chromium-extension/src/coffee/omega_debug.coffee @@ -71,7 +71,7 @@ window.OmegaDebug = body ||= """ \n\n - SwitchyOmega #{env.projectVersion} + ZeroOmega #{env.projectVersion} #{env.userAgent} """ finalUrl = url + encodeURIComponent(body) diff --git a/omega-web/lib/compare-versions.js b/omega-web/lib/compare-versions.js new file mode 100644 index 0000000..687f4bf --- /dev/null +++ b/omega-web/lib/compare-versions.js @@ -0,0 +1,219 @@ +/*** + * source code: https://github.com/omichelsen/compare-versions + **/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.compareVersions = {})); +})(this, (function (exports) { 'use strict'; + + const semver = /^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i; + const validateAndParse = (version) => { + if (typeof version !== 'string') { + throw new TypeError('Invalid argument expected string'); + } + const match = version.match(semver); + if (!match) { + throw new Error(`Invalid argument not valid semver ('${version}' received)`); + } + match.shift(); + return match; + }; + const isWildcard = (s) => s === '*' || s === 'x' || s === 'X'; + const tryParse = (v) => { + const n = parseInt(v, 10); + return isNaN(n) ? v : n; + }; + const forceType = (a, b) => typeof a !== typeof b ? [String(a), String(b)] : [a, b]; + const compareStrings = (a, b) => { + if (isWildcard(a) || isWildcard(b)) + return 0; + const [ap, bp] = forceType(tryParse(a), tryParse(b)); + if (ap > bp) + return 1; + if (ap < bp) + return -1; + return 0; + }; + const compareSegments = (a, b) => { + for (let i = 0; i < Math.max(a.length, b.length); i++) { + const r = compareStrings(a[i] || '0', b[i] || '0'); + if (r !== 0) + return r; + } + return 0; + }; + + /** + * Compare [semver](https://semver.org/) version strings to find greater, equal or lesser. + * This library supports the full semver specification, including comparing versions with different number of digits like `1.0.0`, `1.0`, `1`, and pre-release versions like `1.0.0-alpha`. + * @param v1 - First version to compare + * @param v2 - Second version to compare + * @returns Numeric value compatible with the [Array.sort(fn) interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters). + */ + const compareVersions = (v1, v2) => { + // validate input and split into segments + const n1 = validateAndParse(v1); + const n2 = validateAndParse(v2); + // pop off the patch + const p1 = n1.pop(); + const p2 = n2.pop(); + // validate numbers + const r = compareSegments(n1, n2); + if (r !== 0) + return r; + // validate pre-release + if (p1 && p2) { + return compareSegments(p1.split('.'), p2.split('.')); + } + else if (p1 || p2) { + return p1 ? -1 : 1; + } + return 0; + }; + + /** + * Compare [semver](https://semver.org/) version strings using the specified operator. + * + * @param v1 First version to compare + * @param v2 Second version to compare + * @param operator Allowed arithmetic operator to use + * @returns `true` if the comparison between the firstVersion and the secondVersion satisfies the operator, `false` otherwise. + * + * @example + * ``` + * compare('10.1.8', '10.0.4', '>'); // return true + * compare('10.0.1', '10.0.1', '='); // return true + * compare('10.1.1', '10.2.2', '<'); // return true + * compare('10.1.1', '10.2.2', '<='); // return true + * compare('10.1.1', '10.2.2', '>='); // return false + * ``` + */ + const compare = (v1, v2, operator) => { + // validate input operator + assertValidOperator(operator); + // since result of compareVersions can only be -1 or 0 or 1 + // a simple map can be used to replace switch + const res = compareVersions(v1, v2); + return operatorResMap[operator].includes(res); + }; + const operatorResMap = { + '>': [1], + '>=': [0, 1], + '=': [0], + '<=': [-1, 0], + '<': [-1], + '!=': [-1, 1], + }; + const allowedOperators = Object.keys(operatorResMap); + const assertValidOperator = (op) => { + if (typeof op !== 'string') { + throw new TypeError(`Invalid operator type, expected string but got ${typeof op}`); + } + if (allowedOperators.indexOf(op) === -1) { + throw new Error(`Invalid operator, expected one of ${allowedOperators.join('|')}`); + } + }; + + /** + * Match [npm semver](https://docs.npmjs.com/cli/v6/using-npm/semver) version range. + * + * @param version Version number to match + * @param range Range pattern for version + * @returns `true` if the version number is within the range, `false` otherwise. + * + * @example + * ``` + * satisfies('1.1.0', '^1.0.0'); // return true + * satisfies('1.1.0', '~1.0.0'); // return false + * ``` + */ + const satisfies = (version, range) => { + // clean input + range = range.replace(/([><=]+)\s+/g, '$1'); + // handle multiple comparators + if (range.includes('||')) { + return range.split('||').some((r) => satisfies(version, r)); + } + else if (range.includes(' - ')) { + const [a, b] = range.split(' - ', 2); + return satisfies(version, `>=${a} <=${b}`); + } + else if (range.includes(' ')) { + return range + .trim() + .replace(/\s{2,}/g, ' ') + .split(' ') + .every((r) => satisfies(version, r)); + } + // if no range operator then "=" + const m = range.match(/^([<>=~^]+)/); + const op = m ? m[1] : '='; + // if gt/lt/eq then operator compare + if (op !== '^' && op !== '~') + return compare(version, range, op); + // else range of either "~" or "^" is assumed + const [v1, v2, v3, , vp] = validateAndParse(version); + const [r1, r2, r3, , rp] = validateAndParse(range); + const v = [v1, v2, v3]; + const r = [r1, r2 !== null && r2 !== void 0 ? r2 : 'x', r3 !== null && r3 !== void 0 ? r3 : 'x']; + // validate pre-release + if (rp) { + if (!vp) + return false; + if (compareSegments(v, r) !== 0) + return false; + if (compareSegments(vp.split('.'), rp.split('.')) === -1) + return false; + } + // first non-zero number + const nonZero = r.findIndex((v) => v !== '0') + 1; + // pointer to where segments can be >= + const i = op === '~' ? 2 : nonZero > 1 ? nonZero : 1; + // before pointer must be equal + if (compareSegments(v.slice(0, i), r.slice(0, i)) !== 0) + return false; + // after pointer must be >= + if (compareSegments(v.slice(i), r.slice(i)) === -1) + return false; + return true; + }; + + /** + * Validate [semver](https://semver.org/) version strings. + * + * @param version Version number to validate + * @returns `true` if the version number is a valid semver version number, `false` otherwise. + * + * @example + * ``` + * validate('1.0.0-rc.1'); // return true + * validate('1.0-rc.1'); // return false + * validate('foo'); // return false + * ``` + */ + const validate = (version) => typeof version === 'string' && /^[v\d]/.test(version) && semver.test(version); + /** + * Validate [semver](https://semver.org/) version strings strictly. Will not accept wildcards and version ranges. + * + * @param version Version number to validate + * @returns `true` if the version number is a valid semver version number `false` otherwise + * + * @example + * ``` + * validate('1.0.0-rc.1'); // return true + * validate('1.0-rc.1'); // return false + * validate('foo'); // return false + * ``` + */ + const validateStrict = (version) => typeof version === 'string' && + /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(version); + + exports.compare = compare; + exports.compareVersions = compareVersions; + exports.satisfies = satisfies; + exports.validate = validate; + exports.validateStrict = validateStrict; + +}));