From 12c61dc35a8e8d8d933eda84ac99e69887813b7b Mon Sep 17 00:00:00 2001 From: rouggy Date: Sun, 30 Aug 2026 20:15:45 +0200 Subject: [PATCH] =?UTF-8?q?feat(dvk):=20delete=20a=20message=20=E2=80=94?= =?UTF-8?q?=20recording=20and=20label=20together?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A deleted message is a free slot, per its operator; keeping the label made it look half-deleted. --- app.go | 16 ++++++++++++++++ changelog.json | 6 ++++-- frontend/src/components/SettingsModal.tsx | 11 ++++++++++- frontend/src/lib/i18n.tsx | 4 ++-- frontend/wailsjs/go/main/App.d.ts | 2 ++ frontend/wailsjs/go/main/App.js | 4 ++++ 6 files changed, 38 insertions(+), 5 deletions(-) diff --git a/app.go b/app.go index 88ef31f..5a1da8f 100644 --- a/app.go +++ b/app.go @@ -10300,6 +10300,22 @@ func (a *App) GetDVKMessages() []DVKMessage { return out } +// DVKDelete removes a slot's recording AND its label — a deleted message is a +// free slot, per its operator. +func (a *App) DVKDelete(slot int) error { + if slot < 1 || slot > dvkSlots { + return fmt.Errorf("bad slot") + } + if err := os.Remove(a.dvkPath(slot)); err != nil && !os.IsNotExist(err) { + return fmt.Errorf("delete message %d: %w", slot, err) + } + if a.settings != nil { + _ = a.settings.Set(a.ctx, dvkLabelKey(slot), "") + } + applog.Printf("dvk: message F%d deleted (label cleared)", slot) + return nil +} + // SetDVKLabel renames a voice-keyer slot. func (a *App) SetDVKLabel(slot int, label string) error { if a.settings == nil { diff --git a/changelog.json b/changelog.json index bce44cf..3131104 100644 --- a/changelog.json +++ b/changelog.json @@ -6,13 +6,15 @@ "KPA500: the amplifier no longer switches itself off and commands respond instantly. A command this model does not know (the KPA1500’s ATU poll) was tearing the link down every cycle, and each reconnect toggled the serial control lines — which are the KPA500’s power switch. The lines are now held steady, silence is not treated as a dead link, and the baud is picked from a list.", "FT decodes: within a period, decodes are listed in arrival order — mirroring the decoder’s own window — instead of strongest-first.", "Voice keyer: twelve message slots (F1–F12) instead of six.", - "Preferences open smoothly on a busy station: while the dialog is open, cluster spots, FT decodes and CAT snapshots queue quietly instead of repainting the whole window behind it — everything catches up the moment it closes." + "Preferences open smoothly on a busy station: while the dialog is open, cluster spots, FT decodes and CAT snapshots queue quietly instead of repainting the whole window behind it — everything catches up the moment it closes.", + "Voice keyer: a delete button per message — removes the recording and clears the label." ], "fr": [ "KPA500 : l’ampli ne s’éteint plus tout seul et les commandes répondent instantanément. Une commande inconnue de ce modèle (le poll ATU du KPA1500) détruisait le lien à chaque cycle, et chaque reconnexion basculait les lignes de contrôle série — qui sont l’interrupteur du KPA500. Les lignes sont désormais tenues stables, le silence n’est plus traité comme un lien mort, et le baud se choisit dans une liste.", "FT decodes : dans une période, les décodages sont listés dans l’ordre d’arrivée — comme la fenêtre du décodeur — au lieu du plus fort d’abord.", "Manipulateur vocal : douze messages (F1–F12) au lieu de six.", - "Les Préférences restent fluides sur une station chargée : dialogue ouvert, les spots cluster, les décodages FT et les instantanés CAT patientent en file au lieu de repeindre toute la fenêtre derrière — tout se rattrape à la fermeture." + "Les Préférences restent fluides sur une station chargée : dialogue ouvert, les spots cluster, les décodages FT et les instantanés CAT patientent en file au lieu de repeindre toute la fenêtre derrière — tout se rattrape à la fermeture.", + "Manipulateur vocal : un bouton supprimer par message — efface l’enregistrement et le libellé." ] }, { diff --git a/frontend/src/components/SettingsModal.tsx b/frontend/src/components/SettingsModal.tsx index ec137dc..8b6d8a3 100644 --- a/frontend/src/components/SettingsModal.tsx +++ b/frontend/src/components/SettingsModal.tsx @@ -9,7 +9,7 @@ import { import { GetLookupSettings, SaveLookupSettings, ClearLookupCache, TestLookupProvider, GetListsSettings, SaveListsSettings, - GetCATSettings, SaveCATSettings, GetRadios, SaveRadios, SetActiveRadio, ActiveRadioID, DiscoverFlexRadios, + GetCATSettings, SaveCATSettings, GetRadios, SaveRadios, SetActiveRadio, ActiveRadioID, DiscoverFlexRadios, DVKDelete, GetAudioMonitorPref, ListProfiles, GetActiveProfile, SaveProfile, DeleteProfile, ActivateProfile, DuplicateProfile, GetRotators, SaveRotators, TestRotatorDevice, RotatorPark, RotatorStop, @@ -7178,6 +7178,15 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged > {dvkStat.playing ? t('aud.stop') : t('aud.play')} + ); })} diff --git a/frontend/src/lib/i18n.tsx b/frontend/src/lib/i18n.tsx index 4323f1d..f70b07c 100644 --- a/frontend/src/lib/i18n.tsx +++ b/frontend/src/lib/i18n.tsx @@ -535,7 +535,7 @@ const en: Dict = { 'aud.preroll': 'Pre-roll (seconds)', 'aud.format': 'File format', 'aud.wav': 'WAV (lossless, larger)', 'aud.mp3': 'MP3 (compressed, small)', 'aud.fromLevel': 'From Radio level', 'aud.txLevel': 'Voice keyer level', 'aud.txLevelHint': 'Level of the recorded messages sent to the radio. Raise it if your voice keyer is much quieter than your microphone; Play previews at this same level. If the radio transmits almost nothing, its modulation source is still the front microphone: on an FTDX10 set MENU → SSB MOD SOURCE to REAR (the USB input).', 'aud.micLevel': 'Mic level', 'aud.qsoPlayLevel': 'QSO playback level', 'aud.levelHint': 'If your voice is louder than the station, lower Mic level.', 'aud.autoSend': 'Auto-send the recording to the station by e-mail when I log a QSO', - 'aud.dvkTitle': 'Voice keyer messages (F1–F12)', 'aud.pttMethod': 'PTT method', 'aud.pttNone': 'None (VOX)', 'aud.pttCat': 'CAT (the radio link)', 'aud.pttRts': 'Serial RTS', 'aud.pttDtr': 'Serial DTR', + 'aud.dvkTitle': 'Voice keyer messages (F1–F12)', 'aud.deleteMsg': 'Delete this message', 'aud.pttMethod': 'PTT method', 'aud.pttNone': 'None (VOX)', 'aud.pttCat': 'CAT (the radio link)', 'aud.pttRts': 'Serial RTS', 'aud.pttDtr': 'Serial DTR', 'aud.testPtt': 'Test PTT', 'aud.pttPort': 'PTT COM port', 'aud.pickPort': 'Pick a COM port', 'aud.selectPort': '— select —', 'aud.refresh': 'Refresh', 'aud.msgPlaceholder': 'Message {n} label (CQ, report, 73…)', 'aud.holdRec': '● Hold to rec', 'aud.recordingNow': '● Recording…', 'aud.play': '▶ Play', 'aud.stop': '■ Stop', 'aud.errPttTest': 'PTT test: ', 'aud.errRecord': 'Record: ', 'aud.errSave': 'Save: ', 'aud.errPlay': 'Play: ', @@ -1037,7 +1037,7 @@ const fr: Dict = { 'aud.preroll': 'Pré-enregistrement (secondes)', 'aud.format': 'Format de fichier', 'aud.wav': 'WAV (sans perte, plus volumineux)', 'aud.mp3': 'MP3 (compressé, léger)', 'aud.fromLevel': 'Niveau depuis la radio', 'aud.txLevel': 'Niveau du voice keyer', 'aud.txLevelHint': "Niveau des messages enregistrés envoyés à la radio. Augmentez-le si votre voice keyer est bien plus faible que votre micro ; Lire fait entendre ce même niveau. Si la radio n'émet presque rien, c'est que sa source de modulation est restée le micro de façade : sur un FTDX10, réglez MENU → SSB MOD SOURCE sur REAR (l'entrée USB).", 'aud.micLevel': 'Niveau micro', 'aud.qsoPlayLevel': 'Niveau de relecture QSO', 'aud.levelHint': 'Si votre voix est plus forte que la station, baissez le niveau micro.', 'aud.autoSend': "Envoyer automatiquement l'enregistrement à la station par e-mail lorsque j'enregistre un QSO", - 'aud.dvkTitle': 'Messages du manipulateur vocal (F1–F12)', 'aud.pttMethod': 'Méthode PTT', 'aud.pttNone': 'Aucune (VOX)', 'aud.pttCat': 'CAT (la liaison radio)', 'aud.pttRts': 'RTS série', 'aud.pttDtr': 'DTR série', + 'aud.dvkTitle': 'Messages du manipulateur vocal (F1–F12)', 'aud.deleteMsg': 'Supprimer ce message', 'aud.pttMethod': 'Méthode PTT', 'aud.pttNone': 'Aucune (VOX)', 'aud.pttCat': 'CAT (la liaison radio)', 'aud.pttRts': 'RTS série', 'aud.pttDtr': 'DTR série', 'aud.testPtt': 'Tester le PTT', 'aud.pttPort': 'Port COM du PTT', 'aud.pickPort': 'Choisir un port COM', 'aud.selectPort': '— choisir —', 'aud.refresh': 'Actualiser', 'aud.msgPlaceholder': 'Libellé du message {n} (CQ, report, 73…)', 'aud.holdRec': '● Maintenir pour enreg.', 'aud.recordingNow': '● Enregistrement…', 'aud.play': '▶ Lire', 'aud.stop': '■ Arrêter', 'aud.errPttTest': 'Test PTT : ', 'aud.errRecord': 'Enregistrement : ', 'aud.errSave': 'Sauvegarde : ', 'aud.errPlay': 'Lecture : ', diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 5b84e5b..4594b6f 100644 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -160,6 +160,8 @@ export function CreateDatabase(arg1:string):Promise; export function DVKCancelRecord():Promise; +export function DVKDelete(arg1:number):Promise; + export function DVKPlay(arg1:number):Promise; export function DVKPreview(arg1:number):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index 0cfdb5c..edab00d 100644 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -258,6 +258,10 @@ export function DVKCancelRecord() { return window['go']['main']['App']['DVKCancelRecord'](); } +export function DVKDelete(arg1) { + return window['go']['main']['App']['DVKDelete'](arg1); +} + export function DVKPlay(arg1) { return window['go']['main']['App']['DVKPlay'](arg1); }