Skip to content

Commit 6973fea

Browse files
committed
Frontend: Keep chip-toolbar Save/Undo visible and fix re-add photoprism#4966
1 parent f6a5dc8 commit 6973fea

3 files changed

Lines changed: 46 additions & 12 deletions

File tree

frontend/src/component/sidebar/info.vue

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@
290290
<v-list-item class="metadata__item meta-labels">
291291
<div class="text-subtitle-2">{{ $gettext("Labels") }}</div>
292292
<template v-if="isEditable && chipState.labels.removals.length > 0" #append>
293-
<p-sidebar-inline-toolbar :editing="true" :can-undo="true" @confirm="confirmLabels" @undo="undoChipRemovals('labels')" />
293+
<p-sidebar-inline-toolbar :editing="true" :can-undo="true" chip-mode @confirm="confirmLabels" @undo="undoChipRemovals('labels')" />
294294
</template>
295295
</v-list-item>
296296
<v-list-item v-if="visibleLabels.length > 0" class="metadata__item metadata__chips meta-labels">
@@ -350,7 +350,7 @@
350350
<v-list-item class="metadata__item meta-albums">
351351
<div class="text-subtitle-2">{{ $gettext("Albums") }}</div>
352352
<template v-if="isEditable && chipState.albums.removals.length > 0" #append>
353-
<p-sidebar-inline-toolbar :editing="true" :can-undo="true" @confirm="confirmAlbums" @undo="undoChipRemovals('albums')" />
353+
<p-sidebar-inline-toolbar :editing="true" :can-undo="true" chip-mode @confirm="confirmAlbums" @undo="undoChipRemovals('albums')" />
354354
</template>
355355
</v-list-item>
356356
<v-list-item v-if="visibleAlbums.length > 0" class="metadata__item metadata__chips meta-albums">
@@ -1729,8 +1729,22 @@ export default {
17291729
}
17301730
const norm = this.$util.normalizeTitle(name);
17311731
if (!norm) return false;
1732-
// Already on the photo? Skip the API call.
1733-
if (this.labels.some((l) => this.$util.normalizeTitle(l?.Label?.Name) === norm)) return false;
1732+
// If the typed label matches a chip currently pending removal,
1733+
// restore it instead of calling the API. Without this branch the
1734+
// `visibleLabels.some` check below would still let the call through
1735+
// (the chip is filtered out of visibleLabels) but the resulting
1736+
// POST would race the deferred DELETE on auto-commit and leave the
1737+
// photo in an unpredictable state — and intuitively "type the name
1738+
// you just × clicked" should mean "put it back", not "round-trip".
1739+
const pending = this.labels.find(
1740+
(l) => this.isChipPendingRemoval("labels", l?.Label?.ID) && this.$util.normalizeTitle(l?.Label?.Name) === norm
1741+
);
1742+
if (pending?.Label?.ID != null) {
1743+
this.togglePendingChipRemoval("labels", pending.Label.ID);
1744+
return true;
1745+
}
1746+
// Already on the photo (and not pending removal)? Skip the API call.
1747+
if (this.visibleLabels.some((l) => this.$util.normalizeTitle(l?.Label?.Name) === norm)) return false;
17341748
// Match against the system-wide label list — if a normalized match
17351749
// exists, send the canonical existing-label name so the backend
17361750
// doesn't create a near-duplicate (e.g. typed `Hello Cat` reuses an
@@ -1760,6 +1774,13 @@ export default {
17601774
this.$notify.error(this.$gettext("Name too long"));
17611775
return false;
17621776
}
1777+
// If the album is pending removal, restore it instead of calling
1778+
// the API. Mirrors the Labels pending-restore path; see
1779+
// addLabelImmediate for the rationale.
1780+
if (this.isChipPendingRemoval("albums", album.UID)) {
1781+
this.togglePendingChipRemoval("albums", album.UID);
1782+
return true;
1783+
}
17631784
if (this.albums.some((a) => a.UID === album.UID)) return false;
17641785
const norm = this.$util.normalizeTitle(title);
17651786
if (this.albumTitleConflicts(norm)) return false;

frontend/src/component/sidebar/inline-toolbar.vue

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<template>
2-
<div class="p-sidebar-inline-toolbar d-flex">
2+
<div :class="['p-sidebar-inline-toolbar', 'd-flex', { 'p-sidebar-inline-toolbar--chip': chipMode }]">
33
<v-btn
44
v-if="editing && canUndo"
55
:disabled="undoDisabled"
66
icon="mdi-undo-variant"
77
density="compact"
88
variant="plain"
99
size="x-small"
10-
class="meta-inline-undo"
10+
:class="['meta-inline-undo', { 'meta-chip-undo': chipMode }]"
1111
:title="$gettext('Undo')"
1212
@mousedown.prevent
1313
@click.stop="$emit('undo')"
@@ -18,7 +18,7 @@
1818
density="compact"
1919
variant="plain"
2020
size="x-small"
21-
class="meta-inline-confirm"
21+
:class="['meta-inline-confirm', { 'meta-chip-confirm': chipMode }]"
2222
:title="$gettext('Save')"
2323
@mousedown.prevent
2424
@click.stop="$emit('confirm')"
@@ -58,6 +58,15 @@ export default {
5858
type: Boolean,
5959
default: false,
6060
},
61+
// Marks the toolbar as a chip-section toolbar (Labels / Albums staged
62+
// removals). Adds the `--chip` modifier class so the Save / Undo
63+
// buttons stay visible even when the sidebar root has `hide-edit-save`
64+
// / `hide-edit-undo`: chip sections have no keyboard alternative for
65+
// committing or undoing pending removals.
66+
chipMode: {
67+
type: Boolean,
68+
default: false,
69+
},
6170
},
6271
emits: ["confirm", "start", "undo"],
6372
};

frontend/src/css/lightbox.css

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -523,14 +523,18 @@
523523
+ Notes, Escape cancels, and Ctrl+Z reverts inside the focused
524524
textarea. Per-user preference or A/B variants flip `hideEditUndo` /
525525
`hideEditSave` on the sidebar root to surface the mouse-driven
526-
affordances. The chip-section toolbars share these class names, so
527-
the same toggles also hide their batched-removal Save / Undo
528-
buttons. */
529-
.p-lightbox__container > .p-lightbox__sidebar > .p-sidebar-info.hide-edit-undo .meta-inline-undo {
526+
affordances. Chip-section toolbars (Labels / Albums) carry the
527+
`meta-chip-undo` / `meta-chip-confirm` opt-out class on each button —
528+
they have no keyboard alternative for committing or undoing pending
529+
removals so their Save/Undo affordances always stay visible. The
530+
`:not()` exception sits on the hide rule itself rather than as a
531+
separate override to keep the CSS minifier from collapsing them into
532+
an `:is()` group that breaks the child combinator. */
533+
.p-lightbox__container > .p-lightbox__sidebar > .p-sidebar-info.hide-edit-undo .meta-inline-undo:not(.meta-chip-undo) {
530534
display: none;
531535
}
532536

533-
.p-lightbox__container > .p-lightbox__sidebar > .p-sidebar-info.hide-edit-save .meta-inline-confirm {
537+
.p-lightbox__container > .p-lightbox__sidebar > .p-sidebar-info.hide-edit-save .meta-inline-confirm:not(.meta-chip-confirm) {
534538
display: none;
535539
}
536540

0 commit comments

Comments
 (0)