Improve UX on iOS touch devices #832
This commit is contained in:
parent
f67cd40e75
commit
bb5f8d8858
|
@ -28,6 +28,7 @@
|
|||
<v-card tile
|
||||
:data-id="photo.ID"
|
||||
:data-uid="photo.UID"
|
||||
style="user-select: none"
|
||||
class="result accent lighten-3"
|
||||
:class="photo.classes()"
|
||||
@contextmenu="onContextMenu($event, index)">
|
||||
|
@ -39,6 +40,8 @@
|
|||
:transition="false"
|
||||
aspect-ratio="1"
|
||||
class="accent lighten-2 clickable"
|
||||
@touchstart="onMouseDown($event, index)"
|
||||
@touchend.stop.prevent="onClick($event, index)"
|
||||
@mousedown="onMouseDown($event, index)"
|
||||
@click.stop.prevent="onClick($event, index)"
|
||||
@mouseover="playLive(photo)"
|
||||
|
@ -53,6 +56,8 @@
|
|||
|
||||
<v-btn :ripple="false" :depressed="false" class="input-open"
|
||||
icon flat absolute
|
||||
@touchstart.stop.prevent="openPhoto(index, true)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, true)">
|
||||
<v-icon color="white" class="default-hidden action-raw" :title="$gettext('RAW')">photo_camera</v-icon>
|
||||
<v-icon color="white" class="default-hidden action-live" :title="$gettext('Live')">adjust</v-icon>
|
||||
|
@ -61,12 +66,16 @@
|
|||
|
||||
<v-btn :ripple="false" :depressed="false" class="input-view"
|
||||
icon flat absolute :title="$gettext('View')"
|
||||
@touchstart.stop.prevent="openPhoto(index, false)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, false)">
|
||||
<v-icon color="white" class="action-fullscreen">zoom_in</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn :ripple="false" :depressed="false" color="white" class="input-play"
|
||||
outline fab absolute :title="$gettext('Play')"
|
||||
@touchstart.stop.prevent="openPhoto(index, true)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, true)">
|
||||
<v-icon color="white" class="action-play">play_arrow</v-icon>
|
||||
</v-btn>
|
||||
|
@ -80,6 +89,8 @@
|
|||
<v-btn :ripple="false"
|
||||
icon flat absolute
|
||||
class="input-select"
|
||||
@touchstart.stop.prevent="onSelect($event, index)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="onSelect($event, index)">
|
||||
<v-icon color="white" class="select-on">check_circle</v-icon>
|
||||
<v-icon color="accent lighten-3" class="select-off">radio_button_off</v-icon>
|
||||
|
@ -88,6 +99,8 @@
|
|||
<v-btn :ripple="false"
|
||||
icon flat absolute
|
||||
class="input-favorite"
|
||||
@touchstart.stop.prevent="photo.toggleLike()"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="photo.toggleLike()">
|
||||
<v-icon color="white" class="select-on">favorite</v-icon>
|
||||
<v-icon color="accent lighten-3" class="select-off">favorite_border</v-icon>
|
||||
|
@ -111,7 +124,7 @@
|
|||
<button class="action-date-edit" :data-uid="photo.UID"
|
||||
@click.exact="editPhoto(index)">
|
||||
<v-icon size="14" :title="labels.taken">date_range</v-icon>
|
||||
{{ photo.getDateString() }}
|
||||
{{ photo.getDateString(true) }}
|
||||
</button>
|
||||
<template v-if="!photo.Description">
|
||||
<br/>
|
||||
|
@ -197,6 +210,7 @@ export default {
|
|||
},
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
scrollY: window.scrollY,
|
||||
timeStamp: -1,
|
||||
},
|
||||
};
|
||||
|
@ -229,10 +243,16 @@ export default {
|
|||
},
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.scrollY = window.scrollY;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const scrolled = (this.mouseDown.scrollY - window.scrollY) !== 0;
|
||||
|
||||
if (scrolled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (longClick || this.selectMode) {
|
||||
if (longClick || ev.shiftKey) {
|
||||
|
|
|
@ -31,14 +31,17 @@
|
|||
item-key="ID"
|
||||
:no-data-text="notFoundMessage"
|
||||
>
|
||||
<template v-slot:items="props">
|
||||
<template #items="props">
|
||||
<td style="user-select: none;" :data-uid="props.item.UID" class="result" :class="props.item.classes()">
|
||||
<v-img :key="props.item.Hash"
|
||||
:src="props.item.thumbnailUrl('tile_50')"
|
||||
:alt="props.item.Title"
|
||||
:transition="false"
|
||||
aspect-ratio="1"
|
||||
style="user-select: none"
|
||||
class="accent lighten-2 clickable"
|
||||
@touchstart="onMouseDown($event, props.index)"
|
||||
@touchend.stop.prevent="onClick($event, props.index)"
|
||||
@mousedown="onMouseDown($event, props.index)"
|
||||
@contextmenu="onContextMenu($event, props.index)"
|
||||
@click.stop.prevent="onClick($event, props.index)"
|
||||
|
@ -148,6 +151,7 @@ export default {
|
|||
hidePrivate: this.$config.values.settings.features.private,
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
scrollY: window.scrollY,
|
||||
timeStamp: -1,
|
||||
},
|
||||
};
|
||||
|
@ -169,10 +173,16 @@ export default {
|
|||
},
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.scrollY = window.scrollY;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const scrolled = (this.mouseDown.scrollY - window.scrollY) !== 0;
|
||||
|
||||
if (scrolled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (longClick || this.selectMode) {
|
||||
if (longClick || ev.shiftKey) {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
<v-card tile
|
||||
:data-id="photo.ID"
|
||||
:data-uid="photo.UID"
|
||||
style="user-select: none"
|
||||
class="result"
|
||||
:class="photo.classes()"
|
||||
@contextmenu="onContextMenu($event, index)">
|
||||
|
@ -38,6 +39,8 @@
|
|||
:transition="false"
|
||||
aspect-ratio="1"
|
||||
class="accent lighten-2 clickable"
|
||||
@touchstart="onMouseDown($event, index)"
|
||||
@touchend.stop.prevent="onClick($event, index)"
|
||||
@mousedown="onMouseDown($event, index)"
|
||||
@click.stop.prevent="onClick($event, index)"
|
||||
@mouseover="playLive(photo)"
|
||||
|
@ -52,6 +55,8 @@
|
|||
|
||||
<v-btn :ripple="false" :depressed="false" class="input-open"
|
||||
icon flat small absolute
|
||||
@touchstart.stop.prevent="openPhoto(index, true)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, true)">
|
||||
<v-icon color="white" class="default-hidden action-raw" :title="$gettext('RAW')">photo_camera</v-icon>
|
||||
<v-icon color="white" class="default-hidden action-live" :title="$gettext('Live')">adjust</v-icon>
|
||||
|
@ -60,12 +65,16 @@
|
|||
|
||||
<v-btn :ripple="false" :depressed="false" class="input-view"
|
||||
icon flat small absolute :title="$gettext('View')"
|
||||
@touchstart.stop.prevent="openPhoto(index, false)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, false)">
|
||||
<v-icon color="white" class="action-fullscreen">zoom_in</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn :ripple="false" :depressed="false" color="white" class="input-play"
|
||||
outline fab absolute :title="$gettext('Play')"
|
||||
@touchstart.stop.prevent="openPhoto(index, true)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, true)">
|
||||
<v-icon color="white" class="action-play">play_arrow</v-icon>
|
||||
</v-btn>
|
||||
|
@ -79,6 +88,8 @@
|
|||
<v-btn :ripple="false"
|
||||
icon flat small absolute
|
||||
class="input-select"
|
||||
@touchstart.stop.prevent="onSelect($event, index)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="onSelect($event, index)">
|
||||
<v-icon color="white" class="select-on">check_circle</v-icon>
|
||||
<v-icon color="accent lighten-3" class="select-off">radio_button_off</v-icon>
|
||||
|
@ -87,6 +98,8 @@
|
|||
<v-btn :ripple="false"
|
||||
icon flat small absolute
|
||||
class="input-favorite"
|
||||
@touchstart.stop.prevent="photo.toggleLike()"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="photo.toggleLike()">
|
||||
<v-icon color="white" class="select-on">favorite</v-icon>
|
||||
<v-icon color="accent lighten-3" class="select-off">favorite_border</v-icon>
|
||||
|
@ -114,6 +127,7 @@ export default {
|
|||
hidePrivate: this.$config.settings().features.private,
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
scrollY: window.scrollY,
|
||||
timeStamp: -1,
|
||||
},
|
||||
};
|
||||
|
@ -139,13 +153,19 @@ export default {
|
|||
},
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.scrollY = window.scrollY;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
toggle(photo) {
|
||||
this.$clipboard.toggle(photo);
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const scrolled = (this.mouseDown.scrollY - window.scrollY) !== 0;
|
||||
|
||||
if (scrolled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (longClick || this.selectMode) {
|
||||
if (longClick || ev.shiftKey) {
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
#photoprism .cards-view,
|
||||
#photoprism .mosaic-view,
|
||||
#photoprism .cards-view .v-card,
|
||||
#photoprism .mosaic-view .v-card {
|
||||
user-select: none !important;
|
||||
}
|
||||
|
||||
#photoprism .p-col-select {
|
||||
width: 66px;
|
||||
}
|
||||
|
|
|
@ -65,6 +65,13 @@ export class Album extends RestModel {
|
|||
};
|
||||
}
|
||||
|
||||
route(view) {
|
||||
return {
|
||||
name: view,
|
||||
params: { uid: this.UID, slug: this.Slug, year: this.Year, month: this.Month },
|
||||
};
|
||||
}
|
||||
|
||||
classes(selected) {
|
||||
let classes = ["is-album", "uid-" + this.UID, "type-" + this.Type];
|
||||
|
||||
|
|
|
@ -53,6 +53,10 @@ export class Label extends RestModel {
|
|||
};
|
||||
}
|
||||
|
||||
route(view) {
|
||||
return { name: view, query: { q: "label:" + (this.CustomSlug ? this.CustomSlug : this.Slug) } };
|
||||
}
|
||||
|
||||
classes(selected) {
|
||||
let classes = ["is-label", "uid-" + this.UID];
|
||||
|
||||
|
|
|
@ -51,6 +51,29 @@ export const YearUnknown = -1;
|
|||
export const MonthUnknown = -1;
|
||||
export const DayUnknown = -1;
|
||||
|
||||
const num = "numeric";
|
||||
const short = "short";
|
||||
const long = "long";
|
||||
|
||||
const DATE_FULL = {
|
||||
year: num,
|
||||
month: long,
|
||||
day: num,
|
||||
weekday: long,
|
||||
hour: num,
|
||||
minute: num,
|
||||
};
|
||||
|
||||
const DATE_FULL_TZ = {
|
||||
year: num,
|
||||
month: long,
|
||||
day: num,
|
||||
weekday: long,
|
||||
hour: num,
|
||||
minute: num,
|
||||
timeZoneName: short,
|
||||
};
|
||||
|
||||
export class Photo extends RestModel {
|
||||
constructor(values) {
|
||||
super(values);
|
||||
|
@ -427,15 +450,18 @@ export class Photo extends RestModel {
|
|||
return { width: newW, height: newH };
|
||||
}
|
||||
|
||||
getDateString() {
|
||||
getDateString(showTimeZone) {
|
||||
if (!this.TakenAt || this.Year === YearUnknown) {
|
||||
return $gettext("Unknown");
|
||||
} else if (this.Month === MonthUnknown) {
|
||||
return this.localYearString();
|
||||
} else if (this.Day === DayUnknown) {
|
||||
return this.localDate().toLocaleString({ month: "long", year: "numeric" });
|
||||
return this.localDate().toLocaleString({
|
||||
month: long,
|
||||
year: num,
|
||||
});
|
||||
} else if (this.TimeZone) {
|
||||
return this.localDate().toLocaleString(DateTime.DATETIME_FULL);
|
||||
return this.localDate().toLocaleString(showTimeZone ? DATE_FULL_TZ : DATE_FULL);
|
||||
}
|
||||
|
||||
return this.localDate().toLocaleString(DateTime.DATE_HUGE);
|
||||
|
|
|
@ -85,9 +85,10 @@
|
|||
>
|
||||
<v-card tile
|
||||
:data-uid="album.UID"
|
||||
style="user-select: none"
|
||||
class="result accent lighten-3"
|
||||
:class="album.classes(selection.includes(album.UID))"
|
||||
:to="{name: view, params: {uid: album.UID, slug: album.Slug, year: album.Year, month: album.Month}}"
|
||||
:to="album.route(view)"
|
||||
@contextmenu="onContextMenu($event, index)"
|
||||
>
|
||||
<div class="card-background accent lighten-3"></div>
|
||||
|
@ -97,12 +98,16 @@
|
|||
:transition="false"
|
||||
aspect-ratio="1"
|
||||
class="accent lighten-2 clickable"
|
||||
@touchstart="onMouseDown($event, index)"
|
||||
@touchend.stop.prevent="onClick($event, index)"
|
||||
@mousedown="onMouseDown($event, index)"
|
||||
@click="onClick($event, index)"
|
||||
@click.stop.prevent="onClick($event, index)"
|
||||
>
|
||||
<v-btn v-if="featureShare && album.LinkCount > 0" :ripple="false"
|
||||
icon flat absolute
|
||||
class="action-share"
|
||||
@touchstart.stop.prevent="share(album)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="share(album)">
|
||||
<v-icon color="white">share</v-icon>
|
||||
</v-btn>
|
||||
|
@ -110,6 +115,8 @@
|
|||
<v-btn :ripple="false"
|
||||
icon flat absolute
|
||||
class="input-select"
|
||||
@touchstart.stop.prevent="onSelect($event, index)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="onSelect($event, index)">
|
||||
<v-icon color="white" class="select-on">check_circle</v-icon>
|
||||
<v-icon color="accent lighten-3" class="select-off">radio_button_off</v-icon>
|
||||
|
@ -118,6 +125,8 @@
|
|||
<v-btn :ripple="false"
|
||||
icon flat absolute
|
||||
class="input-favorite"
|
||||
@touchstart.stop.prevent="album.toggleLike()"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="album.toggleLike()">
|
||||
<v-icon color="#FFD600" class="select-on">star</v-icon>
|
||||
<v-icon color="white" class="select-off">star_border</v-icon>
|
||||
|
@ -234,6 +243,7 @@ export default {
|
|||
titleRule: v => v.length <= this.$config.get('clip') || this.$gettext("Title too long"),
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
scrollY: window.scrollY,
|
||||
timeStamp: -1,
|
||||
},
|
||||
lastId: "",
|
||||
|
@ -345,20 +355,25 @@ export default {
|
|||
},
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.scrollY = window.scrollY;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const scrolled = (this.mouseDown.scrollY - window.scrollY) !== 0;
|
||||
|
||||
if (scrolled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (longClick || this.selection.length > 0) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (longClick || ev.shiftKey) {
|
||||
this.selectRange(index, this.results);
|
||||
} else {
|
||||
this.toggleSelection(this.results[index].getId());
|
||||
}
|
||||
} else {
|
||||
this.$router.push(this.results[index].route(this.view));
|
||||
}
|
||||
},
|
||||
onContextMenu(ev, index) {
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
xs3 d-flex grow
|
||||
>
|
||||
<v-hover>
|
||||
<v-card :to="{name: 'browse', query: { color: color.name }}" :dark="useDark(color)"
|
||||
:color="color.example" slot-scope="{ hover }" :flat="!hover"
|
||||
<v-card slot-scope="{ hover }" :to="{name: 'browse', query: { color: color.name }}"
|
||||
:dark="useDark(color)" :color="color.example" :flat="!hover"
|
||||
class="clickable py-1">
|
||||
<v-card-text class="px-0 py-5 body-2">{{ color.label }}</v-card-text>
|
||||
</v-card>
|
||||
|
@ -30,7 +30,7 @@
|
|||
<script>
|
||||
|
||||
export default {
|
||||
name: 'p-tab-discover-colors',
|
||||
name: 'PTabDiscoverColors',
|
||||
data() {
|
||||
return {
|
||||
readonly: this.$config.get("readonly"),
|
||||
|
@ -38,6 +38,8 @@ export default {
|
|||
labels: {},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
},
|
||||
methods: {
|
||||
useDark(color) {
|
||||
switch (color.name) {
|
||||
|
@ -48,7 +50,5 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -62,9 +62,10 @@
|
|||
>
|
||||
<v-card tile
|
||||
:data-uid="label.UID"
|
||||
style="user-select: none"
|
||||
class="result accent lighten-3"
|
||||
:class="label.classes(selection.includes(label.UID))"
|
||||
:to="{name: 'all', query: {q: 'label:' + (label.CustomSlug ? label.CustomSlug : label.Slug)}}"
|
||||
:to="label.route(view)"
|
||||
@contextmenu="onContextMenu($event, index)"
|
||||
>
|
||||
<div class="card-background accent lighten-3"></div>
|
||||
|
@ -74,12 +75,16 @@
|
|||
:transition="false"
|
||||
aspect-ratio="1"
|
||||
class="accent lighten-2 clickable"
|
||||
@touchstart="onMouseDown($event, index)"
|
||||
@touchend.stop.prevent="onClick($event, index)"
|
||||
@mousedown="onMouseDown($event, index)"
|
||||
@click="onClick($event, index)"
|
||||
@click.stop.prevent="onClick($event, index)"
|
||||
>
|
||||
<v-btn :ripple="false"
|
||||
icon flat absolute
|
||||
class="input-select"
|
||||
@touchstart.stop.prevent="onSelect($event, index)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="onSelect($event, index)">
|
||||
<v-icon color="white" class="select-on">check_circle</v-icon>
|
||||
<v-icon color="accent lighten-3" class="select-off">radio_button_off</v-icon>
|
||||
|
@ -88,6 +93,8 @@
|
|||
<v-btn :ripple="false"
|
||||
icon flat absolute
|
||||
class="input-favorite"
|
||||
@touchstart.stop.prevent="label.toggleLike()"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="label.toggleLike()">
|
||||
<v-icon color="#FFD600" class="select-on">star</v-icon>
|
||||
<v-icon color="white" class="select-off">star_border</v-icon>
|
||||
|
@ -148,6 +155,7 @@ export default {
|
|||
const settings = {};
|
||||
|
||||
return {
|
||||
view: 'all',
|
||||
config: this.$config.values,
|
||||
subscriptions: [],
|
||||
listen: false,
|
||||
|
@ -166,6 +174,7 @@ export default {
|
|||
titleRule: v => v.length <= this.$config.get('clip') || this.$gettext("Name too long"),
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
scrollY: window.scrollY,
|
||||
timeStamp: -1,
|
||||
},
|
||||
lastId: "",
|
||||
|
@ -243,20 +252,25 @@ export default {
|
|||
},
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.scrollY = window.scrollY;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const scrolled = (this.mouseDown.scrollY - window.scrollY) !== 0;
|
||||
|
||||
if (scrolled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (longClick || this.selection.length > 0) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (longClick || ev.shiftKey) {
|
||||
this.selectRange(index, this.results);
|
||||
} else {
|
||||
this.toggleSelection(this.results[index].getId());
|
||||
}
|
||||
} else {
|
||||
this.$router.push(this.results[index].route(this.view));
|
||||
}
|
||||
},
|
||||
onContextMenu(ev, index) {
|
||||
|
|
|
@ -149,6 +149,7 @@ export default {
|
|||
titleRule: v => v.length <= this.$config.get('clip') || this.$gettext("Name too long"),
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
scrollY: window.scrollY,
|
||||
timeStamp: -1,
|
||||
},
|
||||
lastId: "",
|
||||
|
@ -248,10 +249,16 @@ export default {
|
|||
},
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.scrollY = window.scrollY;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const scrolled = (this.mouseDown.scrollY - window.scrollY) !== 0;
|
||||
|
||||
if (scrolled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (longClick || this.selection.length > 0) {
|
||||
ev.preventDefault();
|
||||
|
|
|
@ -36,9 +36,10 @@
|
|||
>
|
||||
<v-card tile
|
||||
:data-uid="album.UID"
|
||||
style="user-select: none"
|
||||
class="result accent lighten-3"
|
||||
:class="album.classes(selection.includes(album.UID))"
|
||||
:to="{name: view, params: {uid: album.UID, slug: album.Slug, year: album.Year, month: album.Month}}"
|
||||
:to="album.route(view)"
|
||||
@contextmenu="onContextMenu($event, index)"
|
||||
>
|
||||
<div class="card-background accent lighten-3"></div>
|
||||
|
@ -48,12 +49,16 @@
|
|||
:transition="false"
|
||||
aspect-ratio="1"
|
||||
class="accent lighten-2 clickable"
|
||||
@touchstart="onMouseDown($event, index)"
|
||||
@touchend.stop.prevent="onClick($event, index)"
|
||||
@mousedown="onMouseDown($event, index)"
|
||||
@click="onClick($event, index)"
|
||||
@click.stop.prevent="onClick($event, index)"
|
||||
>
|
||||
<v-btn :ripple="false"
|
||||
icon flat absolute
|
||||
class="input-select"
|
||||
@touchstart.stop.prevent="onSelect($event, index)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="onSelect($event, index)">
|
||||
<v-icon color="white" class="select-on">check_circle</v-icon>
|
||||
<v-icon color="accent lighten-3" class="select-off">radio_button_off</v-icon>
|
||||
|
@ -143,6 +148,7 @@ export default {
|
|||
titleRule: v => v.length <= this.$config.get('clip') || this.$gettext("Title too long"),
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
scrollY: window.scrollY,
|
||||
timeStamp: -1,
|
||||
},
|
||||
lastId: "",
|
||||
|
@ -245,20 +251,25 @@ export default {
|
|||
},
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.scrollY = window.scrollY;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const scrolled = (this.mouseDown.scrollY - window.scrollY) !== 0;
|
||||
|
||||
if (scrolled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (longClick || this.selection.length > 0) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
if (longClick || ev.shiftKey) {
|
||||
this.selectRange(index, this.results);
|
||||
} else {
|
||||
this.toggleSelection(this.results[index].getId());
|
||||
}
|
||||
} else {
|
||||
this.$router.push(this.results[index].route(this.view));
|
||||
}
|
||||
},
|
||||
onContextMenu(ev, index) {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<v-card tile
|
||||
:data-id="photo.ID"
|
||||
:data-uid="photo.UID"
|
||||
style="user-select: none"
|
||||
class="result accent lighten-3"
|
||||
:class="photo.classes()"
|
||||
@contextmenu="onContextMenu($event, index)">
|
||||
|
@ -35,6 +36,8 @@
|
|||
:transition="false"
|
||||
aspect-ratio="1"
|
||||
class="accent lighten-2 clickable"
|
||||
@touchstart="onMouseDown($event, index)"
|
||||
@touchend.stop.prevent="onClick($event, index)"
|
||||
@mousedown="onMouseDown($event, index)"
|
||||
@click.stop.prevent="onClick($event, index)"
|
||||
@mouseover="playLive(photo)"
|
||||
|
@ -49,6 +52,8 @@
|
|||
|
||||
<v-btn :ripple="false" :depressed="false" class="input-open"
|
||||
icon flat absolute
|
||||
@touchstart.stop.prevent="openPhoto(index, true)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, true)">
|
||||
<v-icon color="white" class="default-hidden action-raw" :title="$gettext('RAW')">photo_camera</v-icon>
|
||||
<v-icon color="white" class="default-hidden action-live" :title="$gettext('Live')">adjust</v-icon>
|
||||
|
@ -57,12 +62,16 @@
|
|||
|
||||
<v-btn :ripple="false" :depressed="false" class="input-view"
|
||||
icon flat absolute :title="$gettext('View')"
|
||||
@touchstart.stop.prevent="openPhoto(index, false)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, false)">
|
||||
<v-icon color="white" class="action-fullscreen">zoom_in</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn :ripple="false" :depressed="false" color="white" class="input-play"
|
||||
outline fab absolute :title="$gettext('Play')"
|
||||
@touchstart.stop.prevent="openPhoto(index, true)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, true)">
|
||||
<v-icon color="white" class="action-play">play_arrow</v-icon>
|
||||
</v-btn>
|
||||
|
@ -70,6 +79,8 @@
|
|||
<v-btn :ripple="false"
|
||||
icon flat absolute
|
||||
class="input-select"
|
||||
@touchstart.stop.prevent="onSelect($event, index)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="onSelect($event, index)">
|
||||
<v-icon color="white" class="select-on">check_circle</v-icon>
|
||||
<v-icon color="accent lighten-3" class="select-off">radio_button_off</v-icon>
|
||||
|
@ -91,7 +102,7 @@
|
|||
<div class="caption">
|
||||
<div>
|
||||
<v-icon size="14" :title="labels.taken">date_range</v-icon>
|
||||
{{ photo.getDateString() }}
|
||||
{{ photo.getDateString(true) }}
|
||||
</div>
|
||||
<template v-if="!photo.Description">
|
||||
<div v-if="photo.Type === 'video'" :title="labels.video">
|
||||
|
@ -153,6 +164,7 @@ export default {
|
|||
},
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
scrollY: window.scrollY,
|
||||
timeStamp: -1,
|
||||
},
|
||||
};
|
||||
|
@ -185,10 +197,16 @@ export default {
|
|||
},
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.scrollY = window.scrollY;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const scrolled = (this.mouseDown.scrollY - window.scrollY) !== 0;
|
||||
|
||||
if (scrolled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (longClick || this.selectMode) {
|
||||
if (longClick || ev.shiftKey) {
|
||||
|
|
|
@ -27,14 +27,17 @@
|
|||
item-key="ID"
|
||||
:no-data-text="notFoundMessage"
|
||||
>
|
||||
<template slot:items="props">
|
||||
<template #items="props">
|
||||
<td style="user-select: none;" :data-uid="props.item.UID" class="result" :class="props.item.classes()">
|
||||
<v-img :key="props.item.Hash"
|
||||
:src="props.item.thumbnailUrl('tile_50')"
|
||||
:alt="props.item.Title"
|
||||
:transition="false"
|
||||
aspect-ratio="1"
|
||||
style="user-select: none"
|
||||
class="accent lighten-2 clickable"
|
||||
@touchstart="onMouseDown($event, props.index)"
|
||||
@touchend.stop.prevent="onClick($event, props.index)"
|
||||
@mousedown="onMouseDown($event, props.index)"
|
||||
@contextmenu="onContextMenu($event, props.index)"
|
||||
@click.stop.prevent="onClick($event, props.index)"
|
||||
|
@ -127,6 +130,7 @@ export default {
|
|||
hidePrivate: this.$config.values.settings.features.private,
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
scrollY: window.scrollY,
|
||||
timeStamp: -1,
|
||||
},
|
||||
};
|
||||
|
@ -148,10 +152,16 @@ export default {
|
|||
},
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.scrollY = window.scrollY;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const scrolled = (this.mouseDown.scrollY - window.scrollY) !== 0;
|
||||
|
||||
if (scrolled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (longClick || this.selectMode) {
|
||||
if (longClick || ev.shiftKey) {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<v-card tile
|
||||
:data-id="photo.ID"
|
||||
:data-uid="photo.UID"
|
||||
style="user-select: none"
|
||||
class="result"
|
||||
:class="photo.classes()"
|
||||
@contextmenu="onContextMenu($event, index)">
|
||||
|
@ -34,6 +35,8 @@
|
|||
:transition="false"
|
||||
aspect-ratio="1"
|
||||
class="accent lighten-2 clickable"
|
||||
@touchstart="onMouseDown($event, index)"
|
||||
@touchend.stop.prevent="onClick($event, index)"
|
||||
@mousedown="onMouseDown($event, index)"
|
||||
@click.stop.prevent="onClick($event, index)"
|
||||
@mouseover="playLive(photo)"
|
||||
|
@ -48,6 +51,8 @@
|
|||
|
||||
<v-btn :ripple="false" :depressed="false" class="input-open"
|
||||
icon flat small absolute
|
||||
@touchstart.stop.prevent="openPhoto(index, true)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, true)">
|
||||
<v-icon color="white" class="default-hidden action-raw" :title="$gettext('RAW')">photo_camera</v-icon>
|
||||
<v-icon color="white" class="default-hidden action-live" :title="$gettext('Live')">adjust</v-icon>
|
||||
|
@ -56,12 +61,16 @@
|
|||
|
||||
<v-btn :ripple="false" :depressed="false" class="input-view"
|
||||
icon flat small absolute :title="$gettext('View')"
|
||||
@touchstart.stop.prevent="openPhoto(index, false)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, false)">
|
||||
<v-icon color="white" class="action-fullscreen">zoom_in</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<v-btn :ripple="false" :depressed="false" color="white" class="input-play"
|
||||
outline fab absolute :title="$gettext('Play')"
|
||||
@touchstart.stop.prevent="openPhoto(index, true)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="openPhoto(index, true)">
|
||||
<v-icon color="white" class="action-play">play_arrow</v-icon>
|
||||
</v-btn>
|
||||
|
@ -69,6 +78,8 @@
|
|||
<v-btn :ripple="false"
|
||||
icon flat small absolute
|
||||
class="input-select"
|
||||
@touchstart.stop.prevent="onSelect($event, index)"
|
||||
@touchend.stop.prevent
|
||||
@click.stop.prevent="onSelect($event, index)">
|
||||
<v-icon color="white" class="select-on">check_circle</v-icon>
|
||||
<v-icon color="accent lighten-3" class="select-off">radio_button_off</v-icon>
|
||||
|
@ -96,6 +107,7 @@ export default {
|
|||
hidePrivate: this.$config.settings().features.private,
|
||||
mouseDown: {
|
||||
index: -1,
|
||||
scrollY: window.scrollY,
|
||||
timeStamp: -1,
|
||||
},
|
||||
};
|
||||
|
@ -121,13 +133,19 @@ export default {
|
|||
},
|
||||
onMouseDown(ev, index) {
|
||||
this.mouseDown.index = index;
|
||||
this.mouseDown.scrollY = window.scrollY;
|
||||
this.mouseDown.timeStamp = ev.timeStamp;
|
||||
},
|
||||
toggle(photo) {
|
||||
this.$clipboard.toggle(photo);
|
||||
},
|
||||
onClick(ev, index) {
|
||||
let longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const longClick = (this.mouseDown.index === index && ev.timeStamp - this.mouseDown.timeStamp > 400);
|
||||
const scrolled = (this.mouseDown.scrollY - window.scrollY) !== 0;
|
||||
|
||||
if (scrolled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (longClick || this.selectMode) {
|
||||
if (longClick || ev.shiftKey) {
|
||||
|
|
|
@ -172,7 +172,7 @@ describe("model/photo", () => {
|
|||
const values = {ID: 5, Title: "Crazy Cat", TakenAtLocal: "2012-07-08T14:45:39Z", TakenAt: "2012-07-08T14:45:39Z", TimeZone: "UTC"};
|
||||
const photo = new Photo(values);
|
||||
const result = photo.getDateString();
|
||||
assert.equal(result, "July 8, 2012, 2:45 PM UTC");
|
||||
assert.equal(result, "Sunday, July 8, 2012, 2:45 PM");
|
||||
const values2 = {ID: 5, Title: "Crazy Cat", TakenAtLocal: "", TakenAt: "", TimeZone: "UTC"};
|
||||
const photo2 = new Photo(values2);
|
||||
const result2 = photo2.getDateString();
|
||||
|
|
Loading…
Reference in New Issue
Block a user