BTHLABS-52: Firefox Desktop Extension

This commit is contained in:
Tomek Wójcik 2025-09-15 16:28:17 +00:00
parent d1e60babf4
commit 46254730bd
11 changed files with 103 additions and 23 deletions

View File

@ -22,3 +22,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') CHROME_EXTENSION = _('Chrome Extension')
FIREFOX_EXTENSION = _('Firefox Extension')

View File

@ -132,14 +132,15 @@ def render_access_token_app(access_token: AccessTokenOut) -> str:
variant = 'secondary' variant = 'secondary'
origin_app = access_token.get_origin_app() origin_app = access_token.get_origin_app()
match origin_app:
case AccessTokenOriginApp.SAFARI_WEB_EXTENSION:
app = UIAccessTokenOriginApp[origin_app.value].value
variant = 'info'
case AccessTokenOriginApp.CHROME_EXTENSION: extension_origin_apps = (
app = UIAccessTokenOriginApp[origin_app.value].value AccessTokenOriginApp.SAFARI_WEB_EXTENSION,
variant = 'info' AccessTokenOriginApp.CHROME_EXTENSION,
AccessTokenOriginApp.FIREFOX_EXTENSION,
)
if origin_app in extension_origin_apps:
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>',

View File

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

View File

@ -15,7 +15,10 @@
"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", "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", "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" "watch:chrome": "HOTPOCKET_EXTENSION_TARGET=chrome npx rollup -c rollup.config.js -w",
"build:firefox": "NODE_ENV=production HOTPOCKET_EXTENSION_TARGET=firefox npx rollup -c rollup.config.js",
"dev:firefox": "HOTPOCKET_EXTENSION_TARGET=firefox npx rollup -c rollup.config.js",
"watch:firefox": "HOTPOCKET_EXTENSION_TARGET=firefox npx rollup -c rollup.config.js -w"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "9.33.0", "@eslint/js": "9.33.0",

View File

@ -5,6 +5,7 @@ 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 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 manifestFirefox from './src/manifest/firefox.json' with {type: 'json'};
import manifestSafari from './src/manifest/safari.json' with {type: 'json'}; import manifestSafari from './src/manifest/safari.json' with {type: 'json'};
const BANNER = `/*! const BANNER = `/*!
@ -68,6 +69,11 @@ const manifestJsonOutputPlugin = () => {
...result, ...result,
...manifestChrome, ...manifestChrome,
}; };
} else if (TARGET == 'firefox') {
result = {
...result,
...manifestFirefox,
};
} }
result.version = packageJSON.version; result.version = packageJSON.version;

View File

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

View File

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

View File

@ -0,0 +1,27 @@
{
"action": {
"default_title": "__MSG_extension_name__",
"default_icon": {
"16": "images/toolbar-icon-16.png",
"32": "images/toolbar-icon-32.png"
}
},
"background": {
"scripts": [
"background-bundle.js"
],
"type": "module"
},
"browser_specific_settings": {
"gecko": {
"id": "@Extension.HotPocket.BTHLabs",
"strict_min_version": "142.0",
"data_collection_permissions": {
"required": [
"websiteActivity",
"technicalAndInteraction"
]
}
}
}
}

View File

@ -3,7 +3,9 @@
from __future__ import annotations from __future__ import annotations
from invoke import task import json
from invoke import Context, task
from invoke.exceptions import UnexpectedExit from invoke.exceptions import UnexpectedExit
from hotpocket_workspace_tools import get_workspace_mode from hotpocket_workspace_tools import get_workspace_mode
@ -12,18 +14,18 @@ WORKSPACE_MODE = get_workspace_mode()
@task @task
def clean(ctx): def clean(ctx: Context):
ctx.run('rm -rf dist/') ctx.run('rm -rf dist/')
@task @task
def test(ctx): def test(ctx: Context):
# ctx.run('pytest -v --disable-warnings') # ctx.run('pytest -v --disable-warnings')
print('NOOP') print('NOOP')
@task @task
def flake8(ctx): def flake8(ctx: Context):
ctx.run('flake8') ctx.run('flake8')
@ -45,12 +47,12 @@ def isort(ctx, check=False, diff=False):
@task @task
def eslint(ctx): def eslint(ctx: Context):
ctx.run('yarn run eslint') ctx.run('yarn run eslint')
@task @task
def lint(ctx): def lint(ctx: Context):
ihazsuccess = True ihazsuccess = True
try: try:
@ -73,17 +75,17 @@ def lint(ctx):
@task @task
def typecheck(ctx): def typecheck(ctx: Context):
ctx.run('mypy .') ctx.run('mypy .')
@task @task
def django_shell(ctx): def django_shell(ctx: Context):
raise NotImplementedError() raise NotImplementedError()
@task @task
def ci(ctx): def ci(ctx: Context):
ihazsuccess = True ihazsuccess = True
ci_tasks = [test, lint, typecheck] ci_tasks = [test, lint, typecheck]
@ -98,35 +100,58 @@ def ci(ctx):
@task @task
def setup(ctx): def setup(ctx: Context):
print('NOOP') print('NOOP')
@task @task
def start_web(ctx): def start_web(ctx: Context):
raise NotImplementedError() raise NotImplementedError()
@task @task
def start_safari(ctx): def start_safari(ctx: Context):
ctx.run('yarn watch:safari') ctx.run('yarn watch:safari')
@task(pre=[clean]) @task(pre=[clean])
def start_chrome(ctx): def start_chrome(ctx: Context):
ctx.run('yarn watch:chrome') ctx.run('yarn watch:chrome')
@task(pre=[clean])
def start_firefox(ctx: Context):
ctx.run('yarn watch:firefox')
@task @task
def build_safari(ctx): def build_safari(ctx: Context):
ctx.run('yarn build:safari') ctx.run('yarn build:safari')
@task(pre=[clean]) @task(pre=[clean])
def build_chrome(ctx): def build_chrome(ctx: Context):
ctx.run('yarn build:chrome') ctx.run('yarn build:chrome')
ctx.run(' '.join([ ctx.run(' '.join([
r'/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome', r'/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome',
'--pack-extension=dist/chrome-production/', '--pack-extension=dist/chrome-production/',
'--pack-extension-key=secrets/chrome.pem', '--pack-extension-key=secrets/chrome.pem',
])) ]))
@task(pre=[clean])
def build_firefox(ctx: Context):
ctx.run('yarn build:firefox')
firefox_secrets = None
with open('secrets/firefox.json', 'r', encoding='utf-8') as firefox_secrets_f:
firefox_secrets = json.load(firefox_secrets_f)
with ctx.cd('dist/firefox-production'):
ctx.run(' '.join([
'web-ext',
'sign',
'--channel=unlisted',
f'--api-key={firefox_secrets["api_key"]}',
f'--api-secret={firefox_secrets["api_secret"]}',
]))

View File

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

View File

@ -29,6 +29,9 @@ class AccessTokenOut(ModelOut):
case 'chrome-extension': case 'chrome-extension':
return AccessTokenOriginApp.CHROME_EXTENSION return AccessTokenOriginApp.CHROME_EXTENSION
case 'moz-extension':
return AccessTokenOriginApp.FIREFOX_EXTENSION
case _: case _:
return None return None