Frontend: Refactor long click event
Signed-off-by: Michael Mayer <michael@liquidbytes.net>
This commit is contained in:
parent
01c7fd3fd3
commit
015a67d2e6
7 changed files with 118 additions and 189 deletions
|
@ -21,7 +21,6 @@ import VueLuxon from "vue-luxon";
|
|||
import VueFilters from "vue2-filters";
|
||||
import VueFullscreen from "vue-fullscreen";
|
||||
import VueInfiniteScroll from "vue-infinite-scroll";
|
||||
import VueLongClick from "common/longclick";
|
||||
|
||||
// Initialize helpers
|
||||
const viewer = new Viewer();
|
||||
|
@ -53,8 +52,6 @@ Vue.use(GetTextPlugin, {
|
|||
defaultLanguage: Vue.config.language,
|
||||
});
|
||||
|
||||
Vue.directive("longclick", VueLongClick({delay: 450, interval: 0}));
|
||||
|
||||
Vue.use(VueLuxon);
|
||||
Vue.use(VueInfiniteScroll);
|
||||
Vue.use(VueFullscreen);
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
VueJS long click directive
|
||||
|
||||
Based on https://github.com/ittus/vue-long-click (MIT License)
|
||||
Author: Thang Minh Vu (https://github.com/ittus)
|
||||
*/
|
||||
export default ({delay = 400, interval = 50}) => ({
|
||||
bind: function (el, binding, vNode) {
|
||||
if (typeof binding.value !== "function") {
|
||||
const compName = vNode.context.name;
|
||||
let warn = `[longclick:] provided expression '${binding.expression}' is not a function, but has to be`;
|
||||
if (compName) {
|
||||
warn += `Found in component '${compName}' `;
|
||||
}
|
||||
console.warn(warn) // eslint-disable-line
|
||||
}
|
||||
|
||||
let pressTimer = null;
|
||||
let pressInterval = null;
|
||||
|
||||
const start = (e) => {
|
||||
if (e.type === "click" && e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pressTimer === null) {
|
||||
pressTimer = setTimeout(() => {
|
||||
if (interval && interval > 0) {
|
||||
pressInterval = setInterval(() => {
|
||||
handler();
|
||||
}, interval);
|
||||
}
|
||||
handler();
|
||||
}, delay);
|
||||
}
|
||||
};
|
||||
|
||||
// Cancel Timeout
|
||||
const cancel = () => {
|
||||
if (pressTimer !== null) {
|
||||
clearTimeout(pressTimer);
|
||||
pressTimer = null;
|
||||
}
|
||||
if (pressInterval) {
|
||||
clearInterval(pressInterval);
|
||||
pressInterval = null;
|
||||
}
|
||||
};
|
||||
// Run Function
|
||||
const handler = (e) => {
|
||||
binding.value(e);
|
||||
}
|
||||
|
||||
;["mousedown", "touchstart"].forEach(e => el.addEventListener(e, start))
|
||||
;["click", "mouseout", "touchend", "touchcancel"].forEach(e => el.addEventListener(e, cancel));
|
||||
},
|
||||
});
|
|
@ -23,7 +23,7 @@
|
|||
>
|
||||
<v-hover>
|
||||
<v-card tile slot-scope="{ hover }"
|
||||
@contextmenu="contextMenu($event, photo, index)"
|
||||
@contextmenu="onContextMenu($event, index)"
|
||||
:dark="$clipboard.has(photo)"
|
||||
:class="$clipboard.has(photo) ? 'elevation-10 ma-0 accent darken-1 white--text' : 'elevation-0 ma-1 accent lighten-3'">
|
||||
<v-img
|
||||
|
@ -32,8 +32,8 @@
|
|||
v-bind:class="{ selected: $clipboard.has(photo) }"
|
||||
style="cursor: pointer;"
|
||||
class="accent lighten-2"
|
||||
v-longclick="longClick"
|
||||
@click="onClick($event, photo, index)"
|
||||
@mousedown="onMouseDown($event, index)"
|
||||
@click.stop.prevent="onClick($event, index)"
|
||||
>
|
||||
<v-layout
|
||||
slot="placeholder"
|
||||
|
@ -48,7 +48,7 @@
|
|||
<v-btn v-if="hover || selection.length > 0" :flat="!hover" :ripple="false"
|
||||
icon large absolute
|
||||
:class="$clipboard.has(photo) ? 'p-photo-select' : 'p-photo-select opacity-50'"
|
||||
@click.stop.prevent="onSelect($event, photo, index)">
|
||||
@click.stop.prevent="onSelect($event, index)">
|
||||
<v-icon v-if="selection.length && $clipboard.has(photo)" color="white"
|
||||
class="t-select t-on">check_circle
|
||||
</v-icon>
|
||||
|
@ -75,7 +75,9 @@
|
|||
<h3 class="body-2 mb-2" :title="photo.PhotoTitle">
|
||||
<button @click.exact="editPhoto(index)">
|
||||
{{ photo.PhotoTitle | truncate(80) }}
|
||||
<v-icon v-if="showPrivate && photo.PhotoPrivate" size="16" title="Private">lock</v-icon>
|
||||
<v-icon v-if="showPrivate && photo.PhotoPrivate" size="16" title="Private">
|
||||
lock
|
||||
</v-icon>
|
||||
</button>
|
||||
</h3>
|
||||
<div class="caption">
|
||||
|
@ -117,51 +119,43 @@
|
|||
return {
|
||||
showLocation: this.$config.settings().features.places,
|
||||
showPrivate: this.$config.settings().library.private,
|
||||
wasLong: false,
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
timeStamp: -1,
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
longClick() {
|
||||
this.wasLong = true;
|
||||
},
|
||||
onSelect(ev, model, index) {
|
||||
onSelect(ev, index) {
|
||||
if (ev.shiftKey) {
|
||||
this.selectRange(index);
|
||||
} else {
|
||||
this.$clipboard.toggle(model);
|
||||
this.$clipboard.toggle(this.photos[index]);
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
onClick(ev, model, index) {
|
||||
if (this.wasLong || this.selection.length > 0) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
|
||||
if (this.wasLong || ev.shiftKey) {
|
||||
if (longClick || this.selection.length > 0) {
|
||||
if (longClick || ev.shiftKey) {
|
||||
this.selectRange(index);
|
||||
} else {
|
||||
this.$clipboard.toggle(model);
|
||||
this.$clipboard.toggle(this.photos[index]);
|
||||
}
|
||||
} else {
|
||||
this.openPhoto(index, false);
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
contextMenu(ev, model, index) {
|
||||
onContextMenu(ev, index) {
|
||||
if (this.$isMobile) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (this.wasLong) {
|
||||
this.selectRange(index);
|
||||
} else {
|
||||
this.$clipboard.toggle(model);
|
||||
}
|
||||
this.selectRange(index);
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
selectRange(index) {
|
||||
this.$clipboard.addRange(index, this.photos);
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
<td style="user-select: none;">
|
||||
<v-img class="accent lighten-2" style="cursor: pointer" aspect-ratio="1"
|
||||
:src="props.item.getThumbnailUrl('tile_50')"
|
||||
v-longclick="longClick"
|
||||
@contextmenu="contextMenu($event, props.item, props.index)"
|
||||
@click="onClick($event, props.item, props.index)"
|
||||
@mousedown="onMouseDown($event, props.index)"
|
||||
@contextmenu="onContextMenu($event, props.index)"
|
||||
@click.stop.prevent="onClick($event, props.index)"
|
||||
>
|
||||
<v-layout
|
||||
slot="placeholder"
|
||||
|
@ -37,7 +37,7 @@
|
|||
</v-btn>
|
||||
</v-img>
|
||||
</td>
|
||||
<td class="p-photo-desc p-pointer" @click.exact="openPhoto(props.index)" style="user-select: none;">
|
||||
<td class="p-photo-desc p-pointer" @click.exact="editPhoto(props.index)" style="user-select: none;">
|
||||
{{ props.item.PhotoTitle }}
|
||||
</td>
|
||||
<td class="p-photo-desc hidden-xs-only" :title="props.item.getDateString()">
|
||||
|
@ -98,7 +98,10 @@
|
|||
],
|
||||
showLocation: this.$config.settings().features.places,
|
||||
showPrivate: this.$config.settings().library.private,
|
||||
wasLong: false,
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
timeStamp: -1,
|
||||
},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
|
@ -116,32 +119,36 @@
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
longClick() {
|
||||
this.wasLong = true;
|
||||
},
|
||||
onClick(ev, model, index) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (this.wasLong || ev.shiftKey) {
|
||||
onSelect(ev, index) {
|
||||
if (ev.shiftKey) {
|
||||
this.selectRange(index);
|
||||
} else {
|
||||
this.$clipboard.toggle(model);
|
||||
this.$clipboard.toggle(this.photos[index]);
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
contextMenu(ev, model, index) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
|
||||
if (this.wasLong) {
|
||||
this.selectRange(index);
|
||||
if (longClick || this.selection.length > 0) {
|
||||
if (longClick || ev.shiftKey) {
|
||||
this.selectRange(index);
|
||||
} else {
|
||||
this.$clipboard.toggle(this.photos[index]);
|
||||
}
|
||||
} else {
|
||||
this.$clipboard.toggle(model);
|
||||
this.openPhoto(index, false);
|
||||
}
|
||||
},
|
||||
onContextMenu(ev, index) {
|
||||
if (this.$isMobile) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.selectRange(index);
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
selectRange(index) {
|
||||
this.$clipboard.addRange(index, this.photos);
|
||||
|
|
|
@ -23,15 +23,15 @@
|
|||
>
|
||||
<v-hover>
|
||||
<v-card tile slot-scope="{ hover }"
|
||||
@contextmenu="contextMenu($event, photo, index)"
|
||||
@contextmenu="onContextMenu($event, index)"
|
||||
:class="$clipboard.has(photo) ? 'elevation-10 ma-0' : 'elevation-0 ma-1'"
|
||||
:title="photo.PhotoTitle">
|
||||
<v-img :src="photo.getThumbnailUrl('tile_224')"
|
||||
aspect-ratio="1"
|
||||
class="accent lighten-2"
|
||||
style="cursor: pointer"
|
||||
v-longclick="longClick"
|
||||
@click="onClick($event, photo, index)"
|
||||
@mousedown="onMouseDown($event, index)"
|
||||
@click.stop.prevent="onClick($event, index)"
|
||||
>
|
||||
<v-layout
|
||||
slot="placeholder"
|
||||
|
@ -53,7 +53,7 @@
|
|||
<v-btn v-if="hover || selection.length > 0" :flat="!hover" :ripple="false"
|
||||
icon small absolute
|
||||
:class="$clipboard.has(photo) ? 'p-photo-select' : 'p-photo-select opacity-50'"
|
||||
@click.stop.prevent="onSelect($event, photo, index)">
|
||||
@click.stop.prevent="onSelect($event, index)">
|
||||
<v-icon v-if="selection.length && $clipboard.has(photo)" color="white"
|
||||
class="t-select t-on">check_circle
|
||||
</v-icon>
|
||||
|
@ -100,52 +100,44 @@
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
wasLong: false,
|
||||
showPrivate: this.$config.settings().library.private,
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
timeStamp: -1,
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
longClick() {
|
||||
this.wasLong = true;
|
||||
},
|
||||
onSelect(ev, model, index) {
|
||||
onSelect(ev, index) {
|
||||
if (ev.shiftKey) {
|
||||
this.selectRange(index);
|
||||
} else {
|
||||
this.$clipboard.toggle(model);
|
||||
this.$clipboard.toggle(this.photos[index]);
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
onClick(ev, model, index) {
|
||||
if (this.wasLong || this.selection.length > 0) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
|
||||
if (this.wasLong || ev.shiftKey) {
|
||||
if (longClick || this.selection.length > 0) {
|
||||
if (longClick || ev.shiftKey) {
|
||||
this.selectRange(index);
|
||||
} else {
|
||||
this.$clipboard.toggle(model);
|
||||
this.$clipboard.toggle(this.photos[index]);
|
||||
}
|
||||
} else {
|
||||
this.openPhoto(index, false);
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
contextMenu(ev, model, index) {
|
||||
onContextMenu(ev, index) {
|
||||
if (this.$isMobile) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (this.wasLong) {
|
||||
this.selectRange(index);
|
||||
} else {
|
||||
this.$clipboard.toggle(model);
|
||||
}
|
||||
this.selectRange(index);
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
selectRange(index) {
|
||||
this.$clipboard.addRange(index, this.photos);
|
||||
|
|
|
@ -61,15 +61,15 @@
|
|||
<v-hover>
|
||||
<v-card tile class="accent lighten-3"
|
||||
slot-scope="{ hover }"
|
||||
@contextmenu="contextMenu($event, album, index)"
|
||||
@contextmenu="onContextMenu($event, index)"
|
||||
:dark="selection.includes(album.AlbumUUID)"
|
||||
:class="selection.includes(album.AlbumUUID) ? 'elevation-10 ma-0 accent darken-1 white--text' : 'elevation-0 ma-1 accent lighten-3'"
|
||||
:to="{name: 'album', params: {uuid: album.AlbumUUID, slug: album.AlbumSlug}}"
|
||||
>
|
||||
<v-img
|
||||
:src="album.getThumbnailUrl('tile_500')"
|
||||
v-longclick="longClick"
|
||||
@click="onClick($event, album, index)"
|
||||
@mousedown="onMouseDown($event, index)"
|
||||
@click="onClick($event, index)"
|
||||
aspect-ratio="1"
|
||||
class="accent lighten-2"
|
||||
>
|
||||
|
@ -183,7 +183,10 @@
|
|||
search: this.$gettext("Search"),
|
||||
name: this.$gettext("Album Name"),
|
||||
},
|
||||
wasLong: false,
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
timeStamp: -1,
|
||||
},
|
||||
lastId: "",
|
||||
};
|
||||
},
|
||||
|
@ -213,45 +216,40 @@
|
|||
|
||||
return (rangeEnd - rangeStart) + 1;
|
||||
},
|
||||
longClick() {
|
||||
this.wasLong = true;
|
||||
},
|
||||
onSelect(ev, model, index) {
|
||||
onSelect(ev, index) {
|
||||
if (ev.shiftKey) {
|
||||
this.selectRange(index, this.results);
|
||||
} else {
|
||||
this.toggleSelection(model.getId());
|
||||
this.toggleSelection(this.results[index].getId());
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
onClick(ev, model, index) {
|
||||
if (this.wasLong || this.selection.length > 0) {
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
|
||||
if (longClick || this.selection.length > 0) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (this.wasLong || ev.shiftKey) {
|
||||
if (longClick || ev.shiftKey) {
|
||||
this.selectRange(index, this.results);
|
||||
} else {
|
||||
this.toggleSelection(model.getId());
|
||||
this.toggleSelection(this.results[index].getId());
|
||||
}
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
contextMenu(ev, model, index) {
|
||||
onContextMenu(ev, index) {
|
||||
if (this.$isMobile) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (this.wasLong) {
|
||||
if(this.results[index]) {
|
||||
this.selectRange(index, this.results);
|
||||
} else {
|
||||
this.toggleSelection(model.getId());
|
||||
}
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
clearQuery() {
|
||||
this.filter.q = '';
|
||||
|
|
|
@ -64,14 +64,14 @@
|
|||
<v-hover>
|
||||
<v-card tile class="accent lighten-3"
|
||||
slot-scope="{ hover }"
|
||||
@contextmenu="contextMenu($event, label, index)"
|
||||
@contextmenu="onContextMenu($event, index)"
|
||||
:dark="selection.includes(label.LabelUUID)"
|
||||
:class="selection.includes(label.LabelUUID) ? 'elevation-10 ma-0 accent darken-1 white--text' : 'elevation-0 ma-1 accent lighten-3'"
|
||||
:to="{name: 'photos', query: {q: 'label:' + (label.CustomSlug ? label.CustomSlug : label.LabelSlug)}}">
|
||||
<v-img
|
||||
:src="label.getThumbnailUrl('tile_500')"
|
||||
v-longclick="longClick"
|
||||
@click="onClick($event, label, index)"
|
||||
@mousedown="onMouseDown($event, index)"
|
||||
@click="onClick($event, index)"
|
||||
aspect-ratio="1"
|
||||
class="accent lighten-2"
|
||||
>
|
||||
|
@ -185,7 +185,10 @@
|
|||
name: this.$gettext("Label Name"),
|
||||
},
|
||||
titleRule: v => v.length <= 25 || this.$gettext("Name too long"),
|
||||
wasLong: false,
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
timeStamp: -1,
|
||||
},
|
||||
lastId: "",
|
||||
};
|
||||
},
|
||||
|
@ -215,45 +218,40 @@
|
|||
|
||||
return (rangeEnd - rangeStart) + 1;
|
||||
},
|
||||
longClick() {
|
||||
this.wasLong = true;
|
||||
},
|
||||
onSelect(ev, model, index) {
|
||||
onSelect(ev, index) {
|
||||
if (ev.shiftKey) {
|
||||
this.selectRange(index, this.results);
|
||||
} else {
|
||||
this.toggleSelection(model.getId());
|
||||
this.toggleSelection(this.results[index].getId());
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
onClick(ev, model, index) {
|
||||
if (this.wasLong || this.selection.length > 0) {
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
|
||||
if (longClick || this.selection.length > 0) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (this.wasLong || ev.shiftKey) {
|
||||
if (longClick || ev.shiftKey) {
|
||||
this.selectRange(index, this.results);
|
||||
} else {
|
||||
this.toggleSelection(model.getId());
|
||||
this.toggleSelection(this.results[index].getId());
|
||||
}
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
contextMenu(ev, model, index) {
|
||||
onContextMenu(ev, index) {
|
||||
if (this.$isMobile) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (this.wasLong) {
|
||||
if(this.results[index]) {
|
||||
this.selectRange(index, this.results);
|
||||
} else {
|
||||
this.toggleSelection(model.getId());
|
||||
}
|
||||
}
|
||||
|
||||
this.wasLong = false;
|
||||
},
|
||||
onSave(label) {
|
||||
label.update();
|
||||
|
|
Loading…
Reference in a new issue