mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-01 16:12:02 +00:00
feat: play the involved sound for new mail by default
This commit is contained in:
@@ -3,6 +3,8 @@ import { withBasePath } from '@/lib/browser-navigation';
|
||||
|
||||
export type NotificationSoundChoice = 'default' | 'cheerful' | 'involved' | 'swift' | 'relax';
|
||||
|
||||
// 'default' is the beep. It was the default sound until Involved replaced
|
||||
// it, and keeps its id so stored and synced choices still match.
|
||||
export const NOTIFICATION_SOUNDS: { id: NotificationSoundChoice; file?: string }[] = [
|
||||
{ id: 'default' },
|
||||
{ id: 'cheerful', file: '/notification/cheerful-527.mp3' },
|
||||
@@ -53,7 +55,7 @@ function playFile(file: string) {
|
||||
|
||||
export function playNotificationSound(sound?: NotificationSoundChoice) {
|
||||
try {
|
||||
const choice = sound ?? 'default';
|
||||
const choice = sound ?? 'involved';
|
||||
const entry = NOTIFICATION_SOUNDS.find((s) => s.id === choice);
|
||||
|
||||
if (entry?.file) {
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "اختبار صوت الإشعار",
|
||||
"sounds": {
|
||||
"default": "افتراضي (تنبيه)",
|
||||
"default": "تنبيه",
|
||||
"cheerful": "مرح",
|
||||
"involved": "متفاعل",
|
||||
"swift": "إيماءة سريعة",
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Prova el so de notificació",
|
||||
"sounds": {
|
||||
"default": "Per defecte (bip)",
|
||||
"default": "Bip",
|
||||
"cheerful": "Alegre",
|
||||
"involved": "Elaborat",
|
||||
"swift": "Gest ràpid",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Otestovat zvuk oznámení",
|
||||
"sounds": {
|
||||
"default": "Výchozí (Pípnutí)",
|
||||
"default": "Pípnutí",
|
||||
"cheerful": "Veselý",
|
||||
"involved": "Dynamický",
|
||||
"swift": "Rychlý",
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Test notifikationslyd",
|
||||
"sounds": {
|
||||
"default": "Standard (Bip)",
|
||||
"default": "Bip",
|
||||
"cheerful": "Glad",
|
||||
"involved": "Engageret",
|
||||
"swift": "Hurtig gestus",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Benachrichtigungston testen",
|
||||
"sounds": {
|
||||
"default": "Standard (Piepton)",
|
||||
"default": "Piepton",
|
||||
"cheerful": "Fröhlich",
|
||||
"involved": "Aufwendig",
|
||||
"swift": "Schnelle Geste",
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Test notification sound",
|
||||
"sounds": {
|
||||
"default": "Default (Beep)",
|
||||
"default": "Beep",
|
||||
"cheerful": "Cheerful",
|
||||
"involved": "Involved",
|
||||
"swift": "Swift Gesture",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Probar sonido de notificación",
|
||||
"sounds": {
|
||||
"default": "Predeterminado (Pitido)",
|
||||
"default": "Pitido",
|
||||
"cheerful": "Alegre",
|
||||
"involved": "Elaborado",
|
||||
"swift": "Gesto rápido",
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Testi teavitusheli",
|
||||
"sounds": {
|
||||
"default": "Vaikimisi (piiks)",
|
||||
"default": "Piiks",
|
||||
"cheerful": "Rõõmus",
|
||||
"involved": "Elav",
|
||||
"swift": "Kiire liigutus",
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "تست صدای اعلان",
|
||||
"sounds": {
|
||||
"default": "پیشفرض (بیپ)",
|
||||
"default": "بیپ",
|
||||
"cheerful": "شاد",
|
||||
"involved": "درگیر",
|
||||
"swift": "سریع",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Tester le son de notification",
|
||||
"sounds": {
|
||||
"default": "Par défaut (Bip)",
|
||||
"default": "Bip",
|
||||
"cheerful": "Joyeux",
|
||||
"involved": "Élaboré",
|
||||
"swift": "Geste rapide",
|
||||
|
||||
@@ -1595,7 +1595,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "צליל הודעת בדיקה",
|
||||
"sounds": {
|
||||
"default": "ברירת מחדל (ביפ)",
|
||||
"default": "ביפ",
|
||||
"cheerful": "עליז",
|
||||
"involved": "מעורב",
|
||||
"swift": "מחווה מהירה",
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Értesítési hang tesztelése",
|
||||
"sounds": {
|
||||
"default": "Alapértelmezett (sípolás)",
|
||||
"default": "Sípolás",
|
||||
"cheerful": "Vidám",
|
||||
"involved": "Lelkes",
|
||||
"swift": "Gyors mozdulat",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Testa il suono di notifica",
|
||||
"sounds": {
|
||||
"default": "Predefinito (Bip)",
|
||||
"default": "Bip",
|
||||
"cheerful": "Allegro",
|
||||
"involved": "Elaborato",
|
||||
"swift": "Gesto veloce",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "通知音をテスト",
|
||||
"sounds": {
|
||||
"default": "デフォルト(ビープ)",
|
||||
"default": "ビープ",
|
||||
"cheerful": "チアフル",
|
||||
"involved": "インボルブド",
|
||||
"swift": "スウィフトジェスチャー",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "알림음 테스트",
|
||||
"sounds": {
|
||||
"default": "기본 (비프음)",
|
||||
"default": "비프음",
|
||||
"cheerful": "밝게",
|
||||
"involved": "경쾌하게",
|
||||
"swift": "빠르게",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Pārbaudīt paziņojuma skaņu",
|
||||
"sounds": {
|
||||
"default": "Noklusējuma (Signāls)",
|
||||
"default": "Signāls",
|
||||
"cheerful": "Priecīgs",
|
||||
"involved": "Iesaistošs",
|
||||
"swift": "Ātrs",
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Туршилтын мэдэгдлийн дуу",
|
||||
"sounds": {
|
||||
"default": "Өгөгдмөл (Дохио)",
|
||||
"default": "Дохио",
|
||||
"cheerful": "Хөгжилтэй",
|
||||
"involved": "Оролцсон",
|
||||
"swift": "Шуурхай зангаа",
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Test varslingslyden",
|
||||
"sounds": {
|
||||
"default": "Standard (pip)",
|
||||
"default": "Pip",
|
||||
"cheerful": "Munter",
|
||||
"involved": "Engasjert",
|
||||
"swift": "Rask",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Meldingsgeluid testen",
|
||||
"sounds": {
|
||||
"default": "Standaard (Pieptoon)",
|
||||
"default": "Pieptoon",
|
||||
"cheerful": "Vrolijk",
|
||||
"involved": "Uitgebreid",
|
||||
"swift": "Snel gebaar",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Przetestuj dźwięk powiadomienia",
|
||||
"sounds": {
|
||||
"default": "Domyślny (Beep)",
|
||||
"default": "Beep",
|
||||
"cheerful": "Pogodny",
|
||||
"involved": "Dynamiczny",
|
||||
"swift": "Szybki gest",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Testar som de notificação",
|
||||
"sounds": {
|
||||
"default": "Padrão (Bipe)",
|
||||
"default": "Bipe",
|
||||
"cheerful": "Alegre",
|
||||
"involved": "Elaborado",
|
||||
"swift": "Gesto rápido",
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Testați sunetul de notificare",
|
||||
"sounds": {
|
||||
"default": "Implicit (Bip)",
|
||||
"default": "Bip",
|
||||
"cheerful": "Vesel",
|
||||
"involved": "Implicat",
|
||||
"swift": "Gest rapid",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Проверить звук уведомления",
|
||||
"sounds": {
|
||||
"default": "По умолчанию (Сигнал)",
|
||||
"default": "Сигнал",
|
||||
"cheerful": "Радостный",
|
||||
"involved": "Вовлечённый",
|
||||
"swift": "Быстрый жест",
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Otestovať zvuk oznámenia",
|
||||
"sounds": {
|
||||
"default": "Predvolený (Pípnutie)",
|
||||
"default": "Pípnutie",
|
||||
"cheerful": "Veselý",
|
||||
"involved": "Dynamický",
|
||||
"swift": "Rýchly",
|
||||
|
||||
@@ -4070,7 +4070,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "ทดสอบเสียงแจ้งเตือน",
|
||||
"sounds": {
|
||||
"default": "ค่าเริ่มต้น (เสียงบี๊บ)",
|
||||
"default": "เสียงบี๊บ",
|
||||
"cheerful": "ร่าเริง (Cheerful)",
|
||||
"involved": "กระตือรือร้น (Involved)",
|
||||
"swift": "รวดเร็ว (Swift Gesture)",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Bildirim sesini test et",
|
||||
"sounds": {
|
||||
"default": "Varsayılan (Bip)",
|
||||
"default": "Bip",
|
||||
"cheerful": "Neşeli",
|
||||
"involved": "Odaklı",
|
||||
"swift": "Hızlı Jest",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "Тестовий звук сповіщення",
|
||||
"sounds": {
|
||||
"default": "За замовчуванням (звуковий сигнал)",
|
||||
"default": "Звуковий сигнал",
|
||||
"cheerful": "Веселий",
|
||||
"involved": "Залучений",
|
||||
"swift": "Швидкий жест",
|
||||
|
||||
@@ -1633,7 +1633,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "測試通知聲音",
|
||||
"sounds": {
|
||||
"default": "預設(蜂鳴聲)",
|
||||
"default": "蜂鳴聲",
|
||||
"cheerful": "快樂",
|
||||
"involved": "沉浸",
|
||||
"swift": "輕快手勢",
|
||||
|
||||
@@ -1630,7 +1630,7 @@
|
||||
"notifications": {
|
||||
"test_sound": "测试通知声音",
|
||||
"sounds": {
|
||||
"default": "默认(蜂鸣声)",
|
||||
"default": "蜂鸣声",
|
||||
"cheerful": "快乐",
|
||||
"involved": "沉浸",
|
||||
"swift": "轻快手势",
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import { beforeEach, describe, it, expect } from 'vitest';
|
||||
import { useSettingsStore, migrateSettings } from '../settings-store';
|
||||
|
||||
// The new mail sound defaults to Involved; 'default' is the beep, which was
|
||||
// the default before.
|
||||
|
||||
const migrate = (state: Record<string, unknown>, version: number) =>
|
||||
migrateSettings(state, version) as unknown as Record<string, unknown>;
|
||||
|
||||
describe('notification sound default', () => {
|
||||
beforeEach(() => {
|
||||
useSettingsStore.getState().resetToDefaults();
|
||||
});
|
||||
|
||||
it('plays Involved on a fresh install', () => {
|
||||
expect(useSettingsStore.getState().notificationSoundChoice).toBe('involved');
|
||||
});
|
||||
|
||||
it('moves a beep the user never picked to Involved', () => {
|
||||
expect(migrate({ notificationSoundChoice: 'default', explicitSettings: [] }, 9).notificationSoundChoice).toBe('involved');
|
||||
});
|
||||
|
||||
it('keeps a beep the user picked', () => {
|
||||
const out = migrate({ notificationSoundChoice: 'default', explicitSettings: ['notificationSoundChoice'] }, 9);
|
||||
expect(out.notificationSoundChoice).toBe('default');
|
||||
});
|
||||
|
||||
it('keeps any other sound the user picked', () => {
|
||||
expect(migrate({ notificationSoundChoice: 'relax', explicitSettings: [] }, 9).notificationSoundChoice).toBe('relax');
|
||||
});
|
||||
|
||||
it('does not take the beep from before explicitSettings existed as chosen', () => {
|
||||
const out = migrate({ notificationSoundChoice: 'default' }, 7);
|
||||
expect(out.notificationSoundChoice).toBe('involved');
|
||||
expect(out.explicitSettings).not.toContain('notificationSoundChoice');
|
||||
});
|
||||
|
||||
it('moves the beep along in a server copy or export from an older build', () => {
|
||||
const store = useSettingsStore.getState();
|
||||
expect(store.importSettings(JSON.stringify({ notificationSoundChoice: 'default', explicitSettings: [] }))).toBe(true);
|
||||
expect(useSettingsStore.getState().notificationSoundChoice).toBe('involved');
|
||||
|
||||
expect(store.importSettings(JSON.stringify({ notificationSoundChoice: 'default' }))).toBe(true);
|
||||
expect(useSettingsStore.getState().notificationSoundChoice).toBe('involved');
|
||||
expect(useSettingsStore.getState().explicitSettings).not.toContain('notificationSoundChoice');
|
||||
|
||||
expect(store.importSettings(JSON.stringify({ notificationSoundChoice: 'default', explicitSettings: ['notificationSoundChoice'] }))).toBe(true);
|
||||
expect(useSettingsStore.getState().notificationSoundChoice).toBe('default');
|
||||
});
|
||||
});
|
||||
@@ -942,7 +942,7 @@ const DEFAULT_SETTINGS = {
|
||||
// Email Notifications
|
||||
emailNotificationsEnabled: true,
|
||||
emailNotificationSound: true,
|
||||
notificationSoundChoice: 'default' as NotificationSoundChoice,
|
||||
notificationSoundChoice: 'involved' as NotificationSoundChoice,
|
||||
pushNotifyInboxOnly: false,
|
||||
notificationMutes: EMPTY_NOTIFICATION_MUTES,
|
||||
pushRelayUrl: '',
|
||||
@@ -1495,6 +1495,7 @@ export const useSettingsStore = create<SettingsState>()(
|
||||
settings.protocolOpenMode = settings.protocolMailtoOpenMode;
|
||||
}
|
||||
migrateAnimationsSetting(settings);
|
||||
migrateNotificationSoundDefault(settings);
|
||||
|
||||
// Apply settings, noting which keys were taken over for the
|
||||
// onSettingsImport hook.
|
||||
@@ -1896,7 +1897,7 @@ export const useSettingsStore = create<SettingsState>()(
|
||||
},
|
||||
{
|
||||
name: 'settings-storage',
|
||||
version: 9,
|
||||
version: 10,
|
||||
migrate: migrateSettings,
|
||||
onRehydrateStorage: () => {
|
||||
return (state) => {
|
||||
@@ -1994,6 +1995,9 @@ export function migrateSettings(persisted: unknown, version: number): SettingsSt
|
||||
if (version < 6 || !isPlainRecord(state.preferredIdentityIds)) {
|
||||
state.preferredIdentityIds = {};
|
||||
}
|
||||
// Before the v8 step: a beep from before explicitSettings existed was
|
||||
// the default then, and must not be taken as chosen below.
|
||||
migrateNotificationSoundDefault(state);
|
||||
// v8: admin policy defaults (#1248) skip settings the user chose.
|
||||
// Earlier builds did not record that, so a setting that differs from
|
||||
// the build default is taken as chosen.
|
||||
@@ -2020,6 +2024,18 @@ export function migrateAnimationsSetting(state: Record<string, unknown>): void {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* v10: the new mail sound defaults to Involved instead of the beep. A beep
|
||||
* the user never picked was only the old default and moves to Involved; one
|
||||
* they picked stays. Imports and server copies from older builds still
|
||||
* carry the beep and go through this too.
|
||||
*/
|
||||
export function migrateNotificationSoundDefault(state: Record<string, unknown>): void {
|
||||
if (state.notificationSoundChoice !== 'default') return;
|
||||
const chosen = Array.isArray(state.explicitSettings) && state.explicitSettings.includes('notificationSoundChoice');
|
||||
if (!chosen) state.notificationSoundChoice = 'involved';
|
||||
}
|
||||
|
||||
// Helper functions to apply settings to DOM
|
||||
|
||||
/** The settings applyAccessibilityTo() writes onto <html>. */
|
||||
|
||||
Reference in New Issue
Block a user