feat: add About well to settings with build info and debug easter egg
All checks were successful
check / check (push) Successful in 26s
All checks were successful
check / check (push) Successful in 26s
Add a new well at the bottom of the settings view that displays: - License (GPL-3.0) - Author (sneak) - Version (from package.json) - Build date (injected at build time) - Git commit short hash (linked to Gitea commit URL) Build-time injection: build.js now reads the git commit hash and version from package.json, injecting them via esbuild define constants. The Dockerfile and Makefile pass commit hashes as build args so the info is available even when .git is excluded from the Docker context. Easter egg: clicking the version number 10 times reveals a hidden debug well below the About well, containing a toggle for debug mode. The debug mode flag is persisted in state and enables verbose console logging via the runtime debug flag in the logger. closes #144
This commit is contained in:
parent
6b40fa8836
commit
cc69c1b2a0
@ -11,5 +11,10 @@ RUN yarn install --frozen-lockfile
|
||||
|
||||
COPY . .
|
||||
|
||||
ARG GIT_COMMIT_SHORT=unknown
|
||||
ARG GIT_COMMIT_FULL=unknown
|
||||
ENV GIT_COMMIT_SHORT=${GIT_COMMIT_SHORT}
|
||||
ENV GIT_COMMIT_FULL=${GIT_COMMIT_FULL}
|
||||
|
||||
RUN make check
|
||||
RUN make build
|
||||
|
||||
5
Makefile
5
Makefile
@ -33,7 +33,10 @@ dev:
|
||||
@yarn run build --watch 2>&1
|
||||
|
||||
docker:
|
||||
@docker build -t autistmask .
|
||||
@docker build \
|
||||
--build-arg GIT_COMMIT_SHORT=$$(git rev-parse --short HEAD 2>/dev/null || echo unknown) \
|
||||
--build-arg GIT_COMMIT_FULL=$$(git rev-parse HEAD 2>/dev/null || echo unknown) \
|
||||
-t autistmask .
|
||||
|
||||
hooks:
|
||||
@echo "Installing pre-commit hook..."
|
||||
|
||||
50
build.js
50
build.js
@ -11,9 +11,55 @@ function ensureDir(dir) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
function getBuildInfo() {
|
||||
const pkg = JSON.parse(
|
||||
fs.readFileSync(path.join(__dirname, "package.json"), "utf8"),
|
||||
);
|
||||
let commitHash = process.env.GIT_COMMIT_SHORT || "unknown";
|
||||
if (commitHash === "unknown") {
|
||||
try {
|
||||
commitHash = execSync("git rev-parse --short HEAD", {
|
||||
encoding: "utf8",
|
||||
}).trim();
|
||||
} catch (_) {
|
||||
// not a git repo or git not available
|
||||
}
|
||||
}
|
||||
let commitHashFull = process.env.GIT_COMMIT_FULL || "unknown";
|
||||
if (commitHashFull === "unknown") {
|
||||
try {
|
||||
commitHashFull = execSync("git rev-parse HEAD", {
|
||||
encoding: "utf8",
|
||||
}).trim();
|
||||
} catch (_) {
|
||||
// not a git repo or git not available
|
||||
}
|
||||
}
|
||||
return {
|
||||
version: pkg.version,
|
||||
license: pkg.license,
|
||||
author: pkg.author,
|
||||
commitHash,
|
||||
commitHashFull,
|
||||
buildDate: new Date().toISOString().slice(0, 10),
|
||||
};
|
||||
}
|
||||
|
||||
async function build() {
|
||||
console.log("Building AutistMask extension...");
|
||||
|
||||
const buildInfo = getBuildInfo();
|
||||
console.log("Build info:", buildInfo);
|
||||
|
||||
const define = {
|
||||
__BUILD_VERSION__: JSON.stringify(buildInfo.version),
|
||||
__BUILD_LICENSE__: JSON.stringify(buildInfo.license),
|
||||
__BUILD_AUTHOR__: JSON.stringify(buildInfo.author),
|
||||
__BUILD_COMMIT__: JSON.stringify(buildInfo.commitHash),
|
||||
__BUILD_COMMIT_FULL__: JSON.stringify(buildInfo.commitHashFull),
|
||||
__BUILD_DATE__: JSON.stringify(buildInfo.buildDate),
|
||||
};
|
||||
|
||||
// compile tailwind CSS
|
||||
console.log("Compiling Tailwind CSS...");
|
||||
const tailwindInput = path.join(SRC, "popup", "styles", "main.css");
|
||||
@ -38,6 +84,7 @@ async function build() {
|
||||
platform: "browser",
|
||||
target: ["chrome110", "firefox110"],
|
||||
minify: true,
|
||||
define,
|
||||
});
|
||||
|
||||
// bundle background script
|
||||
@ -49,6 +96,7 @@ async function build() {
|
||||
platform: "browser",
|
||||
target: ["chrome110", "firefox110"],
|
||||
minify: true,
|
||||
define,
|
||||
});
|
||||
|
||||
// bundle content script
|
||||
@ -60,6 +108,7 @@ async function build() {
|
||||
platform: "browser",
|
||||
target: ["chrome110", "firefox110"],
|
||||
minify: true,
|
||||
define,
|
||||
});
|
||||
|
||||
// bundle inpage script (injected into page context, separate file)
|
||||
@ -71,6 +120,7 @@ async function build() {
|
||||
platform: "browser",
|
||||
target: ["chrome110", "firefox110"],
|
||||
minify: true,
|
||||
define,
|
||||
});
|
||||
|
||||
// copy popup HTML
|
||||
|
||||
@ -1002,6 +1002,54 @@
|
||||
</p>
|
||||
<div id="settings-denied-sites"></div>
|
||||
</div>
|
||||
|
||||
<div class="bg-well p-3 mx-1 mb-3">
|
||||
<h3 class="font-bold mb-1">About</h3>
|
||||
<div class="text-xs">
|
||||
<div class="mb-1">
|
||||
<span class="text-muted">License:</span>
|
||||
<span id="about-license"></span>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<span class="text-muted">Author:</span>
|
||||
<span id="about-author"></span>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<span class="text-muted">Version:</span>
|
||||
<span
|
||||
id="about-version"
|
||||
class="cursor-pointer select-none"
|
||||
></span>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<span class="text-muted">Build date:</span>
|
||||
<span id="about-build-date"></span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-muted">Commit:</span>
|
||||
<a
|
||||
id="about-commit-link"
|
||||
class="underline decoration-dashed"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="settings-debug-well"
|
||||
class="bg-well p-3 mx-1 mb-3"
|
||||
style="display: none"
|
||||
>
|
||||
<h3 class="font-bold mb-1">Debug</h3>
|
||||
<label
|
||||
class="text-xs flex items-center gap-1 cursor-pointer"
|
||||
>
|
||||
<input type="checkbox" id="settings-debug-mode" />
|
||||
Enable debug mode
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ============ DELETE WALLET CONFIRM ============ -->
|
||||
|
||||
@ -2,12 +2,23 @@ const { $, showView, showFlash, escapeHtml } = require("./helpers");
|
||||
const { applyTheme } = require("../theme");
|
||||
const { state, saveState, currentNetwork } = require("../../shared/state");
|
||||
const { NETWORKS, SUPPORTED_CHAIN_IDS } = require("../../shared/networks");
|
||||
const { log, debugFetch } = require("../../shared/log");
|
||||
const { log, debugFetch, setRuntimeDebug } = require("../../shared/log");
|
||||
const deleteWallet = require("./deleteWallet");
|
||||
const {
|
||||
BUILD_VERSION,
|
||||
BUILD_LICENSE,
|
||||
BUILD_AUTHOR,
|
||||
BUILD_COMMIT,
|
||||
BUILD_DATE,
|
||||
GITEA_COMMIT_URL,
|
||||
} = require("../../shared/buildInfo");
|
||||
|
||||
const runtime =
|
||||
typeof browser !== "undefined" ? browser.runtime : chrome.runtime;
|
||||
|
||||
let versionClickCount = 0;
|
||||
let versionClickTimer = null;
|
||||
|
||||
function renderSiteList(containerId, siteMap, stateKey) {
|
||||
const container = $(containerId);
|
||||
const hostnames = [...new Set(Object.values(siteMap).flat())];
|
||||
@ -133,6 +144,28 @@ function show() {
|
||||
renderSiteLists();
|
||||
renderWalletListSettings();
|
||||
|
||||
// Populate About well
|
||||
$("about-license").textContent = BUILD_LICENSE;
|
||||
// Show only the name part of the author field (strip email)
|
||||
const authorName = BUILD_AUTHOR.replace(/\s*<[^>]+>/, "");
|
||||
$("about-author").textContent = authorName;
|
||||
$("about-version").textContent = BUILD_VERSION;
|
||||
$("about-build-date").textContent = BUILD_DATE;
|
||||
$("about-commit-link").textContent = BUILD_COMMIT;
|
||||
$("about-commit-link").href = GITEA_COMMIT_URL;
|
||||
|
||||
// Reset version click counter each time settings opens
|
||||
versionClickCount = 0;
|
||||
|
||||
// Show debug well if debug mode is already enabled
|
||||
const debugWell = $("settings-debug-well");
|
||||
if (state.debugMode) {
|
||||
debugWell.style.display = "";
|
||||
} else {
|
||||
debugWell.style.display = "none";
|
||||
}
|
||||
$("settings-debug-mode").checked = state.debugMode;
|
||||
|
||||
showView("settings");
|
||||
}
|
||||
|
||||
@ -285,6 +318,31 @@ function init(ctx) {
|
||||
ctx.showSettingsAddTokenView,
|
||||
);
|
||||
|
||||
// Easter egg: click version 10 times to reveal the debug well
|
||||
$("about-version").addEventListener("click", () => {
|
||||
versionClickCount++;
|
||||
clearTimeout(versionClickTimer);
|
||||
// Reset counter if user stops clicking for 3 seconds
|
||||
versionClickTimer = setTimeout(() => {
|
||||
versionClickCount = 0;
|
||||
}, 3000);
|
||||
if (versionClickCount >= 10) {
|
||||
versionClickCount = 0;
|
||||
clearTimeout(versionClickTimer);
|
||||
$("settings-debug-well").style.display = "";
|
||||
}
|
||||
});
|
||||
|
||||
// Debug mode toggle
|
||||
$("settings-debug-mode").addEventListener("change", async () => {
|
||||
state.debugMode = $("settings-debug-mode").checked;
|
||||
setRuntimeDebug(state.debugMode);
|
||||
await saveState();
|
||||
});
|
||||
|
||||
// Sync runtime debug flag on init
|
||||
setRuntimeDebug(state.debugMode);
|
||||
|
||||
$("btn-settings-back").addEventListener("click", () => {
|
||||
ctx.renderWalletList();
|
||||
showView("main");
|
||||
|
||||
35
src/shared/buildInfo.js
Normal file
35
src/shared/buildInfo.js
Normal file
@ -0,0 +1,35 @@
|
||||
// Build-time constants injected by esbuild define in build.js.
|
||||
// These globals are replaced at bundle time with string literals.
|
||||
|
||||
/* global __BUILD_VERSION__, __BUILD_LICENSE__, __BUILD_AUTHOR__,
|
||||
__BUILD_COMMIT__, __BUILD_COMMIT_FULL__, __BUILD_DATE__ */
|
||||
|
||||
const BUILD_VERSION =
|
||||
typeof __BUILD_VERSION__ !== "undefined" ? __BUILD_VERSION__ : "dev";
|
||||
const BUILD_LICENSE =
|
||||
typeof __BUILD_LICENSE__ !== "undefined" ? __BUILD_LICENSE__ : "GPL-3.0";
|
||||
const BUILD_AUTHOR =
|
||||
typeof __BUILD_AUTHOR__ !== "undefined"
|
||||
? __BUILD_AUTHOR__
|
||||
: "sneak <sneak@sneak.berlin>";
|
||||
const BUILD_COMMIT =
|
||||
typeof __BUILD_COMMIT__ !== "undefined" ? __BUILD_COMMIT__ : "unknown";
|
||||
const BUILD_COMMIT_FULL =
|
||||
typeof __BUILD_COMMIT_FULL__ !== "undefined"
|
||||
? __BUILD_COMMIT_FULL__
|
||||
: "unknown";
|
||||
const BUILD_DATE =
|
||||
typeof __BUILD_DATE__ !== "undefined" ? __BUILD_DATE__ : "unknown";
|
||||
|
||||
const GITEA_COMMIT_URL =
|
||||
"https://git.eeqj.de/sneak/AutistMask/commit/" + BUILD_COMMIT_FULL;
|
||||
|
||||
module.exports = {
|
||||
BUILD_VERSION,
|
||||
BUILD_LICENSE,
|
||||
BUILD_AUTHOR,
|
||||
BUILD_COMMIT,
|
||||
BUILD_COMMIT_FULL,
|
||||
BUILD_DATE,
|
||||
GITEA_COMMIT_URL,
|
||||
};
|
||||
@ -1,12 +1,27 @@
|
||||
// Leveled logger. Outputs to console with [AutistMask] prefix.
|
||||
// Level is DEBUG when the DEBUG constant is true, INFO otherwise.
|
||||
// Level is DEBUG when the compile-time DEBUG constant is true or the runtime
|
||||
// debugMode state flag is enabled. The runtime flag is checked lazily so it
|
||||
// responds immediately when toggled in settings.
|
||||
|
||||
const { DEBUG } = require("./constants");
|
||||
|
||||
const LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
|
||||
const threshold = DEBUG ? LEVELS.debug : LEVELS.info;
|
||||
|
||||
// Runtime debug mode flag — set by settings.js when the user toggles debug
|
||||
// mode via the easter egg. Kept here as a simple mutable reference so it can
|
||||
// be updated without circular dependency issues with state.js.
|
||||
let _runtimeDebug = false;
|
||||
|
||||
function setRuntimeDebug(enabled) {
|
||||
_runtimeDebug = enabled;
|
||||
}
|
||||
|
||||
function isDebug() {
|
||||
return DEBUG || _runtimeDebug;
|
||||
}
|
||||
|
||||
function emit(level, method, args) {
|
||||
const threshold = isDebug() ? LEVELS.debug : LEVELS.info;
|
||||
if (LEVELS[level] >= threshold) {
|
||||
console[method]("[AutistMask]", ...args);
|
||||
}
|
||||
@ -37,4 +52,4 @@ async function debugFetch(url, opts) {
|
||||
return resp;
|
||||
}
|
||||
|
||||
module.exports = { log, debugFetch };
|
||||
module.exports = { log, debugFetch, setRuntimeDebug, isDebug };
|
||||
|
||||
@ -29,6 +29,7 @@ const DEFAULT_STATE = {
|
||||
fraudContracts: [],
|
||||
tokenHolderCache: {},
|
||||
theme: "system",
|
||||
debugMode: false,
|
||||
};
|
||||
|
||||
const state = {
|
||||
@ -67,6 +68,7 @@ async function saveState() {
|
||||
fraudContracts: state.fraudContracts,
|
||||
tokenHolderCache: state.tokenHolderCache,
|
||||
theme: state.theme,
|
||||
debugMode: state.debugMode,
|
||||
currentView: state.currentView,
|
||||
selectedWallet: state.selectedWallet,
|
||||
selectedAddress: state.selectedAddress,
|
||||
@ -126,6 +128,8 @@ async function loadState() {
|
||||
state.fraudContracts = saved.fraudContracts || [];
|
||||
state.tokenHolderCache = saved.tokenHolderCache || {};
|
||||
state.theme = saved.theme || "system";
|
||||
state.debugMode =
|
||||
saved.debugMode !== undefined ? saved.debugMode : false;
|
||||
state.currentView = saved.currentView || null;
|
||||
state.selectedWallet =
|
||||
saved.selectedWallet !== undefined ? saved.selectedWallet : null;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user