mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-27 22:18:36 +00:00
* badges: webapp (#7433) * badges: service migrations, store and catalog * badges: BTCPay provider and settlement poller * badges: web listener and /api endpoints * web: checkout single-page app * badges: tests and BTCPay fixtures * badges: README and ini reference * badges: fix hex16 build on GHC 8.10.7 * badges: Stripe card lane * badges: fix Stripe card checkout, add theming * badges: add a discount row to the order summary * badges: site navbar, embedding, theme, Forget move * badges: use SB code prefix in web checkout * badges: rename sxb app namespace to sb * badges: embed checkout nav via site; keep original app navbar * badges: post iframe height, apply site background when embedded * badges: embed dark surfaces, steadier iframe height * badges: hide app footer when embedded * badges: size embedded body to content, not viewport * badges: declare color-scheme to stop reload flash * badges: fade shell in on load, no reload blank * badges: prerender app shell into index.html * badges: pre-paint theme, hide shell on deep reload * badges: logo returns to landing client-side * badges: embedded wizard back, buy-a-code, resume * badges: signal app-managed screens, resume across reload * badges: rebuild wizard history on deep load so Back walks it * badges: carry welcome-page height as the iframe floor * badges: keep selection on Buy a code; rename to Your codes * badges: read web shell as UTF-8, not locale * badges: resume the exact paid order after Stripe card redirect * badges: move docker deploy under scripts * badges: add serve_webapp toggle and webapp export * badges: wire split webapp deploy in docker config * badges: quiet agent logs by default * badges: resume card redirect in the embedded frame * badges: migrate Stripe adapter to PaymentIntents * badges: correct Stripe restricted key scopes in ini example * badges: card via Payment Element and PaymentIntents * badges: fix stale Checkout Session wording in Stripe adapter * badges: fix stale CheckoutActions reference in card comment * badges: order shell stylesheet before bootstrap script * badges: remove development card stand-in * badges: theme the Stripe card form with the site palette * badges: exclude web from the Haskell build stage * badges: unify invoice cancel and mark canceled * badges: default log level to info * badges: unify closed-invoice buy-again button * badges: mute agent connection logs at info level * badges: show purchase time in local timezone in Your codes * badges: log service events on own channel, quiet agent * badges: fold service migrations into one baseline * badges: run compose on postgres over host network * badges: use high-res hero art * badges: add web CI to catch stale builds * badges: rebuild web shell from committed source * badges: normalize invoice-code link and columns * badges: drop unused columns, rename index * badges: note deferred receipt_hash in migrations * badges: apply code-review fixes * badges: reduce comments across service and web --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com> Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> * badges: improve web page (#7546) * badges: improve web page * improve layout * improve layout * fix * small changes --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> * badges: read one issuer key from the ini * badges: move and group the service tests * badges: service fixes (#7567) * badges: match the redeem error wording in tests * badges: drop unused imports in the bot tests * badges: cancel Stripe orders when they expire * badges: correct the Stripe config and docs * badges: refuse to revoke a redeemed code * badges: make the fake Stripe cancel like Stripe * badges: limit replayed webhook deliveries --------- Co-authored-by: sh <37271604+shumvgolove@users.noreply.github.com> Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com> Co-authored-by: shum <github.shum@liber.li> Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
60 lines
2.2 KiB
TypeScript
60 lines
2.2 KiB
TypeScript
import { readFileSync } from "node:fs";
|
|
|
|
export interface Rule { selector: string; decls: Map<string, string> }
|
|
interface Sheet { rules: Rule[]; media: Array<{ query: string; rules: Rule[] }> }
|
|
|
|
function declarations(body: string): Map<string, string> {
|
|
const out = new Map<string, string>();
|
|
for (const part of body.split(";")) {
|
|
const at = part.indexOf(":");
|
|
if (at < 0) continue;
|
|
out.set(part.slice(0, at).trim().toLowerCase(), part.slice(at + 1).trim());
|
|
}
|
|
return out;
|
|
}
|
|
|
|
// Brace-matching with comments stripped; handles one level of @media.
|
|
function parseCss(source: string): Sheet {
|
|
const text = source.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
const sheet: Sheet = { rules: [], media: [] };
|
|
let i = 0;
|
|
while (i < text.length) {
|
|
const open = text.indexOf("{", i);
|
|
if (open < 0) break;
|
|
const prelude = text.slice(i, open).trim();
|
|
let depth = 1;
|
|
let j = open + 1;
|
|
while (j < text.length && depth > 0) {
|
|
if (text[j] === "{") depth++;
|
|
else if (text[j] === "}") depth--;
|
|
j++;
|
|
}
|
|
const body = text.slice(open + 1, j - 1);
|
|
if (prelude.startsWith("@media")) {
|
|
sheet.media.push({ query: prelude.slice("@media".length).trim(), rules: parseCss(body).rules });
|
|
} else if (!prelude.startsWith("@")) {
|
|
for (const selector of prelude.split(",")) sheet.rules.push({ selector: selector.trim(), decls: declarations(body) });
|
|
}
|
|
i = j;
|
|
}
|
|
return sheet;
|
|
}
|
|
|
|
export const sheet = parseCss(readFileSync(new URL("../../public/styles.css", import.meta.url), "utf8"));
|
|
|
|
export const ruleFor = (rules: Rule[], selector: string): Rule | undefined => rules.find((r) => r.selector === selector);
|
|
|
|
export const mediaFor = (query: string): { query: string; rules: Rule[] } | undefined =>
|
|
sheet.media.find((m) => m.query.replace(/\s+/g, "") === query.replace(/\s+/g, ""));
|
|
|
|
// The value the browser uses is the last declaration for the selector in the sheet, not the first.
|
|
export function decl(selector: string, property: string): string | undefined {
|
|
let value: string | undefined;
|
|
for (const rule of sheet.rules) {
|
|
if (rule.selector !== selector) continue;
|
|
const found = rule.decls.get(property);
|
|
if (found !== undefined) value = found;
|
|
}
|
|
return value;
|
|
}
|