Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f3bb039
feat: register callto:/tel: deep link handlers (DAMOVO-1)
jeanfbrito May 8, 2026
154293f
test: add unit tests for telephony deep link parsing and routing
jeanfbrito May 8, 2026
ab816c0
fix: attach server selection dialog to root window and guard against …
jeanfbrito May 8, 2026
8431a5f
chore: add GitNexus code intelligence config to CLAUDE.md
jeanfbrito May 9, 2026
5050a1d
feat: support sha-prefixed exception versions by git commit hash
jeanfbrito May 9, 2026
c83728f
feat: add telephony preferred server settings UI
jeanfbrito May 9, 2026
8f56445
fix: move MimeType into desktop.entry for electron-builder v26 compat
jeanfbrito May 11, 2026
6ddda80
i18n: add translations for telephony server selection dialog
jeanfbrito May 11, 2026
9d0a4d3
feat: replace native dialog with Fuselage modal for telephony server …
jeanfbrito May 12, 2026
f214798
refactor(telephony-modal): tighten vertical spacing
jeanfbrito May 12, 2026
9cdf640
test(telephony): add coverage for preload, settings dropdown, and ser…
jeanfbrito May 13, 2026
1e04a7b
fix(telephony): decode percent-encoded URI before sanitization
jeanfbrito May 13, 2026
8f1b2f4
fix(supportedVersions): make sha- exception prefix check case-insensi…
jeanfbrito May 13, 2026
3c2ab23
fix(telephony-ui): harden URL parsing and improve modal accessibility
jeanfbrito May 13, 2026
ce12206
Feat/telephony shortcut main process (#3334)
jeanfbrito May 14, 2026
9025556
Add telephony clipboard dial shortcut (#3330)
jeanfbrito May 14, 2026
029e20b
fix telephony deeplink edge cases
jeanfbrito May 14, 2026
c63b431
chore: format telephony PR lint fixes
jeanfbrito May 14, 2026
32299e4
Merge branch 'feat/telephony-deeplink' of https://github.com/RocketCh…
jeanfbrito May 14, 2026
e85a457
refactor: add marginBlock to Field components in SettingsView features
jeanfbrito May 14, 2026
87399fe
chore: polish telephony settings copy
jeanfbrito May 14, 2026
f952c6f
chore: add telephony settings translations
jeanfbrito May 14, 2026
fecce23
Merge branch 'feat/telephony-deeplink' of https://github.com/RocketCh…
jeanfbrito May 15, 2026
773cd30
feat(telephony): add master toggle and gate runtime registration
jeanfbrito May 15, 2026
9151462
feat(telephony): prompt user about default handler conflicts on opt-in
jeanfbrito May 15, 2026
19ebf61
test(app): nest PersistableValues spec into __tests__
jeanfbrito May 15, 2026
d27b48b
feat(menu): register CmdOrCtrl+, accelerator for Settings on all plat…
jeanfbrito May 17, 2026
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ scripts/msi-test/.known_hosts
# legacy agent docs (consolidated into CLAUDE.md)
AGENTS.md
src/outlookCalendar/AGENTS.md
.gitnexus
45 changes: 45 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ This prevents MSI build failures from KMS CNG provider conflicts.

- `*.spec.ts` — Renderer process tests
- `*.main.spec.ts` — Main process tests
- Renderer specs must live in a Jest-matched nested path, e.g. `src/<module>/<subdir>/*.spec.ts(x)` or `src/<module>/renderer.spec.ts(x)`. Flat `src/<module>/*.spec.ts` files are not discovered by current `testMatch`; verify new specs with `yarn test --listTests --runTestsByPath <file>`.
- Uses `@kayahr/jest-electron-runner` for Electron environment simulation
- Tests run on Windows, macOS, AND Linux CI — always verify cross-platform

Expand Down Expand Up @@ -103,3 +104,47 @@ git worktree add ../Rocket.Chat.Electron-worktrees/feature-name -b new-branch ma
- Use measurable descriptions: "reduced memory usage", "improved by X%"
- **Never invent metrics** — no estimated time spent, no speculated user counts. Only include numbers from actual logs, error messages, or documented sources.
- PR descriptions: straightforward language, focus on what changed and why

<!-- gitnexus:start -->
# GitNexus — Code Intelligence

This project is indexed by GitNexus as **Rocket.Chat.Electron** (4593 symbols, 7029 relationships, 103 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.

> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.

## Always Do

- **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `gitnexus_impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
- **MUST run `gitnexus_detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows.
- **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
- When exploring unfamiliar code, use `gitnexus_query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
- When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `gitnexus_context({name: "symbolName"})`.

## Never Do

- NEVER edit a function, class, or method without first running `gitnexus_impact` on it.
- NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
- NEVER rename symbols with find-and-replace — use `gitnexus_rename` which understands the call graph.
- NEVER commit changes without running `gitnexus_detect_changes()` to check affected scope.

## Resources

| Resource | Use for |
|----------|---------|
| `gitnexus://repo/Rocket.Chat.Electron/context` | Codebase overview, check index freshness |
| `gitnexus://repo/Rocket.Chat.Electron/clusters` | All functional areas |
| `gitnexus://repo/Rocket.Chat.Electron/processes` | All execution flows |
| `gitnexus://repo/Rocket.Chat.Electron/process/{name}` | Step-by-step execution trace |

## CLI

| Task | Read this skill file |
|------|---------------------|
| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |

<!-- gitnexus:end -->
11 changes: 6 additions & 5 deletions electron-builder.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"files": ["app/**/*", "package.json"],
"extraResources": ["build/icon.ico", "servers.json"],
"appId": "chat.rocket",
"protocols": {
"name": "Rocket.Chat",
"schemes": ["rocketchat"]
},
"protocols": [
{ "name": "Rocket.Chat", "schemes": ["rocketchat"] },
{ "name": "Rocket.Chat Telephony", "schemes": ["callto", "tel"] }
],
"afterPack": "./build/afterPack.js",
"mac": {
"category": "public.app-category.productivity",
Expand Down Expand Up @@ -127,7 +127,8 @@
"Name": "Rocket.Chat",
"Comment": "Official Rocket.Chat Desktop Client",
"GenericName": "Rocket.Chat",
"Categories": "GNOME;GTK;Network;InstantMessaging"
"Categories": "GNOME;GTK;Network;InstantMessaging",
"MimeType": "x-scheme-handler/rocketchat;x-scheme-handler/callto;x-scheme-handler/tel;"
}
},
"artifactName": "rocketchat-${version}-${os}-${arch}.${ext}"
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
"@rollup/plugin-json": "~6.1.0",
"@rollup/plugin-node-resolve": "~15.2.3",
"@rollup/plugin-replace": "~5.0.5",
"@testing-library/dom": "~10.4.1",
"@testing-library/jest-dom": "~6.9.1",
"@testing-library/react": "~16.3.2",
"@types/archiver": "~7.0.0",
"@types/dompurify": "~3.2.0",
"@types/electron-devtools-installer": "~2.2.5",
Expand Down
23 changes: 21 additions & 2 deletions src/app/PersistableValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Certificate } from 'electron';

import type { Download } from '../downloads/common';
import type { Server } from '../servers/common';
import type { TelephonyGlobalShortcutConfig } from '../telephony/actions';
import type { WindowState } from '../ui/common';

type PersistableValues_0_0_0 = {
Expand Down Expand Up @@ -106,9 +107,15 @@ type PersistableValues_4_13_0 = PersistableValues_4_11_0 & {
isDebugLoggingEnabled: boolean;
};

type PersistableValues_4_14_0 = PersistableValues_4_13_0 & {
isTelephonyEnabled: boolean;
telephonyPreferredServer: string | null;
telephonyGlobalShortcutConfig: TelephonyGlobalShortcutConfig;
};

export type PersistableValues = Pick<
PersistableValues_4_13_0,
keyof PersistableValues_4_13_0
PersistableValues_4_14_0,
keyof PersistableValues_4_14_0
>;

export const migrations = {
Expand Down Expand Up @@ -201,4 +208,16 @@ export const migrations = {
...before,
isDebugLoggingEnabled: false,
}),
'>=4.14.0': (before: PersistableValues_4_13_0): PersistableValues_4_14_0 => ({
...before,
isTelephonyEnabled:
(before as Partial<PersistableValues_4_14_0>).isTelephonyEnabled ?? false,
telephonyPreferredServer:
(before as Partial<PersistableValues_4_14_0>).telephonyPreferredServer ??
null,
telephonyGlobalShortcutConfig: {
enabled: false,
accelerator: null,
},
}),
};
18 changes: 18 additions & 0 deletions src/app/__tests__/PersistableValues.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { migrations } from '../PersistableValues';

describe('PersistableValues migrations', () => {
it('adds telephony shortcut config without losing a persisted telephony server', () => {
const before = {
telephonyPreferredServer: 'https://chat.example.com',
} as unknown as Parameters<(typeof migrations)['>=4.14.0']>[0];

expect(migrations['>=4.14.0'](before)).toEqual({
isTelephonyEnabled: false,
telephonyPreferredServer: 'https://chat.example.com',
telephonyGlobalShortcutConfig: {
enabled: false,
accelerator: null,
},
});
});
});
20 changes: 20 additions & 0 deletions src/app/main/app.main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,26 @@ describe('performElectronStartup - Platform Detection', () => {
});
});

describe('Telephony scheme gating', () => {
it('registers rocketchat at startup', () => {
performElectronStartup();

expect(app.setAsDefaultProtocolClient).toHaveBeenCalledWith('rocketchat');
});

it('does NOT register tel at startup', () => {
performElectronStartup();

expect(app.setAsDefaultProtocolClient).not.toHaveBeenCalledWith('tel');
});

it('does NOT register callto at startup', () => {
performElectronStartup();

expect(app.setAsDefaultProtocolClient).not.toHaveBeenCalledWith('callto');
});
});

describe('Integration', () => {
it('should work correctly with PipeWire feature enabled', () => {
process.env.XDG_SESSION_TYPE = 'x11';
Expand Down
15 changes: 13 additions & 2 deletions src/app/main/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,15 @@ export const packageJsonInformation = {

export const electronBuilderJsonInformation = {
appId: electronBuilderJson.appId,
protocol: electronBuilderJson.protocols.schemes[0],
protocol: (electronBuilderJson.protocols as Array<{ schemes: string[] }>)[0]
.schemes[0],
protocols: (
electronBuilderJson.protocols as Array<{ schemes: string[] }>
).flatMap((p) => p.schemes),
};

export const TELEPHONY_SCHEMES = ['tel', 'callto'] as const;

let isScreenCaptureFallbackForced = false;

export const getPlatformName = (): string => {
Expand Down Expand Up @@ -83,7 +89,12 @@ export const relaunchApp = (...args: string[]): void => {
};

export const performElectronStartup = (): void => {
app.setAsDefaultProtocolClient(electronBuilderJsonInformation.protocol);
for (const scheme of electronBuilderJsonInformation.protocols) {
if ((TELEPHONY_SCHEMES as readonly string[]).includes(scheme)) {
continue;
}
app.setAsDefaultProtocolClient(scheme);
}
app.setAppUserModelId(electronBuilderJsonInformation.appId);

app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');
Expand Down
6 changes: 6 additions & 0 deletions src/app/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,10 @@ export const selectPersistableValues = createStructuredSelector({
}: RootState) => isDetailedEventsLoggingEnabled,
isDebugLoggingEnabled: ({ isDebugLoggingEnabled }: RootState) =>
isDebugLoggingEnabled,
telephonyPreferredServer: ({ telephonyPreferredServer }: RootState) =>
telephonyPreferredServer,
telephonyGlobalShortcutConfig: ({
telephonyGlobalShortcutConfig,
}: RootState) => telephonyGlobalShortcutConfig,
isTelephonyEnabled: ({ isTelephonyEnabled }: RootState) => isTelephonyEnabled,
});
Loading
Loading