BTHLABS-51: Chrome Web Extension

Co-authored-by: Tomek Wójcik <labs@tomekwojcik.pl>
Co-committed-by: Tomek Wójcik <labs@tomekwojcik.pl>
This commit is contained in:
Tomek Wójcik 2025-09-14 06:34:43 +00:00 committed by Tomek Wójcik
parent 1a8c4bfebc
commit ab84f685c0
21 changed files with 82 additions and 9 deletions

View File

@ -21,3 +21,4 @@ class StarUnstarAssociationViewMode(enum.Enum):
class UIAccessTokenOriginApp(enum.Enum): class UIAccessTokenOriginApp(enum.Enum):
SAFARI_WEB_EXTENSION = _('Safari Web Extension') SAFARI_WEB_EXTENSION = _('Safari Web Extension')
CHROME_EXTENSION = _('Chrome Extension')

View File

@ -137,6 +137,10 @@ def render_access_token_app(access_token: AccessTokenOut) -> str:
app = UIAccessTokenOriginApp[origin_app.value].value app = UIAccessTokenOriginApp[origin_app.value].value
variant = 'info' variant = 'info'
case AccessTokenOriginApp.CHROME_EXTENSION:
app = UIAccessTokenOriginApp[origin_app.value].value
variant = 'info'
return format_html( return format_html(
'<span class="badge text-bg-{}">{}</span>', '<span class="badge text-bg-{}">{}</span>',
variant, variant,

View File

@ -72,6 +72,7 @@ JSONRPC_METHOD_MODULES = [
CORS_ALLOWED_ORIGIN_REGEXES = [ CORS_ALLOWED_ORIGIN_REGEXES = [
r'safari-web-extension:\/\/.+?', r'safari-web-extension:\/\/.+?',
r'chrome-extension:\/\/.+?',
] ]
CORS_ALLOW_CREDENTIALS = True CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_HEADERS = ( CORS_ALLOW_HEADERS = (

View File

@ -1,2 +1,3 @@
node_modules/ node_modules/
dist/ dist/
secrets/*.pem

View File

@ -3,6 +3,10 @@
"message": "Save to HotPocket", "message": "Save to HotPocket",
"description": "The display name for the extension." "description": "The display name for the extension."
}, },
"extension_name_development": {
"message": "HotPocket Development",
"description": "The display name for the extension."
},
"extension_description": { "extension_description": {
"message": "Save to HotPocket. Straight from the toolbar!", "message": "Save to HotPocket. Straight from the toolbar!",
"description": "Description of what the extension does." "description": "Description of what the extension does."

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -5,9 +5,9 @@ import globals from 'globals';
export default defineConfig([ export default defineConfig([
{ {
files: [ ignores: [
'eslint.config.js', 'dist/**',
'src/**/*.js', 'rollup.config.js',
], ],
plugins: { plugins: {
js, js,

View File

@ -12,7 +12,10 @@
"eslint": "npx eslint .", "eslint": "npx eslint .",
"build:safari": "NODE_ENV=production HOTPOCKET_EXTENSION_TARGET=safari npx rollup -c rollup.config.js", "build:safari": "NODE_ENV=production HOTPOCKET_EXTENSION_TARGET=safari npx rollup -c rollup.config.js",
"dev:safari": "HOTPOCKET_EXTENSION_TARGET=safari npx rollup -c rollup.config.js", "dev:safari": "HOTPOCKET_EXTENSION_TARGET=safari npx rollup -c rollup.config.js",
"watch:safari": "HOTPOCKET_EXTENSION_TARGET=safari npx rollup -c rollup.config.js -w" "watch:safari": "HOTPOCKET_EXTENSION_TARGET=safari npx rollup -c rollup.config.js -w",
"build:chrome": "NODE_ENV=production HOTPOCKET_EXTENSION_TARGET=chrome npx rollup -c rollup.config.js",
"dev:chrome": "HOTPOCKET_EXTENSION_TARGET=chrome npx rollup -c rollup.config.js",
"watch:chrome": "HOTPOCKET_EXTENSION_TARGET=chrome npx rollup -c rollup.config.js -w"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "9.33.0", "@eslint/js": "9.33.0",

View File

@ -3,6 +3,7 @@ import copy from 'rollup-plugin-copy';
import {string} from 'rollup-plugin-string'; import {string} from 'rollup-plugin-string';
import packageJSON from './package.json' with {type: 'json'}; import packageJSON from './package.json' with {type: 'json'};
import manifestChrome from './src/manifest/chrome.json' with {type: 'json'};
import manifestCommon from './src/manifest/common.json' with {type: 'json'}; import manifestCommon from './src/manifest/common.json' with {type: 'json'};
import manifestSafari from './src/manifest/safari.json' with {type: 'json'}; import manifestSafari from './src/manifest/safari.json' with {type: 'json'};
@ -62,12 +63,17 @@ const manifestJsonOutputPlugin = () => {
...result, ...result,
...manifestSafari, ...manifestSafari,
}; };
} else if (TARGET == 'chrome') {
result = {
...result,
...manifestChrome,
};
} }
result.version = packageJSON.version; result.version = packageJSON.version;
if (IS_PRODUCTION === false) { if (IS_PRODUCTION === false) {
result.name = 'HotPocket Development'; result.name = '__MSG_extension_name_development__';
} }
return JSON.stringify(result, null, 2); return JSON.stringify(result, null, 2);
@ -78,6 +84,8 @@ const manifestJsonOutputPlugin = () => {
let OUTPUT_PATH = `dist/${TARGET}`; let OUTPUT_PATH = `dist/${TARGET}`;
if (TARGET === 'safari') { if (TARGET === 'safari') {
OUTPUT_PATH = '../apple/Shared (Extension)/Resources'; OUTPUT_PATH = '../apple/Shared (Extension)/Resources';
} else if (IS_PRODUCTION === true) {
OUTPUT_PATH = `dist/${TARGET}-production`;
} }
export default [ export default [

View File

View File

@ -0,0 +1,6 @@
import main from './main';
main({
platform: 'Chrome',
api: chrome,
});

View File

@ -0,0 +1,6 @@
import main from './main';
main({
platform: 'Chrome',
api: window.chrome,
});

View File

@ -0,0 +1,13 @@
{
"action": {
"default_title": "__MSG_extension_name__",
"default_icon": {
"16": "images/toolbar-icon-16.png",
"32": "images/toolbar-icon-32.png"
}
},
"background": {
"service_worker": "background-bundle.js",
"type": "module"
}
}

View File

@ -5,6 +5,8 @@
"description": "__MSG_extension_description__", "description": "__MSG_extension_description__",
"version": "25.9.12", "version": "25.9.12",
"icons": { "icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png", "48": "images/icon-48.png",
"64": "images/icon-64.png", "64": "images/icon-64.png",
"96": "images/icon-96.png", "96": "images/icon-96.png",
@ -22,10 +24,6 @@
] ]
} }
], ],
"action": {
"default_title": "__MSG_extension_name__",
"default_icon": "images/toolbar-icon.svg"
},
"permissions": [ "permissions": [
"storage", "storage",
"activeTab", "activeTab",

View File

@ -1,5 +1,9 @@
{ {
"description": "__MSG_extension_description_Safari__", "description": "__MSG_extension_description_Safari__",
"action": {
"default_title": "__MSG_extension_name__",
"default_icon": "images/toolbar-icon.svg"
},
"background": { "background": {
"scripts": [ "scripts": [
"background-bundle.js" "background-bundle.js"

View File

@ -110,3 +110,23 @@ def start_web(ctx):
@task @task
def start_safari(ctx): def start_safari(ctx):
ctx.run('yarn watch:safari') ctx.run('yarn watch:safari')
@task(pre=[clean])
def start_chrome(ctx):
ctx.run('yarn watch:chrome')
@task
def build_safari(ctx):
ctx.run('yarn build:safari')
@task(pre=[clean])
def build_chrome(ctx):
ctx.run('yarn build:chrome')
ctx.run(' '.join([
r'/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome',
'--pack-extension=dist/chrome-production/',
'--pack-extension-key=secrets/chrome.pem',
]))

View File

@ -7,3 +7,4 @@ import enum
class AccessTokenOriginApp(enum.Enum): class AccessTokenOriginApp(enum.Enum):
UNKNOWN = 'UNKNOWN' UNKNOWN = 'UNKNOWN'
SAFARI_WEB_EXTENSION = 'SAFARI_WEB_EXTENSION' SAFARI_WEB_EXTENSION = 'SAFARI_WEB_EXTENSION'
CHROME_EXTENSION = 'CHROME_EXTENSION'

View File

@ -26,6 +26,9 @@ class AccessTokenOut(ModelOut):
case 'safari-web-extension': case 'safari-web-extension':
return AccessTokenOriginApp.SAFARI_WEB_EXTENSION return AccessTokenOriginApp.SAFARI_WEB_EXTENSION
case 'chrome-extension':
return AccessTokenOriginApp.CHROME_EXTENSION
case _: case _:
return None return None