retold-remote 0.0.5 → 0.0.7
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/css/retold-remote.css +3 -0
- package/docs/README.md +181 -0
- package/docs/_cover.md +14 -0
- package/docs/_sidebar.md +10 -0
- package/docs/_topbar.md +3 -0
- package/docs/audio-viewer.md +133 -0
- package/docs/ebook-reader.md +90 -0
- package/docs/image-viewer.md +90 -0
- package/docs/server-setup.md +262 -0
- package/docs/video-viewer.md +134 -0
- package/html/docs.html +59 -0
- package/html/index.html +1 -1
- package/package.json +20 -6
- package/source/Pict-Application-RetoldRemote.js +122 -2
- package/source/RetoldRemote-ExtensionMaps.js +33 -0
- package/source/cli/RetoldRemote-Server-Setup.js +211 -67
- package/source/cli/commands/RetoldRemote-Command-Serve.js +5 -26
- package/source/providers/Pict-Provider-AISortManager.js +456 -0
- package/source/providers/Pict-Provider-CollectionManager.js +1200 -0
- package/source/providers/Pict-Provider-FormattingUtilities.js +109 -0
- package/source/providers/Pict-Provider-GalleryFilterSort.js +2 -11
- package/source/providers/Pict-Provider-GalleryNavigation.js +187 -409
- package/source/providers/Pict-Provider-RetoldRemoteIcons.js +52 -0
- package/source/providers/Pict-Provider-ToastNotification.js +96 -0
- package/source/providers/keyboard-handlers/KeyHandler-AudioExplorer.js +88 -0
- package/source/providers/keyboard-handlers/KeyHandler-Gallery.js +190 -0
- package/source/providers/keyboard-handlers/KeyHandler-Sidebar.js +65 -0
- package/source/providers/keyboard-handlers/KeyHandler-VideoExplorer.js +57 -0
- package/source/providers/keyboard-handlers/KeyHandler-Viewer.js +197 -0
- package/source/server/RetoldRemote-AISortService.js +879 -0
- package/source/server/RetoldRemote-ArchiveService.js +2 -12
- package/source/server/RetoldRemote-AudioWaveformService.js +7 -16
- package/source/server/RetoldRemote-CollectionService.js +843 -0
- package/source/server/RetoldRemote-EbookService.js +7 -16
- package/source/server/RetoldRemote-FileOperationService.js +560 -0
- package/source/server/RetoldRemote-MediaService.js +15 -14
- package/source/server/RetoldRemote-MetadataCache.js +411 -0
- package/source/server/RetoldRemote-ParimeCache.js +349 -0
- package/source/server/RetoldRemote-ThumbnailCache.js +52 -20
- package/source/server/RetoldRemote-VideoFrameService.js +7 -15
- package/source/views/PictView-Remote-AudioExplorer.js +10 -43
- package/source/views/PictView-Remote-CollectionsPanel.js +1486 -0
- package/source/views/PictView-Remote-Gallery.js +237 -44
- package/source/views/PictView-Remote-ImageViewer.js +1 -34
- package/source/views/PictView-Remote-Layout.js +411 -20
- package/source/views/PictView-Remote-MediaViewer.js +311 -28
- package/source/views/PictView-Remote-SettingsPanel.js +275 -133
- package/source/views/PictView-Remote-TopBar.js +701 -14
- package/source/views/PictView-Remote-VLCSetup.js +8 -39
- package/source/views/PictView-Remote-VideoExplorer.js +20 -54
- package/web-application/css/docuserve.css +73 -0
- package/web-application/css/retold-remote.css +3 -0
- package/web-application/docs/README.md +181 -0
- package/web-application/docs/_cover.md +14 -0
- package/web-application/docs/_sidebar.md +10 -0
- package/web-application/docs/_topbar.md +3 -0
- package/web-application/docs/audio-viewer.md +133 -0
- package/web-application/docs/ebook-reader.md +90 -0
- package/web-application/docs/image-viewer.md +90 -0
- package/web-application/docs/server-setup.md +262 -0
- package/web-application/docs/video-viewer.md +134 -0
- package/web-application/docs.html +59 -0
- package/web-application/index.html +1 -1
- package/web-application/js/pict-docuserve.min.js +58 -0
- package/web-application/js/pict.min.js +2 -2
- package/web-application/js/pict.min.js.map +1 -1
- package/web-application/retold-remote.js +2652 -970
- package/web-application/retold-remote.js.map +1 -1
- package/web-application/retold-remote.min.js +60 -13
- package/web-application/retold-remote.min.js.map +1 -1
- package/server.js +0 -43
|
@@ -20,22 +20,76 @@ const _ViewConfiguration =
|
|
|
20
20
|
border-bottom: 1px solid var(--retold-border);
|
|
21
21
|
gap: 16px;
|
|
22
22
|
}
|
|
23
|
-
.retold-remote-topbar-
|
|
23
|
+
.retold-remote-topbar-sidebar-toggle
|
|
24
24
|
{
|
|
25
|
-
font-size: 0.85rem;
|
|
26
|
-
font-weight: 700;
|
|
27
|
-
color: var(--retold-accent);
|
|
28
25
|
flex-shrink: 0;
|
|
26
|
+
display: inline-flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
width: 32px;
|
|
30
|
+
height: 32px;
|
|
31
|
+
padding: 0;
|
|
32
|
+
margin: 0;
|
|
33
|
+
border: 1px solid var(--retold-border);
|
|
34
|
+
border-radius: 4px;
|
|
35
|
+
background: transparent;
|
|
36
|
+
color: var(--retold-text-muted);
|
|
37
|
+
font-size: 1rem;
|
|
38
|
+
line-height: 1;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
|
41
|
+
font-family: inherit;
|
|
42
|
+
-webkit-tap-highlight-color: transparent;
|
|
43
|
+
}
|
|
44
|
+
.retold-remote-topbar-sidebar-toggle:hover,
|
|
45
|
+
.retold-remote-topbar-sidebar-toggle:active,
|
|
46
|
+
.retold-remote-topbar-df-toggle:hover,
|
|
47
|
+
.retold-remote-topbar-df-toggle:active
|
|
48
|
+
{
|
|
49
|
+
color: var(--retold-text-primary);
|
|
50
|
+
border-color: var(--retold-accent);
|
|
51
|
+
background: rgba(128, 128, 128, 0.1);
|
|
52
|
+
}
|
|
53
|
+
.retold-remote-topbar-df-toggle
|
|
54
|
+
{
|
|
55
|
+
flex-shrink: 0;
|
|
56
|
+
display: inline-flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
justify-content: center;
|
|
59
|
+
width: 32px;
|
|
60
|
+
height: 32px;
|
|
61
|
+
padding: 0;
|
|
62
|
+
margin: 0;
|
|
63
|
+
border: 1px solid var(--retold-border);
|
|
64
|
+
border-radius: 4px;
|
|
65
|
+
background: transparent;
|
|
66
|
+
color: var(--retold-text-muted);
|
|
67
|
+
font-size: 1rem;
|
|
68
|
+
line-height: 1;
|
|
69
|
+
cursor: pointer;
|
|
70
|
+
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
|
71
|
+
font-family: inherit;
|
|
72
|
+
-webkit-tap-highlight-color: transparent;
|
|
29
73
|
}
|
|
30
74
|
.retold-remote-topbar-location
|
|
31
75
|
{
|
|
76
|
+
position: relative;
|
|
32
77
|
flex: 1;
|
|
33
78
|
font-size: 0.82rem;
|
|
34
79
|
color: var(--retold-text-muted);
|
|
80
|
+
white-space: nowrap;
|
|
81
|
+
text-align: center;
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
justify-content: center;
|
|
85
|
+
overflow: visible;
|
|
86
|
+
min-width: 0;
|
|
87
|
+
}
|
|
88
|
+
.retold-remote-topbar-location-inner
|
|
89
|
+
{
|
|
35
90
|
overflow: hidden;
|
|
36
91
|
text-overflow: ellipsis;
|
|
37
92
|
white-space: nowrap;
|
|
38
|
-
text-align: center;
|
|
39
93
|
}
|
|
40
94
|
.retold-remote-topbar-location-crumb
|
|
41
95
|
{
|
|
@@ -47,11 +101,120 @@ const _ViewConfiguration =
|
|
|
47
101
|
{
|
|
48
102
|
text-decoration: underline;
|
|
49
103
|
}
|
|
104
|
+
.retold-remote-topbar-home-crumb
|
|
105
|
+
{
|
|
106
|
+
cursor: pointer;
|
|
107
|
+
display: inline-flex;
|
|
108
|
+
align-items: center;
|
|
109
|
+
vertical-align: middle;
|
|
110
|
+
opacity: 0.8;
|
|
111
|
+
}
|
|
112
|
+
.retold-remote-topbar-home-crumb:hover
|
|
113
|
+
{
|
|
114
|
+
opacity: 1;
|
|
115
|
+
}
|
|
50
116
|
.retold-remote-topbar-sep
|
|
51
117
|
{
|
|
52
118
|
color: var(--retold-text-placeholder);
|
|
53
119
|
margin: 0 3px;
|
|
54
120
|
}
|
|
121
|
+
/* Breadcrumb overflow hamburger */
|
|
122
|
+
.retold-remote-topbar-breadcrumb-overflow
|
|
123
|
+
{
|
|
124
|
+
position: relative;
|
|
125
|
+
display: inline-flex;
|
|
126
|
+
align-items: center;
|
|
127
|
+
vertical-align: middle;
|
|
128
|
+
}
|
|
129
|
+
.retold-remote-topbar-overflow-btn
|
|
130
|
+
{
|
|
131
|
+
display: inline-flex;
|
|
132
|
+
align-items: center;
|
|
133
|
+
justify-content: center;
|
|
134
|
+
width: 28px;
|
|
135
|
+
height: 28px;
|
|
136
|
+
padding: 0;
|
|
137
|
+
margin: 0;
|
|
138
|
+
border: 1px solid var(--retold-border);
|
|
139
|
+
border-radius: 4px;
|
|
140
|
+
background: transparent;
|
|
141
|
+
color: var(--retold-text-muted);
|
|
142
|
+
font-size: 0.9rem;
|
|
143
|
+
line-height: 1;
|
|
144
|
+
cursor: pointer;
|
|
145
|
+
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
|
146
|
+
font-family: inherit;
|
|
147
|
+
-webkit-tap-highlight-color: transparent;
|
|
148
|
+
}
|
|
149
|
+
.retold-remote-topbar-overflow-btn:hover,
|
|
150
|
+
.retold-remote-topbar-overflow-btn:active
|
|
151
|
+
{
|
|
152
|
+
color: var(--retold-text-primary);
|
|
153
|
+
border-color: var(--retold-accent);
|
|
154
|
+
background: rgba(128, 128, 128, 0.1);
|
|
155
|
+
}
|
|
156
|
+
.retold-remote-topbar-overflow-dropdown
|
|
157
|
+
{
|
|
158
|
+
display: none;
|
|
159
|
+
position: absolute;
|
|
160
|
+
top: 100%;
|
|
161
|
+
left: 0;
|
|
162
|
+
margin-top: 4px;
|
|
163
|
+
min-width: 200px;
|
|
164
|
+
max-width: 300px;
|
|
165
|
+
background: var(--retold-bg-secondary);
|
|
166
|
+
border: 1px solid var(--retold-border);
|
|
167
|
+
border-radius: 6px;
|
|
168
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
|
169
|
+
z-index: 1000;
|
|
170
|
+
overflow: hidden;
|
|
171
|
+
}
|
|
172
|
+
.retold-remote-topbar-overflow-dropdown.open
|
|
173
|
+
{
|
|
174
|
+
display: block;
|
|
175
|
+
}
|
|
176
|
+
.retold-remote-topbar-overflow-item
|
|
177
|
+
{
|
|
178
|
+
display: flex;
|
|
179
|
+
align-items: center;
|
|
180
|
+
gap: 8px;
|
|
181
|
+
width: 100%;
|
|
182
|
+
padding: 12px 16px;
|
|
183
|
+
border: none;
|
|
184
|
+
border-bottom: 1px solid var(--retold-border);
|
|
185
|
+
background: transparent;
|
|
186
|
+
color: var(--retold-text-primary);
|
|
187
|
+
font-size: 0.9rem;
|
|
188
|
+
text-align: left;
|
|
189
|
+
cursor: pointer;
|
|
190
|
+
font-family: inherit;
|
|
191
|
+
-webkit-tap-highlight-color: transparent;
|
|
192
|
+
min-height: 44px;
|
|
193
|
+
box-sizing: border-box;
|
|
194
|
+
}
|
|
195
|
+
.retold-remote-topbar-overflow-item:last-child
|
|
196
|
+
{
|
|
197
|
+
border-bottom: none;
|
|
198
|
+
}
|
|
199
|
+
.retold-remote-topbar-overflow-item:hover,
|
|
200
|
+
.retold-remote-topbar-overflow-item:active
|
|
201
|
+
{
|
|
202
|
+
background: rgba(128, 128, 128, 0.12);
|
|
203
|
+
color: var(--retold-accent);
|
|
204
|
+
}
|
|
205
|
+
.retold-remote-topbar-overflow-item-icon
|
|
206
|
+
{
|
|
207
|
+
display: inline-flex;
|
|
208
|
+
align-items: center;
|
|
209
|
+
flex-shrink: 0;
|
|
210
|
+
opacity: 0.7;
|
|
211
|
+
}
|
|
212
|
+
.retold-remote-topbar-overflow-item-label
|
|
213
|
+
{
|
|
214
|
+
overflow: hidden;
|
|
215
|
+
text-overflow: ellipsis;
|
|
216
|
+
white-space: nowrap;
|
|
217
|
+
}
|
|
55
218
|
.retold-remote-topbar-info
|
|
56
219
|
{
|
|
57
220
|
flex-shrink: 0;
|
|
@@ -81,6 +244,64 @@ const _ViewConfiguration =
|
|
|
81
244
|
color: var(--retold-text-primary);
|
|
82
245
|
border-color: var(--retold-accent);
|
|
83
246
|
}
|
|
247
|
+
.retold-remote-topbar-addcoll-btn
|
|
248
|
+
{
|
|
249
|
+
font-size: 0.72rem;
|
|
250
|
+
}
|
|
251
|
+
.retold-remote-topbar-collections-btn.panel-open
|
|
252
|
+
{
|
|
253
|
+
color: var(--retold-accent);
|
|
254
|
+
border-color: var(--retold-accent);
|
|
255
|
+
background: rgba(128, 128, 128, 0.1);
|
|
256
|
+
}
|
|
257
|
+
/* Add-to-collection dropdown */
|
|
258
|
+
.retold-remote-addcoll-dropdown
|
|
259
|
+
{
|
|
260
|
+
position: absolute;
|
|
261
|
+
top: 100%;
|
|
262
|
+
right: 0;
|
|
263
|
+
margin-top: 4px;
|
|
264
|
+
min-width: 220px;
|
|
265
|
+
max-width: 320px;
|
|
266
|
+
max-height: 300px;
|
|
267
|
+
overflow-y: auto;
|
|
268
|
+
background: var(--retold-bg-secondary);
|
|
269
|
+
border: 1px solid var(--retold-border);
|
|
270
|
+
border-radius: 6px;
|
|
271
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
|
272
|
+
z-index: 1000;
|
|
273
|
+
}
|
|
274
|
+
.retold-remote-addcoll-dropdown-item
|
|
275
|
+
{
|
|
276
|
+
display: flex;
|
|
277
|
+
align-items: center;
|
|
278
|
+
gap: 8px;
|
|
279
|
+
width: 100%;
|
|
280
|
+
padding: 10px 14px;
|
|
281
|
+
border: none;
|
|
282
|
+
border-bottom: 1px solid var(--retold-border);
|
|
283
|
+
background: transparent;
|
|
284
|
+
color: var(--retold-text-primary);
|
|
285
|
+
font-size: 0.82rem;
|
|
286
|
+
text-align: left;
|
|
287
|
+
cursor: pointer;
|
|
288
|
+
font-family: inherit;
|
|
289
|
+
box-sizing: border-box;
|
|
290
|
+
}
|
|
291
|
+
.retold-remote-addcoll-dropdown-item:last-child
|
|
292
|
+
{
|
|
293
|
+
border-bottom: none;
|
|
294
|
+
}
|
|
295
|
+
.retold-remote-addcoll-dropdown-item:hover
|
|
296
|
+
{
|
|
297
|
+
background: rgba(128, 128, 128, 0.12);
|
|
298
|
+
color: var(--retold-accent);
|
|
299
|
+
}
|
|
300
|
+
.retold-remote-addcoll-dropdown-new
|
|
301
|
+
{
|
|
302
|
+
color: var(--retold-accent);
|
|
303
|
+
font-weight: 500;
|
|
304
|
+
}
|
|
84
305
|
.retold-remote-topbar-filter-btn
|
|
85
306
|
{
|
|
86
307
|
position: relative;
|
|
@@ -112,6 +333,31 @@ const _ViewConfiguration =
|
|
|
112
333
|
border-color: var(--retold-text-muted);
|
|
113
334
|
background: rgba(128, 128, 128, 0.06);
|
|
114
335
|
}
|
|
336
|
+
.retold-remote-topbar-aisort-btn
|
|
337
|
+
{
|
|
338
|
+
padding: 4px 8px;
|
|
339
|
+
border: 1px solid var(--retold-border);
|
|
340
|
+
border-radius: 3px;
|
|
341
|
+
background: transparent;
|
|
342
|
+
color: var(--retold-text-muted);
|
|
343
|
+
font-size: 0.72rem;
|
|
344
|
+
cursor: pointer;
|
|
345
|
+
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
|
346
|
+
font-family: inherit;
|
|
347
|
+
white-space: nowrap;
|
|
348
|
+
}
|
|
349
|
+
.retold-remote-topbar-aisort-btn:hover
|
|
350
|
+
{
|
|
351
|
+
color: var(--retold-text-primary);
|
|
352
|
+
border-color: var(--retold-accent);
|
|
353
|
+
background: rgba(128, 128, 128, 0.1);
|
|
354
|
+
}
|
|
355
|
+
.retold-remote-topbar-aisort-btn.generating
|
|
356
|
+
{
|
|
357
|
+
color: var(--retold-accent);
|
|
358
|
+
border-color: var(--retold-accent);
|
|
359
|
+
cursor: wait;
|
|
360
|
+
}
|
|
115
361
|
.retold-remote-topbar-filter-badge
|
|
116
362
|
{
|
|
117
363
|
position: absolute;
|
|
@@ -136,12 +382,15 @@ const _ViewConfiguration =
|
|
|
136
382
|
Hash: "RetoldRemote-TopBar",
|
|
137
383
|
Template: /*html*/`
|
|
138
384
|
<div class="retold-remote-topbar">
|
|
139
|
-
<
|
|
385
|
+
<button class="retold-remote-topbar-sidebar-toggle" id="RetoldRemote-TopBar-SidebarToggle" onclick="pict.views['ContentEditor-Layout'].toggleSidebar()" title="Toggle Sidebar"></button>
|
|
386
|
+
<button class="retold-remote-topbar-df-toggle" id="RetoldRemote-TopBar-DFToggle" onclick="pict.views['ContentEditor-TopBar'].toggleDistractionFree()" title="Distraction-free mode (d)"></button>
|
|
140
387
|
<div class="retold-remote-topbar-location" id="RetoldRemote-TopBar-Location"></div>
|
|
141
388
|
<div class="retold-remote-topbar-info" id="RetoldRemote-TopBar-Info"></div>
|
|
142
389
|
<div class="retold-remote-topbar-actions">
|
|
390
|
+
<button class="retold-remote-topbar-aisort-btn" id="RetoldRemote-TopBar-AISortBtn" onclick="pict.views['ContentEditor-TopBar'].triggerAISort()" title="AI Sort (generate sort plan for current folder)" style="display:none;">AI Sort</button>
|
|
391
|
+
<button class="retold-remote-topbar-btn retold-remote-topbar-addcoll-btn" id="RetoldRemote-TopBar-AddToCollectionBtn" onclick="pict.views['ContentEditor-TopBar'].addToCollection(event)" title="Add to collection">+★</button>
|
|
392
|
+
<button class="retold-remote-topbar-sidebar-toggle retold-remote-topbar-collections-btn" id="RetoldRemote-TopBar-CollectionsBtn" onclick="pict.views['ContentEditor-TopBar'].toggleCollections()" title="Toggle Collections panel (b)">★</button>
|
|
143
393
|
<button class="retold-remote-topbar-filter-btn" id="RetoldRemote-TopBar-FilterBtn" onclick="pict.views['ContentEditor-TopBar'].toggleFilterBar()" title="Toggle filter bar (/)">◢</button>
|
|
144
|
-
<button class="retold-remote-topbar-btn" onclick="pict.views['ContentEditor-Layout'].toggleSidebar()" title="Toggle Sidebar">☰</button>
|
|
145
394
|
</div>
|
|
146
395
|
</div>
|
|
147
396
|
`
|
|
@@ -168,12 +417,73 @@ class RetoldRemoteTopBarView extends libPictView
|
|
|
168
417
|
onAfterRender()
|
|
169
418
|
{
|
|
170
419
|
super.onAfterRender();
|
|
420
|
+
this.updateSidebarToggleIcon();
|
|
421
|
+
this.updateDFToggleIcon();
|
|
171
422
|
this.updateLocation();
|
|
172
423
|
this.updateInfo();
|
|
173
424
|
}
|
|
174
425
|
|
|
426
|
+
/**
|
|
427
|
+
* Inject the SVG sidebar icon into the sidebar toggle button.
|
|
428
|
+
*/
|
|
429
|
+
updateSidebarToggleIcon()
|
|
430
|
+
{
|
|
431
|
+
let tmpBtn = document.getElementById('RetoldRemote-TopBar-SidebarToggle');
|
|
432
|
+
if (!tmpBtn)
|
|
433
|
+
{
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
let tmpIconProvider = this.pict.providers['RetoldRemote-Icons'];
|
|
438
|
+
if (tmpIconProvider)
|
|
439
|
+
{
|
|
440
|
+
tmpBtn.innerHTML = tmpIconProvider.getIcon('sidebar', 18);
|
|
441
|
+
}
|
|
442
|
+
else
|
|
443
|
+
{
|
|
444
|
+
tmpBtn.innerHTML = '☰';
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Inject the SVG expand icon into the distraction-free toggle button.
|
|
450
|
+
*/
|
|
451
|
+
updateDFToggleIcon()
|
|
452
|
+
{
|
|
453
|
+
let tmpBtn = document.getElementById('RetoldRemote-TopBar-DFToggle');
|
|
454
|
+
if (!tmpBtn)
|
|
455
|
+
{
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Four-corner expand icon
|
|
460
|
+
tmpBtn.innerHTML = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">'
|
|
461
|
+
+ '<polyline points="15 3 21 3 21 9" />'
|
|
462
|
+
+ '<polyline points="9 21 3 21 3 15" />'
|
|
463
|
+
+ '<polyline points="21 15 21 21 15 21" />'
|
|
464
|
+
+ '<polyline points="3 9 3 3 9 3" />'
|
|
465
|
+
+ '</svg>';
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Toggle distraction-free mode via the GalleryNavigation provider.
|
|
470
|
+
*/
|
|
471
|
+
toggleDistractionFree()
|
|
472
|
+
{
|
|
473
|
+
let tmpNav = this.pict.providers['RetoldRemote-GalleryNavigation'];
|
|
474
|
+
if (tmpNav && tmpNav._toggleDistractionFree)
|
|
475
|
+
{
|
|
476
|
+
tmpNav._toggleDistractionFree();
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
175
480
|
/**
|
|
176
481
|
* Update the breadcrumb location display.
|
|
482
|
+
*
|
|
483
|
+
* When more than one folder deep, shows a hamburger button to the
|
|
484
|
+
* left of the home icon with a dropdown listing the intermediate
|
|
485
|
+
* path segments. The breadcrumb itself shows only
|
|
486
|
+
* [home] / [current folder].
|
|
177
487
|
*/
|
|
178
488
|
updateLocation()
|
|
179
489
|
{
|
|
@@ -186,25 +496,149 @@ class RetoldRemoteTopBarView extends libPictView
|
|
|
186
496
|
let tmpRemote = this.pict.AppData.RetoldRemote;
|
|
187
497
|
let tmpCurrentLocation = (this.pict.AppData.PictFileBrowser && this.pict.AppData.PictFileBrowser.CurrentLocation) || '';
|
|
188
498
|
|
|
499
|
+
// Build the home icon for the root crumb
|
|
500
|
+
let tmpIconProvider = this.pict.providers['RetoldRemote-Icons'];
|
|
501
|
+
let tmpHomeIcon = tmpIconProvider ? tmpIconProvider.getIcon('home', 16) : '/';
|
|
502
|
+
let tmpHomeCrumb = '<span class="retold-remote-topbar-home-crumb" onclick="pict.PictApplication.loadFileList(\'\')" title="Home">' + tmpHomeIcon + '</span>';
|
|
503
|
+
|
|
189
504
|
if (!tmpCurrentLocation)
|
|
190
505
|
{
|
|
191
|
-
tmpLocationEl.innerHTML = '<span class="retold-remote-topbar-location-
|
|
506
|
+
tmpLocationEl.innerHTML = '<span class="retold-remote-topbar-location-inner">' + tmpHomeCrumb + '</span>';
|
|
192
507
|
return;
|
|
193
508
|
}
|
|
194
509
|
|
|
195
510
|
let tmpParts = tmpCurrentLocation.split('/').filter((p) => p);
|
|
196
|
-
let tmpHTML = '<span class="retold-remote-topbar-location-crumb" onclick="pict.PictApplication.loadFileList(\'\')">/</span>';
|
|
197
511
|
|
|
198
|
-
|
|
512
|
+
// Shallow path (1 level): home / folder — no hamburger needed
|
|
513
|
+
if (tmpParts.length <= 1)
|
|
514
|
+
{
|
|
515
|
+
let tmpInner = tmpHomeCrumb;
|
|
516
|
+
for (let i = 0; i < tmpParts.length; i++)
|
|
517
|
+
{
|
|
518
|
+
let tmpPath = tmpParts.slice(0, i + 1).join('/');
|
|
519
|
+
tmpInner += '<span class="retold-remote-topbar-sep">/</span>';
|
|
520
|
+
tmpInner += '<span class="retold-remote-topbar-location-crumb" onclick="pict.PictApplication.loadFileList(\'' + tmpPath + '\')">' + tmpParts[i] + '</span>';
|
|
521
|
+
}
|
|
522
|
+
tmpLocationEl.innerHTML = '<span class="retold-remote-topbar-location-inner">' + tmpInner + '</span>';
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Deep path (2+ levels): show hamburger with intermediate folders
|
|
527
|
+
let tmpFolderIcon = tmpIconProvider ? tmpIconProvider.getIcon('folder', 16) : '';
|
|
528
|
+
let tmpHomeIconSmall = tmpIconProvider ? tmpIconProvider.getIcon('home', 16) : '/';
|
|
529
|
+
|
|
530
|
+
// Build dropdown items: home first, then each intermediate folder
|
|
531
|
+
let tmpDropdownHTML = '';
|
|
532
|
+
|
|
533
|
+
// Home item
|
|
534
|
+
tmpDropdownHTML += '<button class="retold-remote-topbar-overflow-item" onclick="pict.PictApplication.loadFileList(\'\'); pict.views[\'ContentEditor-TopBar\'].closeBreadcrumbDropdown();">';
|
|
535
|
+
tmpDropdownHTML += '<span class="retold-remote-topbar-overflow-item-icon">' + tmpHomeIconSmall + '</span>';
|
|
536
|
+
tmpDropdownHTML += '<span class="retold-remote-topbar-overflow-item-label">Home</span>';
|
|
537
|
+
tmpDropdownHTML += '</button>';
|
|
538
|
+
|
|
539
|
+
// Intermediate folders (all except the last segment, which is shown in the breadcrumb)
|
|
540
|
+
for (let i = 0; i < tmpParts.length - 1; i++)
|
|
199
541
|
{
|
|
200
542
|
let tmpPath = tmpParts.slice(0, i + 1).join('/');
|
|
201
|
-
|
|
202
|
-
|
|
543
|
+
tmpDropdownHTML += '<button class="retold-remote-topbar-overflow-item" onclick="pict.PictApplication.loadFileList(\'' + tmpPath + '\'); pict.views[\'ContentEditor-TopBar\'].closeBreadcrumbDropdown();">';
|
|
544
|
+
tmpDropdownHTML += '<span class="retold-remote-topbar-overflow-item-icon">' + tmpFolderIcon + '</span>';
|
|
545
|
+
tmpDropdownHTML += '<span class="retold-remote-topbar-overflow-item-label">' + tmpParts[i] + '</span>';
|
|
546
|
+
tmpDropdownHTML += '</button>';
|
|
203
547
|
}
|
|
204
548
|
|
|
549
|
+
// Assemble: [hamburger + dropdown] [inner: home / current folder]
|
|
550
|
+
let tmpLastPart = tmpParts[tmpParts.length - 1];
|
|
551
|
+
let tmpLastPath = tmpParts.join('/');
|
|
552
|
+
|
|
553
|
+
let tmpHTML = '';
|
|
554
|
+
// The overflow wrapper sits outside the truncation inner
|
|
555
|
+
tmpHTML += '<span class="retold-remote-topbar-breadcrumb-overflow">';
|
|
556
|
+
tmpHTML += '<button class="retold-remote-topbar-overflow-btn" onclick="pict.views[\'ContentEditor-TopBar\'].toggleBreadcrumbDropdown()" title="Navigate to parent folders">☰</button>';
|
|
557
|
+
tmpHTML += '<div class="retold-remote-topbar-overflow-dropdown" id="RetoldRemote-BreadcrumbDropdown">';
|
|
558
|
+
tmpHTML += tmpDropdownHTML;
|
|
559
|
+
tmpHTML += '</div>';
|
|
560
|
+
tmpHTML += '</span>';
|
|
561
|
+
// The visible crumbs: home / current-folder
|
|
562
|
+
tmpHTML += '<span class="retold-remote-topbar-location-inner">';
|
|
563
|
+
tmpHTML += tmpHomeCrumb;
|
|
564
|
+
tmpHTML += '<span class="retold-remote-topbar-sep">/</span>';
|
|
565
|
+
tmpHTML += '<span class="retold-remote-topbar-location-crumb" onclick="pict.PictApplication.loadFileList(\'' + tmpLastPath + '\')">' + tmpLastPart + '</span>';
|
|
566
|
+
tmpHTML += '</span>';
|
|
567
|
+
|
|
205
568
|
tmpLocationEl.innerHTML = tmpHTML;
|
|
206
569
|
}
|
|
207
570
|
|
|
571
|
+
/**
|
|
572
|
+
* Toggle the breadcrumb overflow dropdown.
|
|
573
|
+
*/
|
|
574
|
+
toggleBreadcrumbDropdown()
|
|
575
|
+
{
|
|
576
|
+
let tmpDropdown = document.getElementById('RetoldRemote-BreadcrumbDropdown');
|
|
577
|
+
if (!tmpDropdown)
|
|
578
|
+
{
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
let tmpIsOpen = tmpDropdown.classList.contains('open');
|
|
583
|
+
|
|
584
|
+
if (tmpIsOpen)
|
|
585
|
+
{
|
|
586
|
+
this.closeBreadcrumbDropdown();
|
|
587
|
+
}
|
|
588
|
+
else
|
|
589
|
+
{
|
|
590
|
+
tmpDropdown.classList.add('open');
|
|
591
|
+
|
|
592
|
+
// Close on outside click/tap
|
|
593
|
+
let tmpSelf = this;
|
|
594
|
+
let tmpCloseHandler = function(pEvent)
|
|
595
|
+
{
|
|
596
|
+
// Ignore clicks inside the dropdown or on the toggle button
|
|
597
|
+
if (tmpDropdown.contains(pEvent.target))
|
|
598
|
+
{
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
let tmpBtn = tmpDropdown.parentElement && tmpDropdown.parentElement.querySelector('.retold-remote-topbar-overflow-btn');
|
|
602
|
+
if (tmpBtn && tmpBtn.contains(pEvent.target))
|
|
603
|
+
{
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
tmpSelf.closeBreadcrumbDropdown();
|
|
607
|
+
document.removeEventListener('click', tmpCloseHandler, true);
|
|
608
|
+
document.removeEventListener('touchstart', tmpCloseHandler, true);
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
// Defer attaching so the current click doesn't immediately close it
|
|
612
|
+
setTimeout(function()
|
|
613
|
+
{
|
|
614
|
+
document.addEventListener('click', tmpCloseHandler, true);
|
|
615
|
+
document.addEventListener('touchstart', tmpCloseHandler, true);
|
|
616
|
+
}, 0);
|
|
617
|
+
|
|
618
|
+
// Store the handler so closeBreadcrumbDropdown can clean it up
|
|
619
|
+
this._breadcrumbCloseHandler = tmpCloseHandler;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Close the breadcrumb overflow dropdown.
|
|
625
|
+
*/
|
|
626
|
+
closeBreadcrumbDropdown()
|
|
627
|
+
{
|
|
628
|
+
let tmpDropdown = document.getElementById('RetoldRemote-BreadcrumbDropdown');
|
|
629
|
+
if (tmpDropdown)
|
|
630
|
+
{
|
|
631
|
+
tmpDropdown.classList.remove('open');
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
if (this._breadcrumbCloseHandler)
|
|
635
|
+
{
|
|
636
|
+
document.removeEventListener('click', this._breadcrumbCloseHandler, true);
|
|
637
|
+
document.removeEventListener('touchstart', this._breadcrumbCloseHandler, true);
|
|
638
|
+
this._breadcrumbCloseHandler = null;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
208
642
|
/**
|
|
209
643
|
* Toggle the filter bar visibility.
|
|
210
644
|
* If hidden, show it and focus the search box.
|
|
@@ -215,6 +649,12 @@ class RetoldRemoteTopBarView extends libPictView
|
|
|
215
649
|
let tmpRemote = this.pict.AppData.RetoldRemote;
|
|
216
650
|
tmpRemote.FilterBarVisible = !tmpRemote.FilterBarVisible;
|
|
217
651
|
|
|
652
|
+
// When hiding the filter bar, also close the advanced filter panel
|
|
653
|
+
if (!tmpRemote.FilterBarVisible)
|
|
654
|
+
{
|
|
655
|
+
tmpRemote.FilterPanelOpen = false;
|
|
656
|
+
}
|
|
657
|
+
|
|
218
658
|
let tmpGalleryView = this.pict.views['RetoldRemote-Gallery'];
|
|
219
659
|
if (tmpGalleryView)
|
|
220
660
|
{
|
|
@@ -280,9 +720,11 @@ class RetoldRemoteTopBarView extends libPictView
|
|
|
280
720
|
|
|
281
721
|
/**
|
|
282
722
|
* Update the info display with folder summary.
|
|
723
|
+
* Also updates the AI Sort button visibility.
|
|
283
724
|
*/
|
|
284
725
|
updateInfo()
|
|
285
726
|
{
|
|
727
|
+
this.updateAISortButton();
|
|
286
728
|
let tmpInfoEl = document.getElementById('RetoldRemote-TopBar-Info');
|
|
287
729
|
if (!tmpInfoEl)
|
|
288
730
|
{
|
|
@@ -299,18 +741,29 @@ class RetoldRemoteTopBarView extends libPictView
|
|
|
299
741
|
let tmpItem = tmpItems[tmpIndex];
|
|
300
742
|
if (tmpItem)
|
|
301
743
|
{
|
|
302
|
-
|
|
744
|
+
let tmpPos = (tmpIndex + 1) + '/' + tmpItems.length;
|
|
745
|
+
tmpInfoEl.textContent = tmpPos + ' \u00b7 ' + tmpItem.Name;
|
|
303
746
|
}
|
|
304
747
|
return;
|
|
305
748
|
}
|
|
306
749
|
|
|
750
|
+
let tmpItems = tmpRemote.GalleryItems || [];
|
|
751
|
+
let tmpIndex = tmpRemote.GalleryCursorIndex || 0;
|
|
752
|
+
let tmpCursorText = '';
|
|
753
|
+
|
|
754
|
+
if (tmpItems.length > 0)
|
|
755
|
+
{
|
|
756
|
+
tmpCursorText = (tmpIndex + 1) + '/' + tmpItems.length;
|
|
757
|
+
}
|
|
758
|
+
|
|
307
759
|
if (!tmpSummary)
|
|
308
760
|
{
|
|
309
|
-
tmpInfoEl.textContent =
|
|
761
|
+
tmpInfoEl.textContent = tmpCursorText;
|
|
310
762
|
return;
|
|
311
763
|
}
|
|
312
764
|
|
|
313
765
|
let tmpParts = [];
|
|
766
|
+
if (tmpCursorText) tmpParts.push(tmpCursorText);
|
|
314
767
|
if (tmpSummary.Folders > 0) tmpParts.push(tmpSummary.Folders + ' folders');
|
|
315
768
|
if (tmpSummary.Images > 0) tmpParts.push(tmpSummary.Images + ' images');
|
|
316
769
|
if (tmpSummary.Videos > 0) tmpParts.push(tmpSummary.Videos + ' videos');
|
|
@@ -320,6 +773,240 @@ class RetoldRemoteTopBarView extends libPictView
|
|
|
320
773
|
|
|
321
774
|
tmpInfoEl.textContent = tmpParts.join(' \u00b7 ');
|
|
322
775
|
}
|
|
776
|
+
|
|
777
|
+
// -- AI Sort ----------------------------------------------------------
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* Trigger AI sort for the current folder.
|
|
781
|
+
*/
|
|
782
|
+
triggerAISort()
|
|
783
|
+
{
|
|
784
|
+
let tmpAISortManager = this.pict.providers['RetoldRemote-AISortManager'];
|
|
785
|
+
if (!tmpAISortManager)
|
|
786
|
+
{
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
let tmpCurrentPath = (this.pict.AppData.PictFileBrowser && this.pict.AppData.PictFileBrowser.CurrentLocation) || '';
|
|
791
|
+
|
|
792
|
+
// Show generating state
|
|
793
|
+
let tmpBtn = document.getElementById('RetoldRemote-TopBar-AISortBtn');
|
|
794
|
+
if (tmpBtn)
|
|
795
|
+
{
|
|
796
|
+
tmpBtn.classList.add('generating');
|
|
797
|
+
tmpBtn.textContent = 'Sorting...';
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
tmpAISortManager.generateSortPlan(tmpCurrentPath,
|
|
801
|
+
(pError, pResult) =>
|
|
802
|
+
{
|
|
803
|
+
// Reset button state
|
|
804
|
+
if (tmpBtn)
|
|
805
|
+
{
|
|
806
|
+
tmpBtn.classList.remove('generating');
|
|
807
|
+
tmpBtn.textContent = 'AI Sort';
|
|
808
|
+
}
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Update the AI Sort button visibility.
|
|
814
|
+
* Shows only when browsing a folder (gallery mode).
|
|
815
|
+
*/
|
|
816
|
+
updateAISortButton()
|
|
817
|
+
{
|
|
818
|
+
let tmpBtn = document.getElementById('RetoldRemote-TopBar-AISortBtn');
|
|
819
|
+
if (!tmpBtn)
|
|
820
|
+
{
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
let tmpAISortManager = this.pict.providers['RetoldRemote-AISortManager'];
|
|
825
|
+
if (tmpAISortManager && tmpAISortManager.isAvailable())
|
|
826
|
+
{
|
|
827
|
+
tmpBtn.style.display = '';
|
|
828
|
+
}
|
|
829
|
+
else
|
|
830
|
+
{
|
|
831
|
+
tmpBtn.style.display = 'none';
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// -- Collections Panel ------------------------------------------------
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Toggle the collections panel.
|
|
839
|
+
*/
|
|
840
|
+
toggleCollections()
|
|
841
|
+
{
|
|
842
|
+
let tmpManager = this.pict.providers['RetoldRemote-CollectionManager'];
|
|
843
|
+
if (tmpManager)
|
|
844
|
+
{
|
|
845
|
+
tmpManager.togglePanel();
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* Update the collections toggle button icon/state.
|
|
851
|
+
*/
|
|
852
|
+
updateCollectionsIcon()
|
|
853
|
+
{
|
|
854
|
+
let tmpBtn = document.getElementById('RetoldRemote-TopBar-CollectionsBtn');
|
|
855
|
+
if (!tmpBtn)
|
|
856
|
+
{
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
let tmpRemote = this.pict.AppData.RetoldRemote;
|
|
861
|
+
let tmpIconProvider = this.pict.providers['RetoldRemote-Icons'];
|
|
862
|
+
|
|
863
|
+
if (tmpRemote.CollectionsPanelOpen)
|
|
864
|
+
{
|
|
865
|
+
tmpBtn.classList.add('panel-open');
|
|
866
|
+
if (tmpIconProvider && typeof tmpIconProvider.getIcon === 'function')
|
|
867
|
+
{
|
|
868
|
+
tmpBtn.innerHTML = tmpIconProvider.getIcon('bookmark-filled', 16);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
else
|
|
872
|
+
{
|
|
873
|
+
tmpBtn.classList.remove('panel-open');
|
|
874
|
+
if (tmpIconProvider && typeof tmpIconProvider.getIcon === 'function')
|
|
875
|
+
{
|
|
876
|
+
tmpBtn.innerHTML = tmpIconProvider.getIcon('bookmark', 16);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/**
|
|
882
|
+
* Add current file/folder to a collection.
|
|
883
|
+
* Quick-add: single click adds to last-used collection.
|
|
884
|
+
* If no last-used collection, opens the picker dropdown.
|
|
885
|
+
*
|
|
886
|
+
* @param {Event} pEvent - Click event
|
|
887
|
+
*/
|
|
888
|
+
addToCollection(pEvent)
|
|
889
|
+
{
|
|
890
|
+
let tmpRemote = this.pict.AppData.RetoldRemote;
|
|
891
|
+
let tmpManager = this.pict.providers['RetoldRemote-CollectionManager'];
|
|
892
|
+
if (!tmpManager)
|
|
893
|
+
{
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// Quick-add: if we have a last-used collection, add directly
|
|
898
|
+
if (tmpRemote.LastUsedCollectionGUID)
|
|
899
|
+
{
|
|
900
|
+
let tmpAdded = tmpManager.addCurrentFileToCollection(tmpRemote.LastUsedCollectionGUID);
|
|
901
|
+
if (tmpAdded)
|
|
902
|
+
{
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// Fall through to picker dropdown
|
|
908
|
+
this.showAddToCollectionDropdown(pEvent);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Show the add-to-collection picker dropdown.
|
|
913
|
+
*
|
|
914
|
+
* @param {Event} [pEvent] - Optional click event for positioning
|
|
915
|
+
*/
|
|
916
|
+
showAddToCollectionDropdown(pEvent)
|
|
917
|
+
{
|
|
918
|
+
let tmpSelf = this;
|
|
919
|
+
let tmpRemote = this.pict.AppData.RetoldRemote;
|
|
920
|
+
let tmpManager = this.pict.providers['RetoldRemote-CollectionManager'];
|
|
921
|
+
|
|
922
|
+
// Remove any existing dropdown
|
|
923
|
+
this._closeAddToCollectionDropdown();
|
|
924
|
+
|
|
925
|
+
let tmpBtn = document.getElementById('RetoldRemote-TopBar-AddToCollectionBtn');
|
|
926
|
+
if (!tmpBtn)
|
|
927
|
+
{
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// Ensure we have the latest collections
|
|
932
|
+
tmpManager.fetchCollections(() =>
|
|
933
|
+
{
|
|
934
|
+
let tmpCollections = tmpRemote.Collections || [];
|
|
935
|
+
|
|
936
|
+
let tmpDropdown = document.createElement('div');
|
|
937
|
+
tmpDropdown.className = 'retold-remote-addcoll-dropdown';
|
|
938
|
+
tmpDropdown.id = 'RetoldRemote-AddToCollection-Dropdown';
|
|
939
|
+
|
|
940
|
+
// "New Collection" option
|
|
941
|
+
let tmpNewItem = document.createElement('button');
|
|
942
|
+
tmpNewItem.className = 'retold-remote-addcoll-dropdown-item retold-remote-addcoll-dropdown-new';
|
|
943
|
+
tmpNewItem.textContent = '+ New Collection...';
|
|
944
|
+
tmpNewItem.onclick = () =>
|
|
945
|
+
{
|
|
946
|
+
tmpSelf._closeAddToCollectionDropdown();
|
|
947
|
+
let tmpName = prompt('Collection name:');
|
|
948
|
+
if (tmpName && tmpName.trim())
|
|
949
|
+
{
|
|
950
|
+
tmpManager.createCollection(tmpName.trim(), (pError, pCollection) =>
|
|
951
|
+
{
|
|
952
|
+
if (!pError && pCollection)
|
|
953
|
+
{
|
|
954
|
+
tmpManager.addCurrentFileToCollection(pCollection.GUID);
|
|
955
|
+
}
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
};
|
|
959
|
+
tmpDropdown.appendChild(tmpNewItem);
|
|
960
|
+
|
|
961
|
+
// Existing collections
|
|
962
|
+
for (let i = 0; i < tmpCollections.length; i++)
|
|
963
|
+
{
|
|
964
|
+
let tmpCollection = tmpCollections[i];
|
|
965
|
+
let tmpItem = document.createElement('button');
|
|
966
|
+
tmpItem.className = 'retold-remote-addcoll-dropdown-item';
|
|
967
|
+
tmpItem.textContent = tmpCollection.Name || 'Untitled';
|
|
968
|
+
tmpItem.onclick = () =>
|
|
969
|
+
{
|
|
970
|
+
tmpSelf._closeAddToCollectionDropdown();
|
|
971
|
+
tmpManager.addCurrentFileToCollection(tmpCollection.GUID);
|
|
972
|
+
};
|
|
973
|
+
tmpDropdown.appendChild(tmpItem);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// Position relative to the button
|
|
977
|
+
tmpBtn.style.position = 'relative';
|
|
978
|
+
tmpBtn.appendChild(tmpDropdown);
|
|
979
|
+
|
|
980
|
+
// Close on outside click
|
|
981
|
+
setTimeout(() =>
|
|
982
|
+
{
|
|
983
|
+
document.addEventListener('click', tmpSelf._boundCloseDropdown = (pClickEvent) =>
|
|
984
|
+
{
|
|
985
|
+
if (!tmpDropdown.contains(pClickEvent.target) && pClickEvent.target !== tmpBtn)
|
|
986
|
+
{
|
|
987
|
+
tmpSelf._closeAddToCollectionDropdown();
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
}, 10);
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* Close the add-to-collection dropdown.
|
|
996
|
+
*/
|
|
997
|
+
_closeAddToCollectionDropdown()
|
|
998
|
+
{
|
|
999
|
+
let tmpDropdown = document.getElementById('RetoldRemote-AddToCollection-Dropdown');
|
|
1000
|
+
if (tmpDropdown)
|
|
1001
|
+
{
|
|
1002
|
+
tmpDropdown.remove();
|
|
1003
|
+
}
|
|
1004
|
+
if (this._boundCloseDropdown)
|
|
1005
|
+
{
|
|
1006
|
+
document.removeEventListener('click', this._boundCloseDropdown);
|
|
1007
|
+
this._boundCloseDropdown = null;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
323
1010
|
}
|
|
324
1011
|
|
|
325
1012
|
RetoldRemoteTopBarView.default_configuration = _ViewConfiguration;
|