@christianriedl/media 1.0.91 → 1.0.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/iMedia.d.ts
CHANGED
package/dist/iMedia.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iMedia.js","sourceRoot":"","sources":["../src/iMedia.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,UASX;AATD,WAAY,UAAU;IAClB,6CAAS,CAAA;IACT,6CAAS,CAAA;IACT,iDAAW,CAAA;IACX,4CAAS,CAAA;IACT,0DAAgB,CAAA;IAChB,iDAAa,CAAA;IACb,6CAAW,CAAA;IACX,mDAAc,CAAA;AAClB,CAAC,EATW,UAAU,KAAV,UAAU,QASrB;AACD,MAAM,CAAN,IAAY,eAWX;AAXD,WAAY,eAAe;IACvB,qDAAiB,CAAA;IACjB,gEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,kEAAoB,CAAA;IACpB,4DAAoB,CAAA;IACpB,4DAAoB,CAAA;IACpB,4DAAoB,CAAA;IACpB,8DAAoB,CAAA;AACxB,CAAC,EAXW,eAAe,KAAf,eAAe,QAW1B;
|
|
1
|
+
{"version":3,"file":"iMedia.js","sourceRoot":"","sources":["../src/iMedia.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,UASX;AATD,WAAY,UAAU;IAClB,6CAAS,CAAA;IACT,6CAAS,CAAA;IACT,iDAAW,CAAA;IACX,4CAAS,CAAA;IACT,0DAAgB,CAAA;IAChB,iDAAa,CAAA;IACb,6CAAW,CAAA;IACX,mDAAc,CAAA;AAClB,CAAC,EATW,UAAU,KAAV,UAAU,QASrB;AACD,MAAM,CAAN,IAAY,eAWX;AAXD,WAAY,eAAe;IACvB,qDAAiB,CAAA;IACjB,gEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,kEAAoB,CAAA;IACpB,4DAAoB,CAAA;IACpB,4DAAoB,CAAA;IACpB,4DAAoB,CAAA;IACpB,8DAAoB,CAAA;AACxB,CAAC,EAXW,eAAe,KAAf,eAAe,QAW1B;AAOD,MAAM,CAAN,IAAY,SAoDX;AApDD,WAAY,SAAS;IACjB,yCAAQ,CAAA;IACR,mDAAa,CAAA;IACb,uDAAe,CAAA;IACf,uDAAe,CAAA;IACf,6DAAkB,CAAA;IAClB,iEAAoB,CAAA;IACpB,iEAAoB,CAAA;IACpB,iEAAoB,CAAA;IACpB,iEAAoB,CAAA;IACpB,mDAAgB,CAAA;IAChB,6CAAa,CAAA;IACb,4CAAY,CAAA;IACZ,4CAAY,CAAA;IACZ,gDAAc,CAAA;IACd,6DAAoB,CAAA;IACpB,qDAAgB,CAAA;IAChB,yCAAa,CAAA;IACb,mDAA6C,CAAA;IAC7C,oDAA0B,CAAA;IAC1B,wDAAkC,CAAA;IAClC,wDAAkC,CAAA;IAClC,8DAAqC,CAAA;IACrC,sDAAiC,CAAA;IACjC,wDAAkC,CAAA;IAClC,sDAAiC,CAAA;IACjC,0DAAmC,CAAA;IACnC,uEAA0C,CAAA;IAC1C,2EAA8C,CAAA;IAC9C,sDAAkB,CAAA;IAClB,+DAAkC,CAAA;IAClC,oDAA0B,CAAA;IAC1B,wDAAkC,CAAA;IAClC,wDAAkC,CAAA;IAClC,8DAAqC,CAAA;IACrC,4DAAoC,CAAA;IACpC,uEAA0C,CAAA;IAC1C,2EAA8C,CAAA;IAC9C,yEAA+C,CAAA;IAC/C,oDAAiB,CAAA;IACjB,+DAAkC,CAAA;IAClC,wDAA8B,CAAA;IAC9B,4DAAsC,CAAA;IACtC,4DAAsC,CAAA;IACtC,kEAAyC,CAAA;IACzC,gEAAwC,CAAA;IACxC,wDAAoC,CAAA;IACpC,0DAAqC,CAAA;IACrC,wDAAqB,CAAA;IACrB,uDAA+C,CAAA;IAC/C,qDAAgB,CAAA;IAChB,yCAAU,CAAA;AACd,CAAC,EApDW,SAAS,KAAT,SAAS,QAoDpB;AACD,MAAM,CAAN,IAAY,MAUX;AAVD,WAAY,MAAM;IACd,mCAAQ,CAAA;IACR,yDAAsB,CAAA;IACtB,2CAAe,CAAA;IACf,+CAAiB,CAAA;IACjB,qDAAoB,CAAA;IACpB,kDAAkB,CAAA;IAClB,sDAAoB,CAAA;IACpB,0DAAsB,CAAA;IACtB,+DAAwB,CAAA;AAC5B,CAAC,EAVW,MAAM,KAAN,MAAM,QAUjB;AAwDD,MAAM,CAAN,IAAY,YAQX;AARD,WAAY,YAAY;IAEpB,+CAAQ,CAAA;IACR,qDAAW,CAAA;IACX,6DAAe,CAAA;IACf,uDAAY,CAAA;IACZ,2DAAc,CAAA;IACd,yDAAa,CAAA;AACjB,CAAC,EARW,YAAY,KAAZ,YAAY,QAQvB"}
|
package/package.json
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
<v-text-field name="directory" label="Name (Directory)" type="text" v-model="name" density="compact" hide-details></v-text-field>
|
|
41
41
|
</v-col>
|
|
42
42
|
<v-col cols="4">
|
|
43
|
-
<v-file-input show-size clearable multiple v-model="files" :accept="props.accept" label="Select File"
|
|
43
|
+
<v-file-input show-size clearable multiple hide-details v-model="files" :accept="props.accept" label="Select File"
|
|
44
44
|
prepend-icon="" append-icon="$upload" @click:append="onUpload">
|
|
45
45
|
</v-file-input>
|
|
46
46
|
</v-col>
|
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
let gpsLat: number[];
|
|
34
34
|
let mouseDownTime: number = 0;
|
|
35
35
|
let mouseTimer: number = -1;
|
|
36
|
+
let nameTimer: number = -1;
|
|
37
|
+
const showName = ref(false);
|
|
36
38
|
|
|
37
39
|
watch([appState.bodyHeight, appState.pageWidth], () => {
|
|
38
40
|
width.value = appState.pageWidth.value;
|
|
@@ -68,6 +70,7 @@
|
|
|
68
70
|
}
|
|
69
71
|
}
|
|
70
72
|
url.value = photos.Url;
|
|
73
|
+
onUpdate();
|
|
71
74
|
}
|
|
72
75
|
else {
|
|
73
76
|
nextTick(() => router.back());
|
|
@@ -194,12 +197,12 @@
|
|
|
194
197
|
case "ArrowLeft":
|
|
195
198
|
if (index.value > 0)
|
|
196
199
|
index.value--;
|
|
197
|
-
|
|
200
|
+
onUpdate();
|
|
198
201
|
break;
|
|
199
202
|
case "ArrowRight":
|
|
200
203
|
if (index.value < items.length - 1)
|
|
201
204
|
index.value++;
|
|
202
|
-
|
|
205
|
+
onUpdate();
|
|
203
206
|
break;
|
|
204
207
|
case "KeyI": // Info
|
|
205
208
|
if (infoDialog.value) {
|
|
@@ -364,15 +367,38 @@
|
|
|
364
367
|
document.body.removeChild(anchor);
|
|
365
368
|
infoDialog.value = false;
|
|
366
369
|
}
|
|
370
|
+
function clearName() { // also called by VImg::loadstart
|
|
371
|
+
showName.value = false;
|
|
372
|
+
if (nameTimer >= 0) {
|
|
373
|
+
window.clearTimeout(nameTimer);
|
|
374
|
+
nameTimer = -1;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
function onUpdate() { // Carousel updated
|
|
378
|
+
infoDialog.value = false;
|
|
379
|
+
clearName();
|
|
380
|
+
const item = items[index.value];
|
|
381
|
+
nameTimer = window.setTimeout(() => { onLoad(item); }, 200);
|
|
382
|
+
}
|
|
383
|
+
function onLoad(item: IPictureFile) { // img loaded or cached
|
|
384
|
+
clearName();
|
|
385
|
+
const idx = item.Url.lastIndexOf('.');
|
|
386
|
+
const name = item.Url.substr(0, idx);
|
|
387
|
+
if (!name.includes(item.Name)) {
|
|
388
|
+
showName.value = true;
|
|
389
|
+
nameTimer = window.setTimeout(() => { clearName(); }, mediaAppConfig.nameDurationMS);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
367
392
|
</script>
|
|
368
393
|
|
|
369
394
|
<template>
|
|
370
395
|
<v-container fluid :style="heightStyle" class="bg-grey-darken-3 pa-0">
|
|
371
396
|
<v-carousel ref="carousel" hide-delimiters :show-arrows="false" v-model="index"
|
|
372
397
|
:width="width" :height="height" :cycle="cycle" :interval="interval"
|
|
373
|
-
@click="onClick" @mousedown="onMouseDown" @update:modelValue="
|
|
374
|
-
<v-carousel-item v-for="item in items" :key="item.DLNAID"
|
|
375
|
-
|
|
398
|
+
@click="onClick" @mousedown="onMouseDown" @update:modelValue="onUpdate">
|
|
399
|
+
<v-carousel-item v-for="item in items" :key="item.DLNAID" :src="getUrl(item)" :alt="item.Name" :width="getWidth(item)" :height="getHeight(item)"
|
|
400
|
+
@load="onLoad(item)" @loadstart="clearName()">
|
|
401
|
+
<h2 v-if="showName" class="imgtext">{{item.Name}}</h2>
|
|
376
402
|
</v-carousel-item>
|
|
377
403
|
</v-carousel>
|
|
378
404
|
<v-dialog v-model="infoDialog" :fullscreen="isMobile" >
|
|
@@ -441,4 +467,11 @@
|
|
|
441
467
|
margin-left: auto;
|
|
442
468
|
margin-right: auto;
|
|
443
469
|
}
|
|
470
|
+
.imgtext {
|
|
471
|
+
position:absolute;
|
|
472
|
+
top:0px;
|
|
473
|
+
width:100%;
|
|
474
|
+
text-align:center;
|
|
475
|
+
color:magenta;
|
|
476
|
+
}
|
|
444
477
|
</style>
|
package/src/views/PhotosPage.vue
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
const router = useRouter();
|
|
18
18
|
const open = ref<string[]>([]);
|
|
19
19
|
|
|
20
|
-
const items
|
|
20
|
+
const items = ref<IMediaFolder[]>([]);
|
|
21
21
|
const selected = reactive<IPhotoSelection>(mediaService.photoSelection);
|
|
22
22
|
const listHeight = ref(0);
|
|
23
23
|
const listhead = ref<ComponentPublicInstance|null>(null);
|
|
@@ -181,7 +181,7 @@
|
|
|
181
181
|
itemIndex.value = i;
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
|
-
items.
|
|
184
|
+
items.value = folders;
|
|
185
185
|
}
|
|
186
186
|
function onScroll(ev: Event) {
|
|
187
187
|
const scrollTop = (ev.target as Element).scrollTop;
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { inject, ref, reactive, computed, onMounted, onUnmounted, nextTick, watch, StyleValue } from 'vue';
|
|
3
|
+
import { VDataTableVirtual } from 'vuetify/labs/VDataTable';
|
|
4
|
+
import type { ComponentPublicInstance } from 'vue';
|
|
5
|
+
import { useRouter } from 'vue-router';
|
|
6
|
+
import { IAppState, IAppConfig, EDevice, EBrowser, appStateSymbol, appConfigSymbol, Helper } from '@christianriedl/utils';
|
|
7
|
+
import { EItemType, EMediaType, IMediaFolder, IMediaItem, IPhotoSelection, MediaService, getMediaSymbol, IMediaAppConfig } from '@christianriedl/media';
|
|
8
|
+
import FileUpload from '../components/FileUpload.vue';
|
|
9
|
+
import PhotoDownload from '../components/PhotoDownload.vue';
|
|
10
|
+
|
|
11
|
+
const appState = inject(appStateSymbol)!;
|
|
12
|
+
const appConfig = inject(appConfigSymbol)!;
|
|
13
|
+
const mediaAppConfig = appConfig as unknown as IMediaAppConfig;
|
|
14
|
+
const getMediaService = inject(getMediaSymbol)!;
|
|
15
|
+
const mediaService = getMediaService();
|
|
16
|
+
const heightStyle = computed<StyleValue>(() => { return { height: appState.bodyHeight.value + 'px', overflowY: 'auto' } });
|
|
17
|
+
const isMobile = appState.isMobile && (appState.device != EDevice.iPad);
|
|
18
|
+
const router = useRouter();
|
|
19
|
+
const open = ref<string[]>([]);
|
|
20
|
+
|
|
21
|
+
const items = ref<IMediaFolder[]>([]);
|
|
22
|
+
const selected = reactive<IPhotoSelection>(mediaService.photoSelection);
|
|
23
|
+
const listHeight = ref(appState.bodyHeight.value);
|
|
24
|
+
const listhead = ref<ComponentPublicInstance|null>(null);
|
|
25
|
+
const table = ref<InstanceType<typeof VDataTableVirtual> | null>(null);
|
|
26
|
+
const uploadVisible = ref(false);
|
|
27
|
+
|
|
28
|
+
const roots: string[] = ['Jahr', 'Orte', 'Ereignisse', 'Personen'];
|
|
29
|
+
const criterias: string[] = ['ye', 'lo', 'ev', 'pe'];
|
|
30
|
+
const groupBy = ref<any>([{key: 'info', order: 'asc'}]);
|
|
31
|
+
const sortBy = ref<any>([{key: 'title', order: 'asc'}]);
|
|
32
|
+
const headers= [
|
|
33
|
+
{ title: 'Title', key: 'title', align: 'start', sortable: false },
|
|
34
|
+
{ title: 'Actions', key: 'actions', sortable: false }
|
|
35
|
+
];
|
|
36
|
+
const grouped = ref(false);
|
|
37
|
+
const backVisible = ref(false);
|
|
38
|
+
const showDownload = ref(false);
|
|
39
|
+
const downloadFolder = ref<IMediaFolder | null>(null);
|
|
40
|
+
const selectedYear = ref<number | undefined>(undefined);
|
|
41
|
+
const selectedName = ref<string | undefined>(undefined);
|
|
42
|
+
|
|
43
|
+
window.addEventListener('popstate', onPopState);
|
|
44
|
+
function onPopState(event: any) {
|
|
45
|
+
if (event.state && event.state.noBackExitsApp && backVisible.value) {
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
listBack();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
onUnmounted(() => {
|
|
51
|
+
window.removeEventListener('popstate', onPopState);
|
|
52
|
+
while (window.history.state && window.history.state.noBackExitsApp)
|
|
53
|
+
window.history.back();
|
|
54
|
+
});
|
|
55
|
+
onMounted(async () => {
|
|
56
|
+
mediaService.log.trace('Photos created');
|
|
57
|
+
const rc = await mediaService.getLists(EMediaType.Picture);
|
|
58
|
+
let root;
|
|
59
|
+
if (!selected.selected.DLNAID) {
|
|
60
|
+
root = await mediaService.initializePhotos(stars(), selected.criteria);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
root = mediaService.folders[selected.selected.DLNAID];
|
|
64
|
+
}
|
|
65
|
+
const folders = setSelected(root);
|
|
66
|
+
if (selected.selectedAlbum)
|
|
67
|
+
selectedYear.value = selected.selectedAlbum.Year;
|
|
68
|
+
const expanded = selected.criteria == 'ye' || root.ItemType == EItemType.PictureCategory;
|
|
69
|
+
setGrouped(folders, expanded, selectedYear.value);
|
|
70
|
+
const scrollTop = appState.scrollPosition.value;
|
|
71
|
+
if (scrollTop > 0 && table.value) {
|
|
72
|
+
nextTick(() => {
|
|
73
|
+
// Scoll to this position
|
|
74
|
+
const el = table.value?._?.vnode?.el;
|
|
75
|
+
el?.scrollTo(0, scrollTop);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
mediaService.log.trace(`Photos start with ${selected.selected.DLNAID} scrollTop: ${scrollTop}`);
|
|
79
|
+
})
|
|
80
|
+
watch(appState.bodyHeight, () => computeListHeight());
|
|
81
|
+
function computeListHeight() {
|
|
82
|
+
nextTick(() => {
|
|
83
|
+
let height = appState.bodyHeight.value;
|
|
84
|
+
if (listhead.value) {
|
|
85
|
+
height = height - (listhead.value.$el as HTMLElement).clientHeight;
|
|
86
|
+
}
|
|
87
|
+
listHeight.value = height;
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
function stars() {
|
|
91
|
+
return selected.rating ? (selected.rating == 1 ? '*' : '**') : 'all';
|
|
92
|
+
}
|
|
93
|
+
function showFolder(folder: IMediaFolder) {
|
|
94
|
+
const folders = setSelected(folder);
|
|
95
|
+
setGrouped(folders, true);
|
|
96
|
+
computeListHeight();
|
|
97
|
+
}
|
|
98
|
+
function listExpand(folder: IMediaFolder) {
|
|
99
|
+
if (folder.Year && folder.Year > 0)
|
|
100
|
+
selectedYear.value = folder.Year;
|
|
101
|
+
}
|
|
102
|
+
function showPictures(folder: IMediaFolder) {
|
|
103
|
+
selected.selectedAlbum = folder;
|
|
104
|
+
router.push({ path: 'photoalbum', query: { id: folder.DLNAID } });
|
|
105
|
+
}
|
|
106
|
+
function onClick(ev: Event, row: any) {
|
|
107
|
+
const folder = row.item.raw as IMediaFolder;
|
|
108
|
+
if (folder.info)
|
|
109
|
+
showPictures(folder);
|
|
110
|
+
else
|
|
111
|
+
showFolder(folder);
|
|
112
|
+
}
|
|
113
|
+
function listBack() {
|
|
114
|
+
const parent = mediaService.folders[selected.selected.DLNAParentID];
|
|
115
|
+
const index = parent.Folders.indexOf(selected.selected);
|
|
116
|
+
const folders = setSelected(parent);
|
|
117
|
+
setGrouped(folders, false);
|
|
118
|
+
}
|
|
119
|
+
function onLightbox(folder: IMediaFolder) {
|
|
120
|
+
selected.selectedAlbum = folder;
|
|
121
|
+
router.push({ path: 'photothumbnails', query: { id: folder.DLNAID } });
|
|
122
|
+
|
|
123
|
+
}
|
|
124
|
+
function onDownload(folder: IMediaFolder) {
|
|
125
|
+
downloadFolder.value = folder;
|
|
126
|
+
showDownload.value = true;
|
|
127
|
+
}
|
|
128
|
+
async function onShare(folder: IMediaFolder) {
|
|
129
|
+
const guid = Helper.generateUUID();
|
|
130
|
+
const url = `https://www.christian-riedl.com/photos?id=${guid}`;
|
|
131
|
+
try {
|
|
132
|
+
await window.navigator.clipboard.writeText(url);
|
|
133
|
+
const id = await mediaService.addPhotoService(guid, appConfig.user, folder.DLNAID, mediaAppConfig.linkDaysValid);
|
|
134
|
+
if (id)
|
|
135
|
+
window.alert(`Created and Pasted - id : ${id} !`);
|
|
136
|
+
else
|
|
137
|
+
window.alert(`Creation failed, please repeat !`);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
window.alert(`Not Pasted : ${err} !`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function onCloseDownload() {
|
|
144
|
+
downloadFolder.value = null;
|
|
145
|
+
showDownload.value = false;
|
|
146
|
+
}
|
|
147
|
+
function onRootChange(root: string) {
|
|
148
|
+
const idx = roots.indexOf(selected.root);
|
|
149
|
+
selected.criteria = criterias[idx];
|
|
150
|
+
selectedName.value = undefined;
|
|
151
|
+
initialize().then((v) => { });;
|
|
152
|
+
}
|
|
153
|
+
function onRating(value: number | string) {
|
|
154
|
+
selected.rating = Number(value);
|
|
155
|
+
initialize().then((v) => { });;
|
|
156
|
+
}
|
|
157
|
+
async function initialize(): Promise<boolean> {
|
|
158
|
+
let root = await mediaService.initializePhotos(stars(), selected.criteria);
|
|
159
|
+
let expanded = selected.criteria == 'ye';
|
|
160
|
+
if (selected.criteria != 'ye' && selectedName.value) {
|
|
161
|
+
for (let i = 0; i < root.Folders.length; i++) {
|
|
162
|
+
if (root.Folders[i].Name == selectedName.value) {
|
|
163
|
+
root = root.Folders[i];
|
|
164
|
+
expanded = true;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const folders = setSelected(root);
|
|
170
|
+
setGrouped(folders, expanded, selectedYear.value);
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
function setSelected(folder: IMediaFolder) : IMediaFolder[] {
|
|
174
|
+
selected.selected = folder;
|
|
175
|
+
if (folder.Year && folder.Year > 0)
|
|
176
|
+
selectedYear.value = folder.Year;
|
|
177
|
+
selectedName.value = folder.Name;
|
|
178
|
+
backVisible.value = selected.selected.ItemType != EItemType.PictureGenreType;
|
|
179
|
+
|
|
180
|
+
// calculate list height
|
|
181
|
+
computeListHeight();
|
|
182
|
+
return folder.Folders;
|
|
183
|
+
}
|
|
184
|
+
function setGrouped(folders: IMediaFolder[], expand: boolean, year?: number) {
|
|
185
|
+
grouped.value = expand;
|
|
186
|
+
groupBy.value = expand ? [{key: 'info', order: 'asc'}] : [];
|
|
187
|
+
const expanded = (expand && folders.length <= 6) ? true : false;
|
|
188
|
+
const list: IMediaFolder[] = [];
|
|
189
|
+
for (let i = 0; i < folders.length; i++) {
|
|
190
|
+
let folder = folders[i];
|
|
191
|
+
if (expand) {
|
|
192
|
+
if (year && year == folder.Year) {
|
|
193
|
+
open.value.push(year.toString());
|
|
194
|
+
}
|
|
195
|
+
for (let j = 0; j < folder.Folders.length; j++) {
|
|
196
|
+
const item = folder.Folders[j];
|
|
197
|
+
item.info = folder.title;
|
|
198
|
+
list.push(item);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
folder.info = undefined;
|
|
203
|
+
list.push(folder);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
items.value = list;
|
|
207
|
+
}
|
|
208
|
+
function onScroll(ev: Event) {
|
|
209
|
+
const scrollTop = (ev.target as Element).scrollTop;
|
|
210
|
+
appState.scrollPosition.value = scrollTop;
|
|
211
|
+
}
|
|
212
|
+
function setGroupFunc(toggle:any) : string {
|
|
213
|
+
return "";
|
|
214
|
+
}
|
|
215
|
+
</script>
|
|
216
|
+
<template>
|
|
217
|
+
<v-card ref="listhead" class="bg-media_head">
|
|
218
|
+
<v-card-title>{{selected.selected.Name}}</v-card-title>
|
|
219
|
+
<v-card-actions>
|
|
220
|
+
<v-btn v-if="backVisible" @click="listBack">
|
|
221
|
+
<v-icon size="large" icon="$back" />
|
|
222
|
+
</v-btn>
|
|
223
|
+
<v-rating clearable length="2" v-model="selected.rating" @update:modelValue="onRating" />
|
|
224
|
+
<v-select v-model="selected.root"
|
|
225
|
+
:items="roots"
|
|
226
|
+
persistent-hint
|
|
227
|
+
@update:modelValue="onRootChange"
|
|
228
|
+
hide-details single-line>
|
|
229
|
+
</v-select>
|
|
230
|
+
<v-btn v-if="!isMobile" @click="uploadVisible = !uploadVisible">
|
|
231
|
+
UPLOAD
|
|
232
|
+
<v-icon icon="$upload" />
|
|
233
|
+
</v-btn>
|
|
234
|
+
</v-card-actions>
|
|
235
|
+
</v-card>
|
|
236
|
+
<file-upload v-if="uploadVisible" accept="image/jpeg"></file-upload>
|
|
237
|
+
<v-data-table-virtual ref="table" :group-by="groupBy" :sort-by="sortBy" :items="items" :headers="headers" class="elevation-1" item-value="title" :height="listHeight"
|
|
238
|
+
@click:row="onClick" v-scroll.self="onScroll">
|
|
239
|
+
<template v-slot:top="{ toggleGroup, isGroupOpen }">
|
|
240
|
+
<p style="display:none">{{setGroupFunc(toggleGroup)}}</p>
|
|
241
|
+
</template>
|
|
242
|
+
<template v-slot:item.actions="{ item }">
|
|
243
|
+
<div v-if="item.raw.info">
|
|
244
|
+
<v-icon size="small" icon="$share" @click="onShare(item.raw)"></v-icon>
|
|
245
|
+
<v-icon size="small" icon="$download" @click="onDownload(item.raw)"></v-icon>
|
|
246
|
+
<v-icon size="small" icon="$grid" @click="onLightbox(item.raw)"></v-icon>
|
|
247
|
+
</div>
|
|
248
|
+
</template>
|
|
249
|
+
</v-data-table-virtual>
|
|
250
|
+
<!--
|
|
251
|
+
<v-card :max-height="listHeight" class="overflow-y-auto bg-media" ref="scrollElement" v-scroll.self="onScroll">
|
|
252
|
+
<v-data-table-virtual ref="table" :group-by="groupBy" :items="items" :headers="headers" class="elevation-1" item-value="title" :height="listHeight" @click:row="onClick">
|
|
253
|
+
<template v-slot:item.actions="{ item }">
|
|
254
|
+
<v-icon size="small" icon="$share" @click="onShare(item.raw)"></v-icon>
|
|
255
|
+
<v-icon size="small" icon="$download" @click="onDownload(item.raw)"></v-icon>
|
|
256
|
+
<v-icon size="small" icon="$grid" @click="onLightbox(item.raw)"></v-icon>
|
|
257
|
+
</template>
|
|
258
|
+
</v-data-table-virtual>
|
|
259
|
+
<!-
|
|
260
|
+
<v-list v-if="!grouped">
|
|
261
|
+
<v-list-item v-for="item in items" :key="item.DLNAID" :title="item.info" density="compact" @click.stop="showFolder(item)">
|
|
262
|
+
</v-list-item>
|
|
263
|
+
</v-list>
|
|
264
|
+
<v-list v-else v-model:opened="open">
|
|
265
|
+
<v-list-group v-for="item in items" :key="item.DLNAID" :value="item.Name" @click.stop="listExpand(item)">
|
|
266
|
+
<template v-slot:activator="{ props }">
|
|
267
|
+
<v-list-item v-bind="props" :title="item.info" :value="item.info" density="compact"></v-list-item>
|
|
268
|
+
</template>
|
|
269
|
+
<v-list-item v-for="subItem in item.Folders" :key="subItem.DLNAID" :title="subItem.info" density="compact" @click.stop="showPictures(subItem)">
|
|
270
|
+
<template v-slot:append>
|
|
271
|
+
<v-btn color="grey" variant="tonal" icon="$share" @click.stop.prevent="onShare(subItem)"></v-btn>
|
|
272
|
+
<v-btn color="grey" variant="tonal" icon="$download" @click.stop.prevent="onDownload(subItem)"></v-btn>
|
|
273
|
+
<v-btn color="grey" variant="tonal" icon="$grid" @click.stop.prevent="onLightbox(subItem)"></v-btn>
|
|
274
|
+
</template>
|
|
275
|
+
</v-list-item>
|
|
276
|
+
</v-list-group>
|
|
277
|
+
</v-list>
|
|
278
|
+
->
|
|
279
|
+
</v-card>
|
|
280
|
+
-->
|
|
281
|
+
|
|
282
|
+
<v-dialog v-model="showDownload">
|
|
283
|
+
<photo-download :folder="downloadFolder!" v-click-outside="onCloseDownload" @close="onCloseDownload"></photo-download>
|
|
284
|
+
</v-dialog>
|
|
285
|
+
</template>
|
|
286
|
+
|