feat(dvk): delete a message — recording and label together

A deleted message is a free slot, per its operator; keeping the label made it
look half-deleted.
This commit is contained in:
2026-08-30 20:15:45 +02:00
parent 0c0e8b06ba
commit 12c61dc35a
6 changed files with 38 additions and 5 deletions
+16
View File
@@ -10300,6 +10300,22 @@ func (a *App) GetDVKMessages() []DVKMessage {
return out 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. // SetDVKLabel renames a voice-keyer slot.
func (a *App) SetDVKLabel(slot int, label string) error { func (a *App) SetDVKLabel(slot int, label string) error {
if a.settings == nil { if a.settings == nil {
+4 -2
View File
@@ -6,13 +6,15 @@
"KPA500: the amplifier no longer switches itself off and commands respond instantly. A command this model does not know (the KPA1500s ATU poll) was tearing the link down every cycle, and each reconnect toggled the serial control lines — which are the KPA500s power switch. The lines are now held steady, silence is not treated as a dead link, and the baud is picked from a list.", "KPA500: the amplifier no longer switches itself off and commands respond instantly. A command this model does not know (the KPA1500s ATU poll) was tearing the link down every cycle, and each reconnect toggled the serial control lines — which are the KPA500s 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 decoders own window — instead of strongest-first.", "FT decodes: within a period, decodes are listed in arrival order — mirroring the decoders own window — instead of strongest-first.",
"Voice keyer: twelve message slots (F1F12) instead of six.", "Voice keyer: twelve message slots (F1F12) 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": [ "fr": [
"KPA500 : lampli 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 linterrupteur du KPA500. Les lignes sont désormais tenues stables, le silence nest plus traité comme un lien mort, et le baud se choisit dans une liste.", "KPA500 : lampli 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 linterrupteur du KPA500. Les lignes sont désormais tenues stables, le silence nest 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 lordre darrivée — comme la fenêtre du décodeur — au lieu du plus fort dabord.", "FT decodes : dans une période, les décodages sont listés dans lordre darrivée — comme la fenêtre du décodeur — au lieu du plus fort dabord.",
"Manipulateur vocal : douze messages (F1F12) au lieu de six.", "Manipulateur vocal : douze messages (F1F12) 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 lenregistrement et le libellé."
] ]
}, },
{ {
+10 -1
View File
@@ -9,7 +9,7 @@ import {
import { import {
GetLookupSettings, SaveLookupSettings, ClearLookupCache, TestLookupProvider, GetLookupSettings, SaveLookupSettings, ClearLookupCache, TestLookupProvider,
GetListsSettings, SaveListsSettings, GetListsSettings, SaveListsSettings,
GetCATSettings, SaveCATSettings, GetRadios, SaveRadios, SetActiveRadio, ActiveRadioID, DiscoverFlexRadios, GetCATSettings, SaveCATSettings, GetRadios, SaveRadios, SetActiveRadio, ActiveRadioID, DiscoverFlexRadios, DVKDelete,
GetAudioMonitorPref, GetAudioMonitorPref,
ListProfiles, GetActiveProfile, SaveProfile, DeleteProfile, ActivateProfile, DuplicateProfile, ListProfiles, GetActiveProfile, SaveProfile, DeleteProfile, ActivateProfile, DuplicateProfile,
GetRotators, SaveRotators, TestRotatorDevice, RotatorPark, RotatorStop, GetRotators, SaveRotators, TestRotatorDevice, RotatorPark, RotatorStop,
@@ -7178,6 +7178,15 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
> >
{dvkStat.playing ? t('aud.stop') : t('aud.play')} {dvkStat.playing ? t('aud.stop') : t('aud.play')}
</Button> </Button>
<Button
type="button"
variant="outline" size="sm" className="h-8 w-9 shrink-0 px-0 text-danger hover:text-danger"
title={t('aud.deleteMsg')}
disabled={!m.has_audio || dvkStat.recording || dvkStat.playing}
onClick={() => DVKDelete(m.slot).then(reloadDvk).catch((err) => setDvkErr(String(err?.message ?? err)))}
>
<Trash2 className="size-3.5" />
</Button>
</div> </div>
); );
})} })}
+2 -2
View File
@@ -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.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.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.autoSend': 'Auto-send the recording to the station by e-mail when I log a QSO',
'aud.dvkTitle': 'Voice keyer messages (F1F12)', '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 (F1F12)', '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.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.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: ', '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.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.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.autoSend': "Envoyer automatiquement l'enregistrement à la station par e-mail lorsque j'enregistre un QSO",
'aud.dvkTitle': 'Messages du manipulateur vocal (F1F12)', '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 (F1F12)', '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.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.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 : ', 'aud.errPttTest': 'Test PTT : ', 'aud.errRecord': 'Enregistrement : ', 'aud.errSave': 'Sauvegarde : ', 'aud.errPlay': 'Lecture : ',
+2
View File
@@ -160,6 +160,8 @@ export function CreateDatabase(arg1:string):Promise<void>;
export function DVKCancelRecord():Promise<void>; export function DVKCancelRecord():Promise<void>;
export function DVKDelete(arg1:number):Promise<void>;
export function DVKPlay(arg1:number):Promise<void>; export function DVKPlay(arg1:number):Promise<void>;
export function DVKPreview(arg1:number):Promise<void>; export function DVKPreview(arg1:number):Promise<void>;
+4
View File
@@ -258,6 +258,10 @@ export function DVKCancelRecord() {
return window['go']['main']['App']['DVKCancelRecord'](); return window['go']['main']['App']['DVKCancelRecord']();
} }
export function DVKDelete(arg1) {
return window['go']['main']['App']['DVKDelete'](arg1);
}
export function DVKPlay(arg1) { export function DVKPlay(arg1) {
return window['go']['main']['App']['DVKPlay'](arg1); return window['go']['main']['App']['DVKPlay'](arg1);
} }