Skip to content

Commit d651f13

Browse files
committed
arch: rewrite code and use modules everywhere
and fix quite a few typo bugs and logic issues, including issues up to #381
1 parent dcba6d9 commit d651f13

File tree

116 files changed

+7702
-7481
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+7702
-7481
lines changed

.eslintrc.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@
109109
"radix": "off",
110110
"space-before-function-paren": "off",
111111
"spaced-comment": [ "error", "always", {
112-
"line": { "markers": [ "/" ] },
113-
"block": { "exceptions": [ "#__NOINLINE__", "#__INLINE__" ] }
112+
"line": { "markers": [ "/", "#region" ], "exceptions": ["#endregion"] },
113+
"block": { "exceptions": [ "#__NOINLINE__", "#__INLINE__" ], "balanced": false }
114114
} ],
115115
"use-isnan": "error",
116116
"valid-typeof": "off"

_locales/en/messages.json

+8-296
Large diffs are not rendered by default.

_locales/fr/messages.json

+1-226
Large diffs are not rendered by default.

_locales/zh/messages.json

+4-436
Large diffs are not rendered by default.

_locales/zh_CN/messages.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
},
55
"description": {
66
"message": "一款支持全键盘操作浏览器的辅助工具,只用键盘即可点击任意链接、切换标签页和快速搜索任意内容,支持自定义快捷键和调整操作细节"
7-
}
7+
},
8+
"i18n": { "message": "zh" }
89
}

_locales/zh_TW/messages.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
},
55
"description": {
66
"message": "一款支持全鍵盤操作瀏覽器的輔助工具,只用鍵盤即可點擊任意鏈結、切換分頁和快速搜索任意內容,支持自定義快速鍵和調整操作細節"
7-
}
7+
},
8+
"i18n": { "message": "zh" }
89
}

background/action_icon.ts

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import {
2+
framesForTab_, CurCVer_, OnChrome, set_setIcon_, setIcon_, set_iconData_, iconData_, blank_
3+
} from "./store"
4+
import * as BgUtils_ from "./utils"
5+
import * as settings_ from "./settings"
6+
import { trans_ } from "./i18n"
7+
import { browser_, runtimeError_ } from "./browser"
8+
import { asyncIterFrames_ } from "./ports"
9+
10+
const knownIcons_ = OnChrome ? As_<readonly [IconNS.BinaryPath, IconNS.BinaryPath, IconNS.BinaryPath]>([
11+
"icons/enabled.bin", "icons/partial.bin", "icons/disabled.bin"
12+
]) : As_<readonly [IconNS.ImagePath, IconNS.ImagePath, IconNS.ImagePath]>([
13+
{ 19: "/icons/enabled_19.png", 38: "/icons/enabled_38.png" },
14+
{ 19: "/icons/partial_19.png", 38: "/icons/partial_38.png" },
15+
{ 19: "/icons/disabled_19.png", 38: "/icons/disabled_38.png" }
16+
])
17+
18+
export const browserAction_ = (browser_ as any).action as undefined || browser_.browserAction
19+
let tabIds_cr_: Map<Frames.ValidStatus, number[] | null> | null
20+
let mayShowIcons = true
21+
22+
const onerror = (err: any): void => {
23+
if (!mayShowIcons) { return }
24+
mayShowIcons = false;
25+
console.log("Can not access binary icon data:", err);
26+
set_setIcon_(blank_)
27+
browserAction_.setTitle({ title: trans_("name") + "\n\nFailed in showing dynamic icons." })
28+
}
29+
30+
const loadBinaryImagesAndSetIcon_cr = (type: Frames.ValidStatus): void => {
31+
const path = knownIcons_[type] as IconNS.BinaryPath;
32+
const loadFromRawArray = (array: ArrayBuffer): void => {
33+
const uint8Array = new Uint8ClampedArray(array), firstSize = array.byteLength / 5,
34+
small = (Math.sqrt(firstSize / 4) | 0) as IconNS.ValidSizes, large = (small + small) as IconNS.ValidSizes,
35+
cache = BgUtils_.safeObj_() as IconNS.IconBuffer;
36+
cache[small] = new ImageData(uint8Array.subarray(0, firstSize), small, small);
37+
cache[large] = new ImageData(uint8Array.subarray(firstSize), large, large);
38+
iconData_![type] = cache;
39+
const arr = tabIds_cr_!.get(type)!
40+
tabIds_cr_!.delete(type)
41+
for (let w = 0, h = arr.length; w < h; w++) {
42+
framesForTab_.has(arr[w]) && setIcon_(arr[w], type, true)
43+
}
44+
};
45+
if (Build.MinCVer >= BrowserVer.MinFetchExtensionFiles || CurCVer_ >= BrowserVer.MinFetchExtensionFiles) {
46+
const p = fetch(path).then(r => r.arrayBuffer()).then(loadFromRawArray)
47+
if (!Build.NDEBUG) { p.catch(onerror) }
48+
} else {
49+
const req = new XMLHttpRequest() as ArrayXHR
50+
req.open("GET", path, true)
51+
req.responseType = "arraybuffer"
52+
req.onload = function (this: typeof req) { loadFromRawArray(this.response) }
53+
if (!Build.NDEBUG) { req.onerror = onerror }
54+
req.send()
55+
}
56+
}
57+
58+
export const toggleIconBuffer_ = (): void => {
59+
const enabled = settings_.get_("showActionIcon")
60+
if (enabled === !!iconData_) { return }
61+
const iter = ({ cur_: { s: sender } }: Frames.Frames): void => {
62+
if (sender.status_ !== Frames.Status.enabled) {
63+
setIcon_(sender.tabId_, enabled ? sender.status_ : Frames.Status.enabled)
64+
}
65+
}
66+
const cond = (): boolean => settings_.get_("showActionIcon") === enabled
67+
if (!enabled) {
68+
setTimeout((): void => {
69+
if (settings_.get_("showActionIcon") || iconData_ == null) { return }
70+
set_iconData_(null)
71+
if (OnChrome) { tabIds_cr_ = null }
72+
else {
73+
asyncIterFrames_(iter, cond)
74+
}
75+
}, 200);
76+
return;
77+
}
78+
if (!OnChrome) {
79+
set_iconData_(1 as never)
80+
} else {
81+
set_iconData_([null, null, null])
82+
tabIds_cr_ = new Map()
83+
}
84+
// only do partly updates: ignore "rare" cases like `sender.s` is enabled but the real icon isn't
85+
asyncIterFrames_(iter, cond)
86+
}
87+
88+
/** Firefox does not use ImageData as inner data format
89+
* * https://dxr.mozilla.org/mozilla-central/source/toolkit/components/extensions/schemas/manifest.json#577
90+
* converts ImageData objects in parameters into data:image/png,... URLs
91+
* * https://dxr.mozilla.org/mozilla-central/source/browser/components/extensions/parent/ext-browserAction.js#483
92+
* builds a css text of "--webextension-***: url(icon-url)",
93+
* and then set the style of an extension's toolbar button to it
94+
*/
95+
export const doSetIcon_: typeof setIcon_ = !OnChrome ? (tabId, type): void => {
96+
tabId < 0 || browserAction_.setIcon({ tabId, path: knownIcons_[type]! })
97+
} : (tabId: number, type: Frames.ValidStatus, isLater?: true): void => {
98+
let data: IconNS.IconBuffer | null | undefined;
99+
if (tabId < 0) { /* empty */ }
100+
else if (data = iconData_![type]) {
101+
const f = browserAction_.setIcon
102+
const args: Parameters<typeof f>[0] = { tabId, imageData: data }
103+
isLater ? f(args, runtimeError_) : f(args);
104+
} else if (tabIds_cr_!.has(type)) {
105+
tabIds_cr_!.get(type)!.push(tabId)
106+
} else {
107+
setTimeout(loadBinaryImagesAndSetIcon_cr, 0, type);
108+
tabIds_cr_!.set(type, [tabId])
109+
}
110+
}

0 commit comments

Comments
 (0)