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
2 changes: 1 addition & 1 deletion apps/desktop/src/lib/trpc/routers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const createAppRouter = (getWindow: () => BrowserWindow | null) => {
settings: createSettingsRouter(),
config: createConfigRouter(),
uiState: createUiStateRouter(),
ringtone: createRingtoneRouter(),
ringtone: createRingtoneRouter(getWindow),
});
};

Expand Down
115 changes: 85 additions & 30 deletions apps/desktop/src/lib/trpc/routers/ringtone/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import type { ChildProcess } from "node:child_process";
import { execFile } from "node:child_process";
import { existsSync, readdirSync } from "node:fs";
import { z } from "zod";
import { existsSync } from "node:fs";
import { TRPCError } from "@trpc/server";
import type { BrowserWindow, OpenDialogOptions } from "electron";
import { dialog } from "electron";
import {
getCustomRingtoneInfo,
getCustomRingtonePath,
importCustomRingtoneFromPath,
} from "main/lib/custom-ringtones";
import { getSoundPath } from "main/lib/sound-paths";
import {
getSoundPath,
getSoundsDirectory,
} from "../../../../main/lib/sound-paths";
CUSTOM_RINGTONE_ID,
getRingtoneFilename,
isBuiltInRingtoneId,
} from "shared/ringtones";
import { z } from "zod";
import { publicProcedure, router } from "../..";

/**
Expand Down Expand Up @@ -88,23 +98,43 @@ function playSoundFile(soundPath: string): void {
}
}

function getRingtoneSoundPath(ringtoneId: string): string | null {
if (!ringtoneId || ringtoneId === "") {
return null;
}

if (ringtoneId === CUSTOM_RINGTONE_ID) {
return getCustomRingtonePath();
}

if (!isBuiltInRingtoneId(ringtoneId)) {
return null;
}

const filename = getRingtoneFilename(ringtoneId);
if (!filename) {
return null;
}

return getSoundPath(filename);
}

/**
* Ringtone router for audio preview and playback operations
*/
export const createRingtoneRouter = () => {
export const createRingtoneRouter = (getWindow: () => BrowserWindow | null) => {
return router({
/**
* Preview a ringtone sound by filename
* Preview a ringtone by ringtone ID.
*/
preview: publicProcedure
.input(z.object({ filename: z.string() }))
.input(z.object({ ringtoneId: z.string() }))
.mutation(({ input }) => {
// Handle "none" case - no sound
if (!input.filename || input.filename === "") {
const soundPath = getRingtoneSoundPath(input.ringtoneId);
if (!soundPath) {
return { success: true as const };
}

const soundPath = getSoundPath(input.filename);
playSoundFile(soundPath);
return { success: true as const };
}),
Expand All @@ -118,24 +148,49 @@ export const createRingtoneRouter = () => {
}),

/**
* Get the list of available ringtone files from the sounds directory
* Returns metadata for the imported custom ringtone, if one exists.
*/
list: publicProcedure.query(() => {
const ringtonesDir = getSoundsDirectory();
const files: string[] = [];

// Add ringtones from the sounds directory if it exists
if (existsSync(ringtonesDir)) {
const dirFiles = readdirSync(ringtonesDir).filter(
(file) =>
file.endsWith(".mp3") ||
file.endsWith(".wav") ||
file.endsWith(".ogg"),
);
files.push(...dirFiles);
getCustom: publicProcedure.query(() => {
return getCustomRingtoneInfo();
}),

/**
* Imports a custom ringtone file from disk and stores it in the Superset home assets directory.
*/
importCustom: publicProcedure.mutation(async () => {
const window = getWindow();
const openDialogOptions: OpenDialogOptions = {
properties: ["openFile"],
title: "Select Notification Sound",
filters: [
{
name: "Audio",
extensions: ["mp3", "wav", "ogg"],
},
],
};
const result = window
? await dialog.showOpenDialog(window, openDialogOptions)
: await dialog.showOpenDialog(openDialogOptions);

if (result.canceled || result.filePaths.length === 0) {
return { canceled: true as const, ringtone: null };
}

return files;
try {
const ringtone = await importCustomRingtoneFromPath(
result.filePaths[0],
);
return { canceled: false as const, ringtone };
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
message:
error instanceof Error
? error.message
: "Failed to import custom ringtone",
});
}
}),
});
};
Expand All @@ -144,11 +199,11 @@ export const createRingtoneRouter = () => {
* Plays the notification sound based on the selected ringtone.
* This is used by the notification system.
*/
export function playNotificationRingtone(filename: string): void {
if (!filename || filename === "") {
return; // No sound for "none" option
export function playNotificationRingtone(ringtoneId: string): void {
const soundPath = getRingtoneSoundPath(ringtoneId);
if (!soundPath) {
return;
}

const soundPath = getSoundPath(filename);
playSoundFile(soundPath);
}
Comment on lines +202 to 209
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all usages of playNotificationRingtone
echo "=== Usages of playNotificationRingtone ==="
rg -n 'playNotificationRingtone' --type=ts --type=tsx -C2

echo ""
echo "=== Usages of playNotificationSound ==="
# Also check playNotificationSound usages
rg -n 'playNotificationSound' --type=ts --type=tsx -C2

Repository: superset-sh/superset

Length of output: 220


🏁 Script executed:

#!/bin/bash
# Find all usages of playNotificationRingtone - search all ts/tsx files
echo "=== Usages of playNotificationRingtone ==="
rg 'playNotificationRingtone' -t ts -C2

echo ""
echo "=== Usages of playNotificationSound ==="
rg 'playNotificationSound' -t ts -C2

echo ""
echo "=== Files matching ringtone related patterns ==="
find . -name "*ringtone*" -o -name "*notification*sound*"

Repository: superset-sh/superset

Length of output: 2307


Remove playNotificationRingtone - it is dead code.

The function at lines 202-209 is never called anywhere in the codebase despite being exported. The notification system uses playNotificationSound from apps/desktop/src/main/lib/notification-sound.ts instead (imported and passed to NotificationManager in apps/desktop/src/main/windows/main.ts). The inline comment claiming this function "is used by the notification system" is incorrect and misleading. Either remove this unused export or clarify its purpose if it is intended for external use.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/lib/trpc/routers/ringtone/index.ts` around lines 202 - 209,
The exported function playNotificationRingtone is dead code and should be
removed; delete the entire playNotificationRingtone function/export (including
its internal calls to getRingtoneSoundPath and playSoundFile) from this module,
and if those helper imports (getRingtoneSoundPath, playSoundFile) become unused
after removal, remove their import statements as well; if this function was
intended for external use instead of the existing playNotificationSound
workflow, replace it with a clear, documented wrapper that delegates to the
canonical playNotificationSound implementation rather than keeping this unused
duplicate.

23 changes: 19 additions & 4 deletions apps/desktop/src/lib/trpc/routers/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { TRPCError } from "@trpc/server";
import { app } from "electron";
import { quitWithoutConfirmation } from "main/index";
import { hasCustomRingtone } from "main/lib/custom-ringtones";
import { localDb } from "main/lib/local-db";
import {
DEFAULT_AUTO_APPLY_DEFAULT_PRESET,
Expand All @@ -19,7 +20,11 @@ import {
DEFAULT_SHOW_RESOURCE_MONITOR,
DEFAULT_TERMINAL_LINK_BEHAVIOR,
} from "shared/constants";
import { DEFAULT_RINGTONE_ID, RINGTONES } from "shared/ringtones";
import {
CUSTOM_RINGTONE_ID,
DEFAULT_RINGTONE_ID,
isBuiltInRingtoneId,
} from "shared/ringtones";
import { z } from "zod";
import { publicProcedure, router } from "../..";
import { getGitAuthorName, getGitHubUsername } from "../workspaces/utils/git";
Expand All @@ -28,7 +33,17 @@ import {
transformFontSettings,
} from "./font-settings.utils";

const VALID_RINGTONE_IDS = RINGTONES.map((r) => r.id);
function isValidRingtoneId(ringtoneId: string): boolean {
if (isBuiltInRingtoneId(ringtoneId)) {
return true;
}

if (ringtoneId === CUSTOM_RINGTONE_ID) {
return hasCustomRingtone();
}

return false;
}

function getSettings() {
let row = localDb.select().from(settings).get();
Expand Down Expand Up @@ -357,7 +372,7 @@ export const createSettingsRouter = () => {
return DEFAULT_RINGTONE_ID;
}

if (VALID_RINGTONE_IDS.includes(storedId)) {
if (isValidRingtoneId(storedId)) {
return storedId;
}

Expand All @@ -378,7 +393,7 @@ export const createSettingsRouter = () => {
setSelectedRingtoneId: publicProcedure
.input(z.object({ ringtoneId: z.string() }))
.mutation(({ input }) => {
if (!VALID_RINGTONE_IDS.includes(input.ringtoneId)) {
if (!isValidRingtoneId(input.ringtoneId)) {
throw new TRPCError({
code: "BAD_REQUEST",
message: `Invalid ringtone ID: ${input.ringtoneId}`,
Expand Down
Loading
Loading