mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
* fix(voice): 4 defect(s) (OC-0008, OC-0009, OC-0042, OC-0080) Guard LiveKit session state against supersession: bump the camera/screen generation in leaveVoice and teardownForReconnect so an in-flight enable discards its track, bail out of restoreLocalVoiceState when a newer room claimed _room mid-await, and recheck isStateConnected in the auto-reconnect tail. * fix(ws): 1 defect(s) (OC-0019) * fix(db): 1 defect(s) (OC-0023) * fix(ws): 1 defect(s) (OC-0029) * fix(ws): 1 defect(s) (OC-0032) * fix(voice): 1 defect(s) (OC-0034) * fix(admin): 1 defect(s) (OC-0035) * fix(service): 2 defect(s) (OC-0036, OC-0128) * fix(voice): 2 defect(s) (OC-0038, OC-0065) OC-0038: the LiveKit participant_left webhook cleared the leaver's own client voice state before broadcasting voice_leave, so the broadcast audience (READ_MESSAGES holders union still-in-the-room participants) could no longer see them. Voice membership is gated on CONNECT_VOICE alone, so a participant without READ_MESSAGES never learned the server had torn down their call. Extracted finishVoiceLeave's audience logic into broadcastVoiceEventWithLeaver and used it on the webhook path. OC-0065: handleWebhookParticipantJoined OR'd a GetVoiceState read error into the same branch as "no matching row", so a transient DB failure ejected a legitimate participant from the SFU mid-call. Now the read error is logged and the check skipped, matching sweepStaleVoiceStates. * fix(client): 1 defect(s) (OC-0041) * fix(client): 1 defect(s) (OC-0043) * fix(client): 1 defect(s) (OC-0046) * fix(client): 1 defect(s) (OC-0047) * fix(client): 1 defect(s) (OC-0049) * fix(client): 1 defect(s) (OC-0108) * fix(client): 2 defect(s) (OC-0111, OC-0143) OC-0111: retry a presence_update dropped by the 1-per-10s limiter once the window reopens, so auto-idle's return-to-online does not leave the server and every other client stuck on idle. OC-0143: pass apiConfig.host to the DM profile sidebar so per-user notes are scoped per server, matching channel mutes, the NSFW gate and volume. * test(ws): align aborted-switch test with OC-0034 no-resurrect behavior The fix agent rewrote this pre-existing test (it locked the buggy restore path) but the prove agent left it out of c67d25ed; committed state alone failed go test ./ws/ without it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
51 lines
2.3 KiB
TypeScript
51 lines
2.3 KiB
TypeScript
// jsdom never applies app.css, so a computed-style assertion here would pass
|
|
// whether or not the rules exist (see status-picker-userbar.test.ts for the
|
|
// same pattern). Instead this pins the CSS *source*.
|
|
//
|
|
// applyTheme() (components/settings/helpers.ts) writes theme tokens --
|
|
// including --text-normal -- as an *inline* style on document.documentElement.
|
|
// An inline declaration always beats a plain class rule on the same element,
|
|
// so `.high-contrast { --text-normal: ... }` can never win against it: the
|
|
// High Contrast toggle's headline promise (pure-white body text) is a no-op
|
|
// unless the override is `!important`.
|
|
//
|
|
// applyThemeByName() (lib/themes.ts) does the same thing for custom themes,
|
|
// except it writes the inline override on document.body instead of
|
|
// documentElement -- so the override also needs a selector that reaches body
|
|
// while high-contrast is active, not just one that targets html.
|
|
import { readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { describe, it, expect } from "vitest";
|
|
|
|
describe("high-contrast CSS overrides beat inline theme styles", () => {
|
|
const css = readFileSync(join(process.cwd(), "src/styles/app.css"), "utf8");
|
|
|
|
function highContrastRuleBody(): string {
|
|
const match = /\.high-contrast[^{]*\{([^}]*)\}/.exec(css);
|
|
expect(match, "expected a `.high-contrast { ... }` rule in app.css").not.toBeNull();
|
|
return match![1]!;
|
|
}
|
|
|
|
it("declares --text-normal, --text-muted, and --bg-active with !important", () => {
|
|
const body = highContrastRuleBody();
|
|
|
|
for (const prop of ["--text-normal", "--text-muted", "--bg-active"]) {
|
|
const declaration = new RegExp(`${prop}\\s*:[^;]*;`).exec(body);
|
|
expect(declaration, `expected a declaration for ${prop}`).not.toBeNull();
|
|
expect(
|
|
declaration![0],
|
|
`${prop} must be !important -- otherwise applyTheme()'s inline style on ` +
|
|
`documentElement always wins and the toggle does nothing`,
|
|
).toMatch(/!important/);
|
|
}
|
|
});
|
|
|
|
it("also reaches document.body, where custom-theme inline overrides live", () => {
|
|
expect(
|
|
css,
|
|
"expected a selector reaching body while .high-contrast is active (e.g. " +
|
|
"`.high-contrast body`), otherwise custom themes' inline body vars never see the override",
|
|
).toMatch(/\.high-contrast[^{,]*body\s*[{,]/);
|
|
});
|
|
});
|