parent
0a9155dcec
commit
164aa99eca
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,7 @@ import {
|
||||
Tab,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
MenuClickInfo,
|
||||
CHROME,
|
||||
} from "./browser";
|
||||
import { Bus } from "./bus";
|
||||
import { filterInSitu } from "./util";
|
||||
@ -27,6 +28,20 @@ const menus = typeof (_menus) !== "undefined" && _menus || _cmenus;
|
||||
|
||||
const GATHER = "/bundles/content-gather.js";
|
||||
|
||||
const CHROME_CONTEXTS = Object.freeze(new Set([
|
||||
"all",
|
||||
"audio",
|
||||
"browser_action",
|
||||
"editable",
|
||||
"frame",
|
||||
"image",
|
||||
"launcher",
|
||||
"link",
|
||||
"page",
|
||||
"page_action",
|
||||
"selection",
|
||||
"video",
|
||||
]));
|
||||
|
||||
async function runContentJob(tab: Tab, file: string, msg: any) {
|
||||
try {
|
||||
@ -83,11 +98,15 @@ class Handler {
|
||||
|
||||
async performSelection(options: SelectionOptions) {
|
||||
try {
|
||||
const toptions: any = {
|
||||
currentWindow: true,
|
||||
discarded: false,
|
||||
};
|
||||
if (!CHROME) {
|
||||
toptions.hidden = true;
|
||||
}
|
||||
const selectedTabs = options.allTabs ?
|
||||
await tabs.query({
|
||||
currentWindow: true,
|
||||
discarded: false,
|
||||
hidden: false}) as any[] :
|
||||
await tabs.query(toptions) as any[] :
|
||||
[options.tab];
|
||||
|
||||
const textLinks = await Prefs.get("text-links", true);
|
||||
@ -146,10 +165,18 @@ locale.then(() => {
|
||||
this.onClicked = this.onClicked.bind(this);
|
||||
const alls = new Map<string, string[]>();
|
||||
const mcreate = (options: any) => {
|
||||
if (CHROME) {
|
||||
delete options.icons;
|
||||
options.contexts = options.contexts.
|
||||
filter((e: string) => CHROME_CONTEXTS.has(e));
|
||||
if (!options.contexts.length) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (options.contexts.includes("all")) {
|
||||
alls.set(options.id, options.contexts);
|
||||
}
|
||||
return menus.create(options);
|
||||
menus.create(options);
|
||||
};
|
||||
mcreate({
|
||||
id: "DTARegularLink",
|
||||
@ -520,13 +547,21 @@ locale.then(() => {
|
||||
|
||||
function adjustAction(globalTurbo: boolean) {
|
||||
action.setPopup({
|
||||
popup: globalTurbo ? "" : null
|
||||
popup: globalTurbo ? "" : "/windows/popup.html"
|
||||
});
|
||||
action.setIcon({
|
||||
path: globalTurbo ? {
|
||||
16: "/style/button-turbo.png",
|
||||
32: "/style/button-turbo@2x.png",
|
||||
} : null
|
||||
} : {
|
||||
16: "/style/icon16.png",
|
||||
32: "/style/icon32.png",
|
||||
48: "/style/icon48.png",
|
||||
64: "/style/icon64.png",
|
||||
96: "/style/icon96.png",
|
||||
128: "/style/icon128.png",
|
||||
256: "/style/icon256.png"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -50,3 +50,5 @@ export const {storage} = polyfill;
|
||||
export const {tabs} = polyfill;
|
||||
export const {webNavigation} = polyfill;
|
||||
export const {windows} = polyfill;
|
||||
|
||||
export const CHROME = navigator.appVersion.includes("Chrome/");
|
||||
|
@ -9,6 +9,8 @@ declare let chrome: any;
|
||||
const CACHE_KEY = "_cached_locales";
|
||||
const CUSTOM_KEY = "_custom_locale";
|
||||
|
||||
const normalizer = /[^A-Za-z0-9_]/g;
|
||||
|
||||
interface JSONEntry {
|
||||
message: string;
|
||||
placeholders: any;
|
||||
@ -72,7 +74,7 @@ class Localization {
|
||||
}
|
||||
|
||||
localize(id: string, ...args: any[]) {
|
||||
const entry = this.strings.get(id);
|
||||
const entry = this.strings.get(id.replace(normalizer, "_"));
|
||||
if (!entry) {
|
||||
return "";
|
||||
}
|
||||
@ -121,7 +123,8 @@ function loadCached() {
|
||||
async function loadRawLocales() {
|
||||
// en is the base locale
|
||||
const langs = new Set<string>(["en"]);
|
||||
const ui = (browser.i18n || chrome.i18n).getUILanguage();
|
||||
const ui = (typeof browser !== "undefined" ? browser : chrome).
|
||||
i18n.getUILanguage();
|
||||
langs.add(ui);
|
||||
|
||||
// Try the base too
|
||||
|
@ -1,14 +1,14 @@
|
||||
"use strict";
|
||||
// License: MIT
|
||||
|
||||
import { downloads } from "./browser";
|
||||
import { downloads, CHROME } from "./browser";
|
||||
import { EventEmitter } from "../uikit/lib/events";
|
||||
import { PromiseSerializer } from "./pserializer";
|
||||
|
||||
const VERSION = 1;
|
||||
const STORE = "iconcache";
|
||||
// eslint-disable-next-line no-magic-numbers
|
||||
const CACHE_SIZES = [16, 32, 64, 127];
|
||||
const CACHE_SIZES = CHROME ? [16, 32] : [16, 32, 64, 127];
|
||||
|
||||
const BLACKLISTED = Object.freeze(new Set([
|
||||
"",
|
||||
@ -28,7 +28,8 @@ const BLACKLISTED = Object.freeze(new Set([
|
||||
]));
|
||||
|
||||
async function getIcon(size: number, manId: number) {
|
||||
const icon = new URL(await downloads.getFileIcon(manId, {size}));
|
||||
const raw = await downloads.getFileIcon(manId, {size});
|
||||
const icon = new URL(raw);
|
||||
if (icon.protocol === "data:") {
|
||||
const res = await fetch(icon.toString());
|
||||
const blob = await res.blob();
|
||||
|
@ -11,14 +11,16 @@ import { BaseDownload } from "./basedownload";
|
||||
import { PromiseSerializer } from "../pserializer";
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { Manager } from "./man";
|
||||
import { downloads } from "../browser";
|
||||
import { IconCache } from "../iconcache";
|
||||
import { downloads, CHROME } from "../browser";
|
||||
import { debounce } from "../../uikit/lib/util";
|
||||
|
||||
|
||||
const setShelfEnabled = downloads.setShelfEnabled || function() {
|
||||
// ignored
|
||||
};
|
||||
|
||||
const reenableShelf = debounce(() => setShelfEnabled(true), 1000, true);
|
||||
|
||||
type Header = {name: string; value: string};
|
||||
interface Options {
|
||||
conflictAction: string;
|
||||
@ -27,7 +29,7 @@ interface Options {
|
||||
url: string;
|
||||
method?: string;
|
||||
body?: string;
|
||||
incognito: boolean;
|
||||
incognito?: boolean;
|
||||
headers: Header[];
|
||||
}
|
||||
|
||||
@ -104,13 +106,15 @@ export class Download extends BaseDownload {
|
||||
saveAs: false,
|
||||
url: this.url,
|
||||
headers: [],
|
||||
incognito: this.private
|
||||
};
|
||||
if (!CHROME && this.private) {
|
||||
options.incognito = true;
|
||||
}
|
||||
if (this.postData) {
|
||||
options.body = this.postData;
|
||||
options.method = "POST";
|
||||
}
|
||||
if (this.referrer) {
|
||||
if (!CHROME && this.referrer) {
|
||||
options.headers.push({
|
||||
name: "Referer",
|
||||
value: this.referrer
|
||||
@ -135,12 +139,9 @@ export class Download extends BaseDownload {
|
||||
this.manager.addManId(
|
||||
this.manId = await downloads.download(options), this);
|
||||
}
|
||||
await IconCache.
|
||||
set(this.renamer.p_ext, this.manId).
|
||||
catch(console.error);
|
||||
}
|
||||
finally {
|
||||
setShelfEnabled(true);
|
||||
reenableShelf();
|
||||
}
|
||||
this.markDirty();
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import { donate, openPrefs } from "../windowutils";
|
||||
import { API } from "../api";
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { BaseDownload } from "./basedownload";
|
||||
import { IconCache } from "../iconcache";
|
||||
|
||||
type SID = {sid: number};
|
||||
type SIDS = {
|
||||
@ -63,10 +62,6 @@ export class ManagerPort {
|
||||
delete this.port;
|
||||
});
|
||||
|
||||
IconCache.on("cached", ext => {
|
||||
this.port.post("icon-cached", ext);
|
||||
});
|
||||
|
||||
this.port.post("active", this.manager.active);
|
||||
this.sendAll();
|
||||
}
|
||||
|
@ -8,9 +8,6 @@ import * as DEFAULT_ICONS from "../data/icons.json";
|
||||
const DONATE_URL = "https://www.downthemall.org/howto/donate/";
|
||||
const MANAGER_URL = "/windows/manager.html";
|
||||
|
||||
const IS_CHROME = navigator && navigator.userAgent.includes("Chrome");
|
||||
|
||||
|
||||
export async function mostRecentBrowser(): Promise<any> {
|
||||
let window = Array.from(await windows.getAll({windowTypes: ["normal"]})).
|
||||
filter((w: any) => w.type === "normal").pop();
|
||||
@ -106,32 +103,10 @@ const ICONS = Object.freeze((() => {
|
||||
return new Map<string, string>(rv);
|
||||
})());
|
||||
|
||||
let iconForPathPlatform: Function;
|
||||
if (IS_CHROME) {
|
||||
const FOUR = 128;
|
||||
const DOUBLE = 64;
|
||||
iconForPathPlatform = function(icon: string, size: number) {
|
||||
let scale = "1x";
|
||||
if (size > FOUR) {
|
||||
// wishful thinking at this point
|
||||
scale = "4x";
|
||||
}
|
||||
else if (size > DOUBLE) {
|
||||
scale = "2x";
|
||||
}
|
||||
return `chrome://fileicon/${icon}?scale=${scale}`;
|
||||
};
|
||||
}
|
||||
else {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
iconForPathPlatform = function(icon: string, size: number) {
|
||||
return ICONS.get(icon) || "icon-file-generic";
|
||||
};
|
||||
}
|
||||
export const DEFAULT_ICON_SIZE = 16;
|
||||
|
||||
|
||||
// eslint-disable-next-line no-magic-numbers
|
||||
export function iconForPath(path: string, size = 16) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
export function iconForPath(path: string, size = DEFAULT_ICON_SIZE) {
|
||||
const web = /^https?:\/\//.test(path);
|
||||
let file = path.split(/[\\/]/).pop();
|
||||
if (file) {
|
||||
@ -152,7 +127,7 @@ export function iconForPath(path: string, size = 16) {
|
||||
file = "file";
|
||||
}
|
||||
}
|
||||
return iconForPathPlatform(file, size);
|
||||
return ICONS.get(file) || "icon-file-generic";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,7 +33,7 @@
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: right;
|
||||
justify-content: flex-end;
|
||||
background: rgba(30, 30, 30, 0.2);
|
||||
margin-top: 2em;
|
||||
border-top: 1px solid rgba(30, 30, 30, 0.5);
|
||||
|
@ -15,16 +15,20 @@ export function addClass(elem: HTMLElement, ...cls: string[]) {
|
||||
|
||||
interface Timer {
|
||||
args: any[];
|
||||
id: number;
|
||||
}
|
||||
|
||||
export function debounce(fn: Function, to: number) {
|
||||
export function debounce(fn: Function, to: number, reset?: boolean) {
|
||||
let timer: Timer | null;
|
||||
return function(...args: any[]) {
|
||||
if (timer) {
|
||||
timer.args = args;
|
||||
return;
|
||||
if (!reset) {
|
||||
timer.args = args;
|
||||
return;
|
||||
}
|
||||
window.clearTimeout(timer.id);
|
||||
}
|
||||
setTimeout(function() {
|
||||
const id = window.setTimeout(function() {
|
||||
if (!timer) {
|
||||
return;
|
||||
}
|
||||
@ -37,7 +41,7 @@ export function debounce(fn: Function, to: number) {
|
||||
console.error(ex.toString(), ex);
|
||||
}
|
||||
}, to);
|
||||
timer = {args};
|
||||
timer = {args, id};
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ LICENSED = set((".css", ".html", ".js", "*.ts"))
|
||||
IGNORED = set((".DS_Store", "Thumbs.db"))
|
||||
|
||||
PERM_IGNORED_FX = set(("downloads.shelf",))
|
||||
PERM_IGNORED_CHROME = set(("menus",))
|
||||
|
||||
SCRIPTS = [
|
||||
"yarn build:regexps",
|
||||
@ -90,8 +91,6 @@ def build_firefox(args):
|
||||
else:
|
||||
infos["browser_specific_settings"]["gecko"]["id"] = RELEASE_ID
|
||||
|
||||
|
||||
|
||||
infos["permissions"] = [p for p in infos.get("permissions") if not p in PERM_IGNORED_FX]
|
||||
out = Path("web-ext-artifacts") / f"dta-{version}-{args.mode}-fx.zip"
|
||||
if not out.parent.exists():
|
||||
@ -101,6 +100,33 @@ def build_firefox(args):
|
||||
print("Output", out)
|
||||
build(out, json.dumps(infos, indent=2).encode("utf-8"))
|
||||
|
||||
|
||||
def build_chrome(args):
|
||||
now = datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
with open("manifest.json") as manip:
|
||||
infos = json.load(manip, object_pairs_hook=OrderedDict)
|
||||
|
||||
version = infos.get("version")
|
||||
if args.mode == "nightly":
|
||||
version = infos["version"] = f"{version}.{now}"
|
||||
|
||||
version = infos.get("version")
|
||||
|
||||
del infos["browser_specific_settings"]
|
||||
if args.mode != "release":
|
||||
infos["version_name"] = f"{version}-{args.mode}"
|
||||
infos["short_name"] = infos.get("name")
|
||||
infos["name"] = f"{infos.get('name')} {args.mode}"
|
||||
|
||||
infos["permissions"] = [p for p in infos.get("permissions") if not p in PERM_IGNORED_CHROME]
|
||||
out = Path("web-ext-artifacts") / f"dta-{version}-{args.mode}-crx.zip"
|
||||
if not out.parent.exists():
|
||||
out.parent.mkdir()
|
||||
if out.exists():
|
||||
out.unlink()
|
||||
print("Output", out)
|
||||
build(out, json.dumps(infos, indent=2).encode("utf-8"))
|
||||
|
||||
def main():
|
||||
from argparse import ArgumentParser
|
||||
args = ArgumentParser()
|
||||
@ -114,6 +140,7 @@ def main():
|
||||
else:
|
||||
run([script], shell=True)
|
||||
build_firefox(args)
|
||||
build_chrome(args)
|
||||
print("DONE.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
25
util/i18ntochrome.py
Executable file
25
util/i18ntochrome.py
Executable file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
from pathlib import Path
|
||||
|
||||
re_valid = re.compile("[^A-Za-z0-9_]")
|
||||
|
||||
for file in Path("_locales/").glob("**/*.json"):
|
||||
with file.open("r") as filep:
|
||||
messages = json.load(filep, object_pairs_hook=OrderedDict)
|
||||
for x in list(messages):
|
||||
prev = x
|
||||
while True:
|
||||
y = re_valid.sub("_", x)
|
||||
if prev == y:
|
||||
break
|
||||
prev = y
|
||||
if x == y:
|
||||
continue
|
||||
messages[y] = messages[x]
|
||||
del messages[x]
|
||||
with file.open("w", encoding="utf-8") as filep:
|
||||
json.dump(messages, filep, ensure_ascii=False, indent=2)
|
@ -93,10 +93,6 @@ addEventListener("DOMContentLoaded", function dom() {
|
||||
Table.setItems(items);
|
||||
});
|
||||
});
|
||||
PORT.on("icon-cached", async () => {
|
||||
await fullyloaded;
|
||||
Table.onIconCached();
|
||||
});
|
||||
|
||||
// Updates
|
||||
const serializer = new PromiseSerializer(1);
|
||||
|
@ -33,7 +33,7 @@ import { DownloadState, StateTexts, StateClasses, StateIcons } from "./state";
|
||||
import { Tooltip } from "./tooltip";
|
||||
import "../../lib/util";
|
||||
import { CellTypes } from "../../uikit/lib/constants";
|
||||
import { downloads } from "../../lib/browser";
|
||||
import { downloads, CHROME } from "../../lib/browser";
|
||||
import { $ } from "../winutil";
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { TableConfig } from "../../uikit/lib/config";
|
||||
@ -57,9 +57,11 @@ const HIDPI = window.matchMedia &&
|
||||
window.matchMedia("(min-resolution: 2dppx)").matches;
|
||||
|
||||
const ICON_BASE_SIZE = 16;
|
||||
const ICON_REAL_SIZE = HIDPI ? ICON_BASE_SIZE * 2 : ICON_BASE_SIZE;
|
||||
const LARGE_ICON_BASE_SIZE = 64;
|
||||
const MAX_ICON_BASE_SIZE = 127;
|
||||
const ICON_REAL_SIZE = !CHROME && HIDPI ? ICON_BASE_SIZE * 2 : ICON_BASE_SIZE;
|
||||
// eslint-disable-next-line no-magic-numbers
|
||||
const LARGE_ICON_BASE_SIZE = CHROME ? 32 : 64;
|
||||
// eslint-disable-next-line no-magic-numbers
|
||||
const MAX_ICON_BASE_SIZE = CHROME ? 32 : 127;
|
||||
const LARGE_ICON_REAL_SIZE = HIDPI ? MAX_ICON_BASE_SIZE : LARGE_ICON_BASE_SIZE;
|
||||
|
||||
let TEXT_SIZE_UNKNOWM = "unknown";
|
||||
@ -475,6 +477,8 @@ export class DownloadTable extends VirtualTable {
|
||||
col.iconElem.classList.remove("icon-filter");
|
||||
});
|
||||
|
||||
IconCache.on("cached", this.onIconCached.bind(this));
|
||||
|
||||
this.sids = new Map<number, DownloadItem>();
|
||||
this.icons = new Icons($("#icons"));
|
||||
|
||||
@ -1061,10 +1065,16 @@ export class DownloadTable extends VirtualTable {
|
||||
this.updateSizes();
|
||||
$("#statusSpeedContainer").classList.remove("hidden");
|
||||
}
|
||||
if (item.manId && item.ext) {
|
||||
IconCache.set(item.ext, item.manId).catch(console.error);
|
||||
}
|
||||
break;
|
||||
|
||||
case DownloadState.DONE:
|
||||
this.finished++;
|
||||
if (item.manId && item.ext) {
|
||||
IconCache.set(item.ext, item.manId).catch(console.error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.selectionChanged();
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
html, body {
|
||||
height: auto !important;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
ul {
|
||||
@ -29,6 +31,7 @@
|
||||
vertical-align: center;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,9 @@ import { localize } from "../lib/i18n";
|
||||
declare let browser: any;
|
||||
declare let chrome: any;
|
||||
|
||||
const runtime = browser !== "undefined" ? browser.runtime : chrome.runtime;
|
||||
const runtime = typeof browser !== "undefined" ?
|
||||
browser.runtime :
|
||||
chrome.runtime;
|
||||
|
||||
function handler(e: Event) {
|
||||
e.preventDefault();
|
||||
|
Loading…
x
Reference in New Issue
Block a user