Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,7 @@ module.exports = {
// Nested ternaries from before the rule.
{
files: [
"e2e/playwright.config.ts",
"e2e/soak/support/probes.ts",
"e2e/soak/support/tracker.ts",
"e2e/tests/send-across-restart.spec.ts",
"src/lib/reports/callTimeline.ts",
"src/packages/addons/src/pluginPanels.ts",
"src/packages/common/src/auth/keycloak.ts",
"src/packages/common/src/components/NotificationLevelMenu.tsx",
"src/packages/common/src/hooks/useCustomThemes.ts",
"src/packages/common/src/hooks/useTheme.ts",
"src/packages/socket/src/components/ChannelList.tsx",
"src/packages/socket/src/components/ChatEditor.tsx",
"src/packages/socket/src/components/ChatMessage.tsx",
Expand Down Expand Up @@ -146,9 +137,6 @@ module.exports = {
"src/packages/socket/src/components/memberInvite.ts",
"src/packages/socket/src/components/serverView.tsx",
"src/packages/socket/src/components/tileColor.ts",
"src/packages/socket/src/hooks/contactFilterStore.ts",
"src/packages/socket/src/hooks/dmDirectory.ts",
"src/packages/socket/src/hooks/mergeMessages.ts",
"src/packages/socket/src/hooks/useEmoteImport.ts",
"src/packages/socket/src/hooks/useHistoryWindow.ts",
"src/packages/socket/src/hooks/useOpenDmSpace.ts",
Expand Down
5 changes: 4 additions & 1 deletion e2e/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import { defineConfig, devices } from "@playwright/test";

const CI = !!process.env.CI;

// Each worker starts its own server, so a shared one gets one worker.
const WORKERS = CI ? 4 : 3;

export default defineConfig({
testDir: "./tests",
outputDir: "./test-results",
globalSetup: "./global-setup.ts",
forbidOnly: CI,
retries: CI ? 1 : 0,
// Each worker starts its own server. CI runners on this public repo have four cores, so four workers.
workers: process.env.GRYT_E2E_SERVER ? 1 : CI ? 4 : 3,
workers: process.env.GRYT_E2E_SERVER ? 1 : WORKERS,
timeout: 60_000,
expect: { timeout: 15_000 },
// CI shards the suite across several runners (see ci.yml); each writes its own blob file,
Expand Down
3 changes: 2 additions & 1 deletion e2e/soak/support/probes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ export function networkWatch(log: EventWriter, everyMs = 5000): Stoppable {
for (const [name, list] of Object.entries(networkInterfaces())) {
for (const a of list ?? []) {
if (a.internal) continue;
const scope = a.family === "IPv6" ? (a.address.startsWith("fe80") ? "link" : "global") : "v4";
const v6scope = a.address.startsWith("fe80") ? "link" : "global";
const scope = a.family === "IPv6" ? v6scope : "v4";
const id = createHash("sha256").update(a.address).digest("hex").slice(0, 8);
seen.set(`${name}/${scope}/${id}`, a.family);
}
Expand Down
6 changes: 4 additions & 2 deletions e2e/soak/support/tracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ export class Tracker {

status(): string {
const servers = [...this.serverUp.values()];
const sio = servers.length === 0 ? "sio -" : servers.every(Boolean) ? "sio up" : "sio DOWN";
const allUp = servers.every(Boolean) ? "sio up" : "sio DOWN";
const sio = servers.length === 0 ? "sio -" : allUp;
const ice = [...this.ice.values()].filter((s) => s !== "closed");
const media = ice.length === 0 ? "" : ` ice ${ice.join("/")} rtt ${this.last.rtt ?? "?"}ms aob ${this.last.aob ? Math.round(this.last.aob / 1000) + "k" : "?"} audio ${this.last.audioFlowing ?? 0}/${this.last.audioIn ?? 0}`;
const voice = this.inVoice === null ? "" : this.inVoice ? " voice in" : " voice OUT";
const inOut = this.inVoice ? " voice in" : " voice OUT";
const voice = this.inVoice === null ? "" : inOut;
const { serverDrops, sfuDrops, iceDrops } = this.counts;
return `${this.who.padEnd(14)} ${sio} sfu-ws ${this.sfuOpen}${voice}${media} drops sio ${serverDrops} sfu ${sfuDrops} ice ${iceDrops}`;
}
Expand Down
11 changes: 6 additions & 5 deletions e2e/tests/send-across-restart.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,10 @@ async function rowStates(rows: Locator, nonces: Set<string>): Promise<string[]>
const seen = await rows.evaluateAll((els) =>
els.map((el) => ({ id: el.getAttribute("data-message-id") ?? "", failed: !!el.textContent?.includes("Failed to send") })),
);
return seen.map(({ id, failed }) =>
failed ? "failed" : id.startsWith("pending-") || nonces.has(id) ? "pending" : "sent",
);
return seen.map(({ id, failed }) => {
if (failed) return "failed";
return id.startsWith("pending-") || nonces.has(id) ? "pending" : "sent";
});
}

for (const kind of ["channel", "dm", "thread"] as const) {
Expand All @@ -207,8 +208,8 @@ for (const kind of ["channel", "dm", "thread"] as const) {
await joinServer(bob.page, server.host);
}

const conversation =
kind === "channel" ? channel(alice.page) : kind === "dm" ? await dm(alice, bob!) : await thread(alice.page);
const opener = { channel: () => channel(alice.page), dm: () => dm(alice, bob!), thread: () => thread(alice.page) };
const conversation = await opener[kind]();

// Here before the restart, so a first page rebuilt after it has to carry it.
const before = unique("said before the restart");
Expand Down
8 changes: 6 additions & 2 deletions src/lib/reports/callTimeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,14 @@ let before: CallStatsSample | null = null;

const ms = (v: number | null) => (v === null ? "?" : `${Math.round(v)}ms`);

function lostSince(now: number | null, before: number | null | undefined): string {
if (now === null) return "?";
return before == null ? String(now) : `+${now - before}`;
}

/** One line: what the call looked like this second, and what changed since the last. */
export function formatCallSample(secs: number, now: CallStatsSample, prev: CallStatsSample | null): string {
const lost =
now.packetsLost === null ? "?" : prev?.packetsLost == null ? String(now.packetsLost) : `+${now.packetsLost - prev.packetsLost}`;
const lost = lostSince(now.packetsLost, prev?.packetsLost);
return [
`+${secs}s`,
`socket ${ms(now.socketRttMs)}`,
Expand Down
2 changes: 1 addition & 1 deletion src/packages/addons/src/pluginPanels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function republish(): void {
* By addon id, compared with `<` rather than `localeCompare`: under `nb` Chrome
* answers -1 for `"zzz".localeCompare("aaa")`, so the order was not sorted.
*/
snapshot = [...panels.values()].sort((a, b) => (a.addonId < b.addonId ? -1 : a.addonId > b.addonId ? 1 : 0));
snapshot = [...panels.values()].sort((a, b) => (a.addonId < b.addonId ? -1 : Number(a.addonId > b.addonId)));
for (const listener of listeners) listener();
}

Expand Down
4 changes: 1 addition & 3 deletions src/packages/common/src/components/NotificationLevelMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ export function NotificationLevelMenu({
parentItemId: placement?.parentItemId ?? null,
defaultLevel: getPlacement(host, scope.id)?.defaultLevel ?? null,
})
: scope.kind === "folder"
? (getOwnLevel(host, { kind: "server" }) ?? "all")
: "all";
: (scope.kind === "folder" && getOwnLevel(host, { kind: "server" })) || "all";

/* What this scope currently comes out as: its own setting, else what it inherits. */
const resolved: NotificationLevel = own ?? inherited;
Expand Down
10 changes: 3 additions & 7 deletions src/packages/common/src/hooks/useCustomThemes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,9 @@ function useCustomThemesImpl(): CustomThemesState {
* A preset the library ships, or one somebody saved. Presets are stored as
* "preset:<id>", so a newer @gryt/ui brings its corrections with it.
*/
const activeTheme =
activeId === null
? null
: activeId.startsWith(PRESET_PREFIX)
? (grytPresetsById.get(activeId.slice(PRESET_PREFIX.length))?.theme ??
null)
: (themes.find((entry) => entry.id === activeId)?.theme ?? null);
const preset = activeId?.startsWith(PRESET_PREFIX) ? grytPresetsById.get(activeId.slice(PRESET_PREFIX.length)) : null;
const saved = activeId === null || preset !== null ? null : themes.find((entry) => entry.id === activeId);
const activeTheme = (preset ?? saved)?.theme ?? null;

return {
themes,
Expand Down
3 changes: 2 additions & 1 deletion src/packages/common/src/hooks/useTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,9 @@ function useThemeHook(): ThemeSettings {
return () => systemPrefersDark.removeEventListener("change", handleChange);
}, [systemPrefersDark]);

const systemAppearance = systemIsDark ? "dark" : "light";
const resolvedAppearance: AppearanceResolved =
appearancePreference === "system" ? (systemIsDark ? "dark" : "light") : appearancePreference;
appearancePreference === "system" ? systemAppearance : appearancePreference;

function setAccentColor(value: AccentColor) {
setAccentColorState(value);
Expand Down
14 changes: 9 additions & 5 deletions src/packages/socket/src/hooks/contactFilterStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,16 @@ function commit(next: FilteredItem[]): void {
/** What they did, in a few words. */
export function filteredSummary(item: FilteredItem): string {
const times = item.count === 1 ? "" : ` ${item.count} times`;
const what =
item.kind === "call" ? `Called you${times}`
: item.kind === "conversation" ? "Started a conversation"
: item.count === 1 ? "Sent a message" : `Sent ${item.count} messages`;
const what = filteredAction(item, times);
return item.reason === "flood" ? `${what}, in a burst` : what;
}

function filteredAction(item: FilteredItem, times: string): string {
if (item.kind === "call") return `Called you${times}`;
if (item.kind === "conversation") return "Started a conversation";
return item.count === 1 ? "Sent a message" : `Sent ${item.count} messages`;
}

/** A conversation and its messages are one row, and a call is its own. */
function rowKind(kind: FilteredEvent["kind"]): "call" | "message" {
return kind === "call" ? "call" : "message";
Expand All @@ -113,7 +116,8 @@ export function recordFiltered(event: FilteredEvent): void {
// The conversation arriving adds no message to the count; its first message does.
const opened = event.kind === "conversation";
const kind = opened ? (prev?.kind ?? "conversation") : event.kind;
const count = opened ? (prev?.count ?? 1) : prev?.kind === "conversation" ? 1 : (prev?.count ?? 0) + 1;
const nextCount = prev?.kind === "conversation" ? 1 : (prev?.count ?? 0) + 1;
const count = opened ? (prev?.count ?? 1) : nextCount;
const item: FilteredItem = {
host: event.host,
conversationId: event.conversationId,
Expand Down
2 changes: 1 addition & 1 deletion src/packages/socket/src/hooks/dmDirectory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function newestFirst(a: DirectoryEntry, b: DirectoryEntry): number {
}

function compare(a: string, b: string): number {
return a < b ? -1 : a > b ? 1 : 0;
return a < b ? -1 : Number(a > b);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/packages/socket/src/hooks/mergeMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function compareMessages(a: ChatMessage, b: ChatMessage): number {
if (!!a.pending !== !!b.pending) return a.pending ? 1 : -1;
const diff = millis(a.created_at) - millis(b.created_at);
if (diff !== 0) return diff;
return a.message_id < b.message_id ? -1 : a.message_id > b.message_id ? 1 : 0;
return a.message_id < b.message_id ? -1 : Number(a.message_id > b.message_id);
}

/**
Expand Down
Loading