Add basic selection stuff
parent
b6cce36f0c
commit
8a2ed8156a
|
@ -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>
|
|
@ -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>
|
Loading…
Reference in New Issue