diff --git a/frontend/src/component/photo/cards.vue b/frontend/src/component/photo/cards.vue index 9c3c612b3..dfae318c9 100644 --- a/frontend/src/component/photo/cards.vue +++ b/frontend/src/component/photo/cards.vue @@ -21,34 +21,29 @@ - -
-
+
+
-
+

{{ photo.Title | truncate(80) }}

-
+
{{ photo.Description }}
-
- +
+ {{ photo.getDateString(true) }}
- + @@ -57,130 +52,125 @@
- +
- - - photo_camera - $vuetify.icons.live_photo - gif - play_arrow - burst_mode - + - - zoom_in - + - - play_arrow - + - - lock - + + - - favorite - favorite_border - - + +
+ small depressed dark block :round="false" + class="action-archive text-xs-center" + :title="$gettext('Archive')" @click.stop="photo.archive()"> clear + small depressed dark block :round="false" + class="action-approve text-xs-center" + :title="$gettext('Approve')" @click.stop="photo.approve()"> check - +


@@ -227,15 +217,15 @@

-
-
- +
+
+
@@ -244,9 +234,13 @@ import download from "common/download"; import Notify from "common/notify"; import {Input, InputInvalid, ClickShort, ClickLong} from "common/input"; import {virtualizationTools} from 'common/virtualization-tools'; +import IconLivePhoto from "component/icon/live_photo.vue"; export default { name: 'PPhotoCards', + components: { + IconLivePhoto, + }, props: { photos: { type: Array, @@ -321,8 +315,16 @@ export default { if (this.$refs.items === undefined) { return; } - for (const item of this.$refs.items) { - this.intersectionObserver.observe(item); + + /** + * observing only every 5th item reduces the amount of time + * spent computing intersection by 80%. me might render up to + * 8 items more than required, but the time saved computing + * intersections is far greater than the time lost rendering + * a couple more items + */ + for (let i = 0; i < this.$refs.items.length; i += 5) { + this.intersectionObserver.observe(this.$refs.items[i]); } }, elementIndexFromIntersectionObserverEntry(entry) { @@ -335,8 +337,10 @@ export default { this.elementIndexFromIntersectionObserverEntry, ); - this.firstVisibleElementIndex = smallestIndex; - this.lastVisibileElementIndex = largestIndex; + // we observe only every 5th item, so we increase the rendered + // range here by 4 items in every directio just to be safe + this.firstVisibleElementIndex = smallestIndex - 4; + this.lastVisibileElementIndex = largestIndex + 4; }, livePlayer(photo) { return document.querySelector("#live-player-" + photo.ID); @@ -388,9 +392,19 @@ export default { if (ev.shiftKey) { this.selectRange(index); } else { - this.$clipboard.toggle(this.photos[index]); + this.toggle(this.photos[index]); } }, + toggle(photo) { + this.$clipboard.toggle(photo); + /** + * updating the clipboard does not rerender this component. Because of that + * there can be scenarios where the select-icon is missing after a change, + * for example when using touch and no hover-state changes.We therefore + * force an update to fix that. + */ + this.$forceUpdate(); + }, onOpen(ev, index, showMerged) { const inputType = this.input.eval(ev, index); @@ -412,7 +426,7 @@ export default { if (longClick || ev.shiftKey) { this.selectRange(index); } else { - this.$clipboard.toggle(this.photos[index]); + this.toggle(this.photos[index]); } } else { this.openPhoto(index, false); @@ -427,6 +441,13 @@ export default { }, selectRange(index) { this.$clipboard.addRange(index, this.photos); + /** + * updating the clipboard does not rerender this component. Because of that + * there can be scenarios where the select-icon is missing after a change, + * for example when selecting mutliple elements at once. We therefore + * force an update to fix that. + */ + this.$forceUpdate(); }, } }; diff --git a/frontend/src/component/photo/list.vue b/frontend/src/component/photo/list.vue index 3a7833d02..e201ff188 100644 --- a/frontend/src/component/photo/list.vue +++ b/frontend/src/component/photo/list.vue @@ -20,118 +20,127 @@

- +
+ + + + + + + + + + + + - > - - + + + + +
+ + {{$gettext('Title')}} + + {{$gettext('Taken')}} + + {{$gettext('Camera')}} + + {{showName ? $gettext('Name') : $gettext('Location')}} + +
+
+
+ + +
+
+
+