You've already forked hotpocket
BTHLABS-82: Spring 2026 Refresh
Co-authored-by: Tomek Wójcik <labs@tomekwojcik.pl> Co-committed-by: Tomek Wójcik <labs@tomekwojcik.pl>
This commit is contained in:
@@ -2,6 +2,7 @@ run:
|
||||
echo: true
|
||||
pty: true
|
||||
files_to_version:
|
||||
- "src/content/options.html"
|
||||
- "src/content/preauth.html"
|
||||
- "src/manifest/common.json"
|
||||
- "package.json"
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
"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"
|
||||
"watch:firefox": "HOTPOCKET_EXTENSION_TARGET=firefox npx rollup -c rollup.config.js -w",
|
||||
"build:opera": "NODE_ENV=production HOTPOCKET_EXTENSION_TARGET=opera npx rollup -c rollup.config.js",
|
||||
"dev:opera": "HOTPOCKET_EXTENSION_TARGET=opera npx rollup -c rollup.config.js",
|
||||
"watch:opera": "HOTPOCKET_EXTENSION_TARGET=opera npx rollup -c rollup.config.js -w"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "9.33.0",
|
||||
|
||||
@@ -6,6 +6,7 @@ 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 manifestFirefox from './src/manifest/firefox.json' with {type: 'json'};
|
||||
import manifestOpera from './src/manifest/opera.json' with {type: 'json'};
|
||||
import manifestSafari from './src/manifest/safari.json' with {type: 'json'};
|
||||
|
||||
const BANNER = `/*!
|
||||
@@ -66,6 +67,11 @@ const manifestJsonOutputPlugin = () => {
|
||||
...result,
|
||||
...manifestFirefox,
|
||||
};
|
||||
} else if (TARGET == 'opera') {
|
||||
result = {
|
||||
...result,
|
||||
...manifestOpera,
|
||||
};
|
||||
}
|
||||
|
||||
result.version = packageJSON.version;
|
||||
@@ -110,6 +116,8 @@ export default [
|
||||
},
|
||||
{
|
||||
src: [
|
||||
'src/content/options.html',
|
||||
'src/content/options.js',
|
||||
'src/content/preauth.html',
|
||||
'src/content/preauth.js',
|
||||
],
|
||||
|
||||
@@ -8,13 +8,21 @@ let authSessionToken = null;
|
||||
let accountsRPCURL = null;
|
||||
let rpcURL = null;
|
||||
|
||||
const updateRpcURLs = () => {
|
||||
const updateRpcURLs = (options) => {
|
||||
options = {
|
||||
clear: false,
|
||||
...(options || {}),
|
||||
};
|
||||
|
||||
accountsRPCURL = null;
|
||||
rpcURL = null;
|
||||
|
||||
if (HotPocketExtension.base_url !== null) {
|
||||
rpcURL = (new URL(RPC_PATH, HotPocketExtension.base_url)).toString();
|
||||
accountsRPCURL = (new URL(ACCOUNTS_RPC_PATH, HotPocketExtension.base_url)).toString();
|
||||
} else if (options.clear === true) {
|
||||
rpcURL = null;
|
||||
accountsRPCURL = null;
|
||||
}
|
||||
|
||||
HotPocketExtension.LOGGER.debug(
|
||||
@@ -355,6 +363,12 @@ const onBrowserActionClicked = async (tab) => {
|
||||
return await doSendTabMessage(tab, message);
|
||||
};
|
||||
|
||||
const doLogOut = async () => {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let storageResult = await HotPocketExtension.api.storage.local.clear();
|
||||
updateRpcURLs({clear: true});
|
||||
};
|
||||
|
||||
const onMessage = (message, sender, sendResponse) => {
|
||||
HotPocketExtension.LOGGER.debug(
|
||||
'HotPocketExtension.background.onMessage()', message, sender, sendResponse,
|
||||
@@ -368,6 +382,10 @@ const onMessage = (message, sender, sendResponse) => {
|
||||
});
|
||||
} else if (message.type === 'HotPocket:Extension:setBaseURL') {
|
||||
doUpdateBaseURL(message.result);
|
||||
} else if (message.type === 'HotPocket:ExtensionOptions:logOut') {
|
||||
doLogOut();
|
||||
} else if (message.type === 'HotPocket:ExtensionOptions:logIn') {
|
||||
doSetupRPC();
|
||||
}
|
||||
} catch (exception) {
|
||||
HotPocketExtension.LOGGER.error(
|
||||
|
||||
6
services/extension/src/background/opera.js
Normal file
6
services/extension/src/background/opera.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import main from './main';
|
||||
|
||||
main({
|
||||
platform: 'Opera',
|
||||
api: chrome,
|
||||
});
|
||||
6
services/extension/src/content/opera.js
Normal file
6
services/extension/src/content/opera.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import main from './main';
|
||||
|
||||
main({
|
||||
platform: 'Opera',
|
||||
api: window.chrome,
|
||||
});
|
||||
112
services/extension/src/content/options.html
Normal file
112
services/extension/src/content/options.html
Normal file
File diff suppressed because one or more lines are too long
118
services/extension/src/content/options.js
Normal file
118
services/extension/src/content/options.js
Normal file
@@ -0,0 +1,118 @@
|
||||
/*!
|
||||
* HotPocket by BTHLabs (https://hotpocket.app/)
|
||||
* Copyright 2025-present BTHLabs <contact@bthlabs.pl> (https://bthlabs.pl/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
(() => {
|
||||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', (event) => {
|
||||
const form = document.getElementById('OptionsForm');
|
||||
const fieldBaseURL = document.getElementById('div_id_base_url');
|
||||
const fieldNeedsSetup = document.getElementById('div_id_needs_setup');
|
||||
const inputBaseURL = document.getElementById('id_base_url');
|
||||
const inputSubmit = document.getElementById('id_submit');
|
||||
let formLoader = form.querySelector('.loader');
|
||||
|
||||
let api = window.browser || null;
|
||||
if (api === null && window.chrome) {
|
||||
api = window.chrome;
|
||||
}
|
||||
|
||||
const updateForm = () => {
|
||||
if (inputBaseURL.value) {
|
||||
fieldBaseURL.classList.remove('d-none');
|
||||
fieldNeedsSetup.classList.add('d-none');
|
||||
|
||||
inputSubmit.classList.remove('btn-primary');
|
||||
inputSubmit.classList.add('btn-secondary');
|
||||
inputSubmit.value = 'Log out';
|
||||
} else {
|
||||
fieldBaseURL.classList.add('d-none');
|
||||
fieldNeedsSetup.classList.remove('d-none');
|
||||
|
||||
inputSubmit.classList.remove('btn-secondary');
|
||||
inputSubmit.classList.add('btn-primary');
|
||||
inputSubmit.value = 'Log in';
|
||||
}
|
||||
};
|
||||
|
||||
const loadBaseURL = async (options) => {
|
||||
options = {
|
||||
initial: false,
|
||||
...(options || {}),
|
||||
};
|
||||
|
||||
formLoader.classList.remove('d-none');
|
||||
|
||||
const storageResult = await api.storage.local.get(['baseURL']);
|
||||
|
||||
if (storageResult.baseURL) {
|
||||
inputBaseURL.value = storageResult.baseURL;
|
||||
}
|
||||
|
||||
if (options.initial === true) {
|
||||
formLoader.classList.add('d-none');
|
||||
}
|
||||
|
||||
updateForm();
|
||||
|
||||
return storageResult.baseURL || null;
|
||||
};
|
||||
|
||||
const startPollingBaseURL = async () => {
|
||||
let timeout = null;
|
||||
|
||||
formLoader.classList.remove('d-none');
|
||||
|
||||
window.setTimeout(
|
||||
async () => {
|
||||
window.clearTimeout(timeout);
|
||||
|
||||
const result = await loadBaseURL();
|
||||
|
||||
if (result === null) {
|
||||
startPollingBaseURL();
|
||||
} else {
|
||||
formLoader.classList.add('d-none');
|
||||
}
|
||||
},
|
||||
5000,
|
||||
);
|
||||
};
|
||||
|
||||
form.addEventListener('submit', (event) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
if (inputBaseURL.value) {
|
||||
api.runtime.sendMessage({
|
||||
type: 'HotPocket:ExtensionOptions:logOut',
|
||||
});
|
||||
inputBaseURL.value = '';
|
||||
} else {
|
||||
api.runtime.sendMessage({
|
||||
type: 'HotPocket:ExtensionOptions:logIn',
|
||||
});
|
||||
startPollingBaseURL();
|
||||
}
|
||||
|
||||
updateForm();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
loadBaseURL({initial: true});
|
||||
});
|
||||
})();
|
||||
@@ -86,6 +86,6 @@ body, html {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="/preauth.js"></script>
|
||||
<script type="text/javascript" src="/preauth.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -28,5 +28,9 @@
|
||||
"storage",
|
||||
"activeTab",
|
||||
"tabs"
|
||||
]
|
||||
],
|
||||
"options_ui": {
|
||||
"open_in_tab": true,
|
||||
"page": "options.html"
|
||||
}
|
||||
}
|
||||
|
||||
13
services/extension/src/manifest/opera.json
Normal file
13
services/extension/src/manifest/opera.json
Normal 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"
|
||||
}
|
||||
}
|
||||
@@ -255,7 +255,7 @@ def build_firefox_source(ctx: Context):
|
||||
|
||||
@task
|
||||
def build_opera_source(ctx: Context):
|
||||
# AMO requires source bundle to be uploaded alongside the built version.
|
||||
# Opera requires source bundle to be uploaded alongside the built version.
|
||||
ctx.run('rm -rf dist/opera-source')
|
||||
ctx.run('mkdir -p dist/opera-source dist/opera-source/assets dist/opera-source/src')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user