Add basic selection stuff

pull/37/head
Varun Patil 2022-09-07 15:14:12 -07:00
parent b6cce36f0c
commit 8a2ed8156a
2 changed files with 83 additions and 22 deletions

View File

@ -1,13 +1,15 @@
<template> <template>
<div> <div class="photo-container" :class="{ 'selected': data.selected }">
<div class="icon-checkmark select" @click="toggleSelect"></div>
<div v-if="data.isvideo" class="icon-video-white"></div> <div v-if="data.isvideo" class="icon-video-white"></div>
<img <img
@click="openFile()" @click="click"
:src="data.ph ? undefined : getPreviewUrl(data.fileid, data.etag)" :src="data.ph ? undefined : getPreviewUrl(data.fileid, data.etag)"
:key="data.fileid" :key="data.fileid"
@load = "data.l = Math.random()" @load = "data.l = Math.random()"
@error="(e) => e.target.src='/apps/memories/img/error.svg'" @error="(e) => e.target.src='/apps/memories/img/error.svg'"
v-bind:style="{ :style="{
width: rowHeight + 'px', width: rowHeight + 'px',
height: rowHeight + 'px', height: rowHeight + 'px',
}"/> }"/>
@ -38,6 +40,11 @@ export default {
/** Passthrough */ /** Passthrough */
getPreviewUrl: getPreviewUrl, getPreviewUrl: getPreviewUrl,
/** Pass to parent */
click() {
this.$emit('clickImg', this);
},
/** Open viewer */ /** Open viewer */
async openFile() { async openFile() {
// Check if this is a placeholder // Check if this is a placeholder
@ -129,11 +136,37 @@ export default {
this.day.count = this.day.detail.length; this.day.count = this.day.detail.length;
this.$emit('reprocess', this.day); this.$emit('reprocess', this.day);
}, },
toggleSelect() {
this.$emit('select', this.data);
this.$forceUpdate();
},
} }
} }
</script> </script>
<style scoped> <style scoped>
.photo-container:hover .icon-checkmark {
opacity: 0.6;
}
.photo-container.selected .icon-checkmark {
opacity: 0.9;
filter: invert();
}
.photo-container.selected img {
padding: 8%;
}
.icon-checkmark {
opacity: 0;
position: absolute;
top: 8px; left: 8px;
background-color: var(--color-main-background);
border-radius: 50%;
background-size: 80%;
padding: 5px;
cursor: pointer;
}
.icon-video-white { .icon-video-white {
position: absolute; position: absolute;
top: 8px; right: 8px; top: 8px; right: 8px;
@ -145,5 +178,6 @@ img {
object-fit: cover; object-fit: cover;
border-radius: 3%; border-radius: 3%;
cursor: pointer; cursor: pointer;
transition: padding 0.1s ease-in-out;
} }
</style> </style>

View File

@ -1,5 +1,6 @@
<template> <template>
<div class="container" ref="container" :class="{ 'icon-loading': loading }"> <div class="container" ref="container" :class="{ 'icon-loading': loading }">
<!-- Main recycler view for rows -->
<RecycleScroller <RecycleScroller
ref="scroller" ref="scroller"
class="scroller" class="scroller"
@ -24,11 +25,14 @@
:data="photo" :rowHeight="rowHeight" /> :data="photo" :rowHeight="rowHeight" />
<Photo v-else <Photo v-else
:data="photo" :rowHeight="rowHeight" :day="item.day" :data="photo" :rowHeight="rowHeight" :day="item.day"
@reprocess="processDay" /> @select="selectPhoto"
@reprocess="processDay"
@clickImg="clickPhoto" />
</div> </div>
</div> </div>
</RecycleScroller> </RecycleScroller>
<!-- Timeline -->
<div ref="timelineScroll" class="timeline-scroll" <div ref="timelineScroll" class="timeline-scroll"
v-bind:class="{ scrolling }" v-bind:class="{ scrolling }"
@mousemove="timelineHover" @mousemove="timelineHover"
@ -52,6 +56,11 @@
</template> </template>
</div> </div>
</div> </div>
<!-- Top bar for selections etc -->
<div v-if="selection.size > 0" class="top-bar">
{{ selection.size }} items selected
</div>
</div> </div>
</template> </template>
@ -113,6 +122,9 @@ export default {
/** Is mobile layout */ /** Is mobile layout */
isMobile: false, isMobile: false,
/** List of selected file ids */
selection: new Set(),
/** State for request cancellations */ /** State for request cancellations */
state: Math.random(), state: Math.random(),
} }
@ -621,11 +633,32 @@ export default {
} }
this.$refs.scroller.scrollToPosition(1000); this.$refs.scroller.scrollToPosition(1000);
}, },
/** Clicking on photo */
clickPhoto(photoComponent) {
if (this.selection.size > 0) { // selection mode
photoComponent.toggleSelect();
} else {
photoComponent.openFile();
}
},
/** Add a photo to selection list */
selectPhoto(photo) {
photo.selected = !this.selection.has(photo.fileid) || undefined;
if (photo.selected) {
this.selection.add(photo.fileid);
} else {
this.selection.delete(photo.fileid);
}
this.$forceUpdate();
},
}, },
} }
</script> </script>
<style scoped> <style scoped>
/** Main view */
.container { .container {
height: 100%; height: 100%;
width: 100%; width: 100%;
@ -644,24 +677,6 @@ export default {
cursor: pointer; cursor: pointer;
} }
.photo-row .photo::before {
content: "";
position: absolute;
display: block;
height: calc(100% - 4px);
width: calc(100% - 4px);
top: 2px; left: 2px;
background: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.3) 95%);
opacity: 0;
border-radius: 3px;
transition: opacity .1s ease-in-out;
pointer-events: none;
user-select: none;
}
.photo-row .photo:hover::before {
opacity: 1;
}
.head-row { .head-row {
height: 40px; height: 40px;
padding-top: 10px; padding-top: 10px;
@ -670,6 +685,7 @@ export default {
font-weight: 600; font-weight: 600;
} }
/** Timeline */
.timeline-scroll { .timeline-scroll {
overflow-y: clip; overflow-y: clip;
position: absolute; position: absolute;
@ -743,4 +759,15 @@ export default {
padding-left: 34px; padding-left: 34px;
} }
} }
/** Top bar */
.top-bar {
position: absolute;
top: 10px; right: 20px;
padding: 15px;
min-width: 30vw;
background-color: var(--color-main-background);
box-shadow: 0 0 2px gray;
border-radius: 10px;
}
</style> </style>