Merge branch 'fix/group-drag-actually-moves'

This commit is contained in:
ScreenTinker 2026-07-29 21:33:56 -05:00
commit 54f1f62762
7 changed files with 30 additions and 3 deletions

View file

@ -126,6 +126,8 @@ export default {
'dashboard.prompt_group_name': 'Gruppenname:',
'dashboard.error_pairing_code': 'Geben Sie einen gültigen 6-stelligen Kopplungscode ein',
'dashboard.confirm_add_to_group': '{name} ist bereits in: {groups}\n\nAuch zu „{target}“ hinzufügen?',
'dashboard.confirm_move_to_group': '{name} ist derzeit in: {groups}\n\nNach "{target}" verschieben?',
'dashboard.toast.move_partial': 'Entfernen aus {group} fehlgeschlagen — Bildschirm ist noch in beiden',
'dashboard.confirm_assign_playlist': 'Playlist „{playlist}“ allen Geräten in „{group}“ zuweisen?',
'dashboard.confirm_destructive_command': '{cmd} alle {n} Geräte in „{group}“?\n\nDies kann nicht rückgängig gemacht werden.',
'dashboard.confirm_delete_group': 'Diese Gruppe löschen? Geräte sind nicht betroffen.',

View file

@ -223,6 +223,8 @@ export default {
'dashboard.prompt_group_name': 'Group name:',
'dashboard.error_pairing_code': 'Enter a valid 6-digit pairing code',
'dashboard.confirm_add_to_group': '{name} is already in: {groups}\n\nAdd it to "{target}" too?',
'dashboard.confirm_move_to_group': '{name} is currently in: {groups}\n\nMove it to "{target}"?',
'dashboard.toast.move_partial': 'Could not remove it from {group} — it is still in both',
'dashboard.confirm_assign_playlist': 'Assign playlist "{playlist}" to all devices in "{group}"?',
'dashboard.confirm_destructive_command': '{cmd} all {n} devices in "{group}"?\n\nThis cannot be undone.',
'dashboard.confirm_delete_group': 'Delete this group? Devices will not be affected.',

View file

@ -126,6 +126,8 @@ export default {
'dashboard.prompt_group_name': 'Nombre del grupo:',
'dashboard.error_pairing_code': 'Ingresa un código de vinculación válido de 6 dígitos',
'dashboard.confirm_add_to_group': '{name} ya está en: {groups}\n\n¿Agregarlo también a "{target}"?',
'dashboard.confirm_move_to_group': '{name} está actualmente en: {groups}\n\n¿Moverla a "{target}"?',
'dashboard.toast.move_partial': 'No se pudo quitar de {group}: sigue en ambos',
'dashboard.confirm_assign_playlist': '¿Asignar la lista "{playlist}" a todos los dispositivos de "{group}"?',
'dashboard.confirm_destructive_command': '¿{cmd} todos los {n} dispositivos de "{group}"?\n\nEsto no se puede deshacer.',
'dashboard.confirm_delete_group': '¿Eliminar este grupo? Los dispositivos no se verán afectados.',

View file

@ -126,6 +126,8 @@ export default {
'dashboard.prompt_group_name': 'Nom du groupe :',
'dashboard.error_pairing_code': 'Saisissez un code d\'appairage valide à 6 chiffres',
'dashboard.confirm_add_to_group': '{name} est déjà dans : {groups}\n\nL\'ajouter aussi à « {target} » ?',
'dashboard.confirm_move_to_group': '{name} est actuellement dans : {groups}\n\nLe déplacer vers "{target}" ?',
'dashboard.toast.move_partial': 'Impossible de le retirer de {group} — il est encore dans les deux',
'dashboard.confirm_assign_playlist': 'Attribuer la liste « {playlist} » à tous les appareils de « {group} » ?',
'dashboard.confirm_destructive_command': '{cmd} les {n} appareils de « {group} » ?\n\nCette action est irréversible.',
'dashboard.confirm_delete_group': 'Supprimer ce groupe ? Les appareils ne seront pas affectés.',

View file

@ -127,6 +127,8 @@ export default {
'dashboard.prompt_group_name': 'Nome gruppo:',
'dashboard.error_pairing_code': 'Inserisci un codice di associazione valido di 6 cifre',
'dashboard.confirm_add_to_group': '{name} è già presente in: {groups}\n\nAggiungerlo anche a "{target}"?',
'dashboard.confirm_move_to_group': '{name} è attualmente in: {groups}\n\nSpostarlo in "{target}"?',
'dashboard.toast.move_partial': 'Impossibile rimuoverlo da {group}: è ancora in entrambi',
'dashboard.confirm_assign_playlist': 'Assegnare la playlist "{playlist}" a tutti i dispositivi in "{group}"?',
'dashboard.confirm_destructive_command': 'Eseguire {cmd} su tutti i {n} dispositivi in "{group}"?\n\nL\'azione è irreversibile.',
'dashboard.confirm_delete_group': 'Eliminare questo gruppo? I dispositivi non verranno rimossi dal sistema.',

View file

@ -126,6 +126,8 @@ export default {
'dashboard.prompt_group_name': 'Nome do grupo:',
'dashboard.error_pairing_code': 'Digite um código de pareamento válido de 6 dígitos',
'dashboard.confirm_add_to_group': '{name} já está em: {groups}\n\nAdicionar também a "{target}"?',
'dashboard.confirm_move_to_group': '{name} está atualmente em: {groups}\n\nMover para "{target}"?',
'dashboard.toast.move_partial': 'Não foi possível remover de {group} — continua em ambos',
'dashboard.confirm_assign_playlist': 'Atribuir a playlist "{playlist}" a todos os dispositivos de "{group}"?',
'dashboard.confirm_destructive_command': '{cmd} todos os {n} dispositivos de "{group}"?\n\nIsso não pode ser desfeito.',
'dashboard.confirm_delete_group': 'Excluir este grupo? Os dispositivos não serão afetados.',

View file

@ -767,13 +767,28 @@ function attachGroupHandlers(groupsWithDevices, allDevices) {
showToast(t('dashboard.toast.already_in_group', { name: deviceName, group: targetGroup.name }), 'info');
return;
}
// If the device is in another group, mirror the Manage modal's confirm.
const others = (groupsByDeviceId.get(deviceId) || []).map(g => g.name);
// Dragging a screen onto a group MOVES it. This used to borrow the Manage modal's
// "add it too?" confirm and then only add — so the screen ended up in both groups while the
// toast claimed it had moved, the page still showed the old group, and a second attempt said
// "already in group 2". Reported by a customer doing exactly that with two screens.
// The Manage modal keeps add/remove checkboxes: multi-group membership is deliberate THERE.
// It is not deliberate here, and it is not harmless — deviceSyncGroup() picks arbitrarily
// when a device is in several sync-enabled groups, so a half-move leaves sync ambiguous.
const others = groupsByDeviceId.get(deviceId) || [];
if (others.length > 0) {
if (!confirm(t('dashboard.confirm_add_to_group', { name: deviceName, groups: others.join(', '), target: targetGroup.name }))) return;
if (!confirm(t('dashboard.confirm_move_to_group', {
name: deviceName, groups: others.map(g => g.name).join(', '), target: targetGroup.name,
}))) return;
}
try {
// Add first, then drop the old memberships: if the add fails the screen keeps the group it
// had rather than being left ungrouped by a half-finished move.
await api.addDeviceToGroup(groupId, deviceId);
for (const g of others) {
if (g.id === groupId) continue;
try { await api.removeDeviceFromGroup(g.id, deviceId); }
catch (e) { showToast(t('dashboard.toast.move_partial', { group: g.name }), 'warning'); }
}
showToast(t('dashboard.toast.moved_device', { name: deviceName, group: targetGroup.name }), 'success');
loadDashboard();
} catch (err) { showToast(err.message, 'error'); }