retold-remote 0.0.1 → 0.0.2
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/html/index.html +2 -0
- package/package.json +20 -14
- package/source/Pict-Application-RetoldRemote.js +46 -5
- package/source/cli/RetoldRemote-CLI-Run.js +0 -0
- package/source/cli/RetoldRemote-Server-Setup.js +790 -8
- package/source/cli/commands/RetoldRemote-Command-Serve.js +34 -1
- package/source/providers/Pict-Provider-GalleryFilterSort.js +61 -9
- package/source/providers/Pict-Provider-GalleryNavigation.js +517 -18
- package/source/providers/Pict-Provider-RetoldRemote.js +11 -2
- package/source/providers/Pict-Provider-RetoldRemoteIcons.js +1 -0
- package/source/server/RetoldRemote-ArchiveService.js +830 -0
- package/source/server/RetoldRemote-AudioWaveformService.js +673 -0
- package/source/server/RetoldRemote-EbookService.js +242 -0
- package/source/server/RetoldRemote-MediaService.js +1 -1
- package/source/server/RetoldRemote-ToolDetector.js +31 -1
- package/source/server/RetoldRemote-VideoFrameService.js +486 -0
- package/source/views/PictView-Remote-AudioExplorer.js +1213 -0
- package/source/views/PictView-Remote-Gallery.js +141 -2
- package/source/views/PictView-Remote-Layout.js +18 -27
- package/source/views/PictView-Remote-MediaViewer.js +638 -39
- package/source/views/PictView-Remote-SettingsPanel.js +23 -0
- package/source/views/PictView-Remote-TopBar.js +121 -0
- package/source/views/PictView-Remote-VideoExplorer.js +1229 -0
- package/web-application/index.html +2 -0
- package/web-application/js/epub.min.js +1 -0
- package/web-application/retold-remote.js +7030 -1244
- package/web-application/retold-remote.js.map +1 -1
- package/web-application/retold-remote.min.js +13 -44
- package/web-application/retold-remote.min.js.map +1 -1
- package/web-application/retold-remote.compatible.js +0 -5764
- package/web-application/retold-remote.compatible.js.map +0 -1
- package/web-application/retold-remote.compatible.min.js +0 -120
- package/web-application/retold-remote.compatible.min.js.map +0 -1
|
@@ -113,6 +113,44 @@ const _ViewConfiguration =
|
|
|
113
113
|
{
|
|
114
114
|
color: var(--retold-text-placeholder);
|
|
115
115
|
}
|
|
116
|
+
.retold-remote-gallery-search-options
|
|
117
|
+
{
|
|
118
|
+
display: flex;
|
|
119
|
+
align-items: center;
|
|
120
|
+
gap: 8px;
|
|
121
|
+
flex-shrink: 0;
|
|
122
|
+
}
|
|
123
|
+
.retold-remote-gallery-search-option
|
|
124
|
+
{
|
|
125
|
+
display: inline-flex;
|
|
126
|
+
align-items: center;
|
|
127
|
+
gap: 3px;
|
|
128
|
+
font-size: 0.68rem;
|
|
129
|
+
color: var(--retold-text-dim);
|
|
130
|
+
cursor: pointer;
|
|
131
|
+
white-space: nowrap;
|
|
132
|
+
user-select: none;
|
|
133
|
+
}
|
|
134
|
+
.retold-remote-gallery-search-option:hover
|
|
135
|
+
{
|
|
136
|
+
color: var(--retold-text-muted);
|
|
137
|
+
}
|
|
138
|
+
.retold-remote-gallery-search-option input[type="checkbox"]
|
|
139
|
+
{
|
|
140
|
+
margin: 0;
|
|
141
|
+
cursor: pointer;
|
|
142
|
+
accent-color: var(--retold-accent);
|
|
143
|
+
}
|
|
144
|
+
.retold-remote-gallery-search-option.active
|
|
145
|
+
{
|
|
146
|
+
color: var(--retold-accent);
|
|
147
|
+
}
|
|
148
|
+
.retold-remote-gallery-search-regex-error
|
|
149
|
+
{
|
|
150
|
+
font-size: 0.68rem;
|
|
151
|
+
color: #e06c75;
|
|
152
|
+
white-space: nowrap;
|
|
153
|
+
}
|
|
116
154
|
/* Filter chips */
|
|
117
155
|
.retold-remote-filter-chips
|
|
118
156
|
{
|
|
@@ -635,6 +673,12 @@ class RetoldRemoteGalleryView extends libPictView
|
|
|
635
673
|
let tmpThumbnailSize = tmpRemote.ThumbnailSize || 'medium';
|
|
636
674
|
let tmpCursorIndex = tmpRemote.GalleryCursorIndex || 0;
|
|
637
675
|
|
|
676
|
+
// Capture search input focus state before re-render so we can restore it
|
|
677
|
+
let tmpSearchEl = document.getElementById('RetoldRemote-Gallery-Search');
|
|
678
|
+
let tmpSearchHadFocus = tmpSearchEl && (document.activeElement === tmpSearchEl);
|
|
679
|
+
let tmpSearchSelStart = tmpSearchHadFocus ? tmpSearchEl.selectionStart : 0;
|
|
680
|
+
let tmpSearchSelEnd = tmpSearchHadFocus ? tmpSearchEl.selectionEnd : 0;
|
|
681
|
+
|
|
638
682
|
// Build header with type filters, sort, filter toggle, and search
|
|
639
683
|
let tmpHTML = this._buildHeaderHTML(tmpRemote.FilterState ? tmpRemote.FilterState.MediaType : 'all');
|
|
640
684
|
|
|
@@ -652,6 +696,17 @@ class RetoldRemoteGalleryView extends libPictView
|
|
|
652
696
|
tmpHTML += '<div>Empty folder</div>';
|
|
653
697
|
tmpHTML += '</div>';
|
|
654
698
|
tmpContainer.innerHTML = tmpHTML;
|
|
699
|
+
|
|
700
|
+
// Restore search focus even on empty results
|
|
701
|
+
if (tmpSearchHadFocus)
|
|
702
|
+
{
|
|
703
|
+
let tmpNewSearch = document.getElementById('RetoldRemote-Gallery-Search');
|
|
704
|
+
if (tmpNewSearch)
|
|
705
|
+
{
|
|
706
|
+
tmpNewSearch.focus();
|
|
707
|
+
tmpNewSearch.setSelectionRange(tmpSearchSelStart, tmpSearchSelEnd);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
655
710
|
return;
|
|
656
711
|
}
|
|
657
712
|
|
|
@@ -667,6 +722,17 @@ class RetoldRemoteGalleryView extends libPictView
|
|
|
667
722
|
|
|
668
723
|
tmpContainer.innerHTML = tmpHTML;
|
|
669
724
|
|
|
725
|
+
// Restore search input focus and cursor position after re-render
|
|
726
|
+
if (tmpSearchHadFocus)
|
|
727
|
+
{
|
|
728
|
+
let tmpNewSearch = document.getElementById('RetoldRemote-Gallery-Search');
|
|
729
|
+
if (tmpNewSearch)
|
|
730
|
+
{
|
|
731
|
+
tmpNewSearch.focus();
|
|
732
|
+
tmpNewSearch.setSelectionRange(tmpSearchSelStart, tmpSearchSelEnd);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
670
736
|
// Set up lazy loading for thumbnail images
|
|
671
737
|
this._setupLazyLoading();
|
|
672
738
|
|
|
@@ -676,6 +742,13 @@ class RetoldRemoteGalleryView extends libPictView
|
|
|
676
742
|
{
|
|
677
743
|
tmpNavProvider.recalculateColumns();
|
|
678
744
|
}
|
|
745
|
+
|
|
746
|
+
// Update the top bar filter icon state
|
|
747
|
+
let tmpTopBarView = this.pict.views['ContentEditor-TopBar'];
|
|
748
|
+
if (tmpTopBarView && tmpTopBarView.updateFilterIcon)
|
|
749
|
+
{
|
|
750
|
+
tmpTopBarView.updateFilterIcon();
|
|
751
|
+
}
|
|
679
752
|
}
|
|
680
753
|
|
|
681
754
|
// ──────────────────────────────────────────────
|
|
@@ -684,10 +757,18 @@ class RetoldRemoteGalleryView extends libPictView
|
|
|
684
757
|
|
|
685
758
|
/**
|
|
686
759
|
* Build the gallery header with type filters, sort dropdown, filter toggle, and search.
|
|
760
|
+
* The filter bar is hidden by default; toggled via / key or the top bar filter icon.
|
|
687
761
|
*/
|
|
688
762
|
_buildHeaderHTML(pActiveFilter)
|
|
689
763
|
{
|
|
690
764
|
let tmpRemote = this.pict.AppData.RetoldRemote;
|
|
765
|
+
|
|
766
|
+
// If the filter bar is not visible, don't render the header
|
|
767
|
+
if (!tmpRemote.FilterBarVisible)
|
|
768
|
+
{
|
|
769
|
+
return '';
|
|
770
|
+
}
|
|
771
|
+
|
|
691
772
|
let tmpFilters = [
|
|
692
773
|
{ key: 'all', label: 'All' },
|
|
693
774
|
{ key: 'images', label: 'Images' },
|
|
@@ -754,6 +835,24 @@ class RetoldRemoteGalleryView extends libPictView
|
|
|
754
835
|
+ 'placeholder="Search files... (/)" '
|
|
755
836
|
+ 'value="' + this._escapeHTML(tmpSearchValue) + '" '
|
|
756
837
|
+ 'oninput="pict.views[\'RetoldRemote-Gallery\'].onSearchInput(this.value)">';
|
|
838
|
+
|
|
839
|
+
// Case sensitivity and regex checkboxes
|
|
840
|
+
let tmpCaseSensitive = tmpRemote.SearchCaseSensitive || false;
|
|
841
|
+
let tmpRegex = tmpRemote.SearchRegex || false;
|
|
842
|
+
tmpHTML += '<div class="retold-remote-gallery-search-options">';
|
|
843
|
+
tmpHTML += '<label class="retold-remote-gallery-search-option' + (tmpCaseSensitive ? ' active' : '') + '">'
|
|
844
|
+
+ '<input type="checkbox" ' + (tmpCaseSensitive ? 'checked ' : '')
|
|
845
|
+
+ 'onchange="pict.views[\'RetoldRemote-Gallery\'].onSearchCaseSensitiveChange(this.checked)">'
|
|
846
|
+
+ 'Aa</label>';
|
|
847
|
+
tmpHTML += '<label class="retold-remote-gallery-search-option' + (tmpRegex ? ' active' : '') + '">'
|
|
848
|
+
+ '<input type="checkbox" ' + (tmpRegex ? 'checked ' : '')
|
|
849
|
+
+ 'onchange="pict.views[\'RetoldRemote-Gallery\'].onSearchRegexChange(this.checked)">'
|
|
850
|
+
+ '.*</label>';
|
|
851
|
+
if (tmpRemote._searchRegexError)
|
|
852
|
+
{
|
|
853
|
+
tmpHTML += '<span class="retold-remote-gallery-search-regex-error" title="' + this._escapeHTML(tmpRemote._searchRegexError) + '">invalid regex</span>';
|
|
854
|
+
}
|
|
855
|
+
tmpHTML += '</div>';
|
|
757
856
|
tmpHTML += '</div>';
|
|
758
857
|
|
|
759
858
|
return tmpHTML;
|
|
@@ -950,6 +1049,11 @@ class RetoldRemoteGalleryView extends libPictView
|
|
|
950
1049
|
tmpHTML += '<div class="retold-remote-tile-thumb-icon"><span class="retold-remote-icon retold-remote-icon-md">' + (tmpIconProvider ? tmpIconProvider.getIcon('folder', 48) : '') + '</span></div>';
|
|
951
1050
|
tmpHTML += '<span class="retold-remote-tile-badge retold-remote-tile-badge-folder">Folder</span>';
|
|
952
1051
|
}
|
|
1052
|
+
else if (tmpItem.Type === 'archive')
|
|
1053
|
+
{
|
|
1054
|
+
tmpHTML += '<div class="retold-remote-tile-thumb-icon"><span class="retold-remote-icon retold-remote-icon-md">' + (tmpIconProvider ? tmpIconProvider.getIcon('file-archive', 48) : '') + '</span></div>';
|
|
1055
|
+
tmpHTML += '<span class="retold-remote-tile-badge retold-remote-tile-badge-folder">Archive</span>';
|
|
1056
|
+
}
|
|
953
1057
|
else if (tmpCategory === 'image' && tmpProvider)
|
|
954
1058
|
{
|
|
955
1059
|
let tmpThumbURL = tmpProvider.getThumbnailURL(tmpItem.Path, 400, 300);
|
|
@@ -1012,6 +1116,10 @@ class RetoldRemoteGalleryView extends libPictView
|
|
|
1012
1116
|
{
|
|
1013
1117
|
tmpHTML += '<div class="retold-remote-tile-meta">Folder</div>';
|
|
1014
1118
|
}
|
|
1119
|
+
else if (tmpItem.Type === 'archive')
|
|
1120
|
+
{
|
|
1121
|
+
tmpHTML += '<div class="retold-remote-tile-meta">Archive' + (tmpItem.Size ? ' · ' + this._formatFileSize(tmpItem.Size) : '') + '</div>';
|
|
1122
|
+
}
|
|
1015
1123
|
|
|
1016
1124
|
tmpHTML += '</div>'; // end tile
|
|
1017
1125
|
}
|
|
@@ -1047,7 +1155,7 @@ class RetoldRemoteGalleryView extends libPictView
|
|
|
1047
1155
|
tmpHTML += '<div class="retold-remote-list-icon">' + tmpIcon + '</div>';
|
|
1048
1156
|
tmpHTML += '<div class="retold-remote-list-name">' + this._escapeHTML(tmpItem.Name) + '</div>';
|
|
1049
1157
|
|
|
1050
|
-
if (tmpItem.Type === 'file' && tmpItem.Size !== undefined)
|
|
1158
|
+
if ((tmpItem.Type === 'file' || tmpItem.Type === 'archive') && tmpItem.Size !== undefined)
|
|
1051
1159
|
{
|
|
1052
1160
|
tmpHTML += '<div class="retold-remote-list-size">' + this._formatFileSize(tmpItem.Size) + '</div>';
|
|
1053
1161
|
}
|
|
@@ -1169,7 +1277,37 @@ class RetoldRemoteGalleryView extends libPictView
|
|
|
1169
1277
|
onSearchInput(pValue)
|
|
1170
1278
|
{
|
|
1171
1279
|
let tmpRemote = this.pict.AppData.RetoldRemote;
|
|
1172
|
-
tmpRemote.SearchQuery =
|
|
1280
|
+
tmpRemote.SearchQuery = pValue || '';
|
|
1281
|
+
|
|
1282
|
+
let tmpFilterSort = this.pict.providers['RetoldRemote-GalleryFilterSort'];
|
|
1283
|
+
if (tmpFilterSort)
|
|
1284
|
+
{
|
|
1285
|
+
tmpFilterSort.applyFilterSort();
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
/**
|
|
1290
|
+
* Handle case-sensitive checkbox change.
|
|
1291
|
+
*/
|
|
1292
|
+
onSearchCaseSensitiveChange(pChecked)
|
|
1293
|
+
{
|
|
1294
|
+
let tmpRemote = this.pict.AppData.RetoldRemote;
|
|
1295
|
+
tmpRemote.SearchCaseSensitive = pChecked;
|
|
1296
|
+
|
|
1297
|
+
let tmpFilterSort = this.pict.providers['RetoldRemote-GalleryFilterSort'];
|
|
1298
|
+
if (tmpFilterSort)
|
|
1299
|
+
{
|
|
1300
|
+
tmpFilterSort.applyFilterSort();
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
/**
|
|
1305
|
+
* Handle regex checkbox change.
|
|
1306
|
+
*/
|
|
1307
|
+
onSearchRegexChange(pChecked)
|
|
1308
|
+
{
|
|
1309
|
+
let tmpRemote = this.pict.AppData.RetoldRemote;
|
|
1310
|
+
tmpRemote.SearchRegex = pChecked;
|
|
1173
1311
|
|
|
1174
1312
|
let tmpFilterSort = this.pict.providers['RetoldRemote-GalleryFilterSort'];
|
|
1175
1313
|
if (tmpFilterSort)
|
|
@@ -1400,6 +1538,7 @@ class RetoldRemoteGalleryView extends libPictView
|
|
|
1400
1538
|
_getCategory(pExtension, pType)
|
|
1401
1539
|
{
|
|
1402
1540
|
if (pType === 'folder') return 'folder';
|
|
1541
|
+
if (pType === 'archive') return 'archive';
|
|
1403
1542
|
// Delegate to the filter/sort provider if available
|
|
1404
1543
|
let tmpFilterSort = this.pict.providers['RetoldRemote-GalleryFilterSort'];
|
|
1405
1544
|
if (tmpFilterSort)
|
|
@@ -102,32 +102,6 @@ const _ViewConfiguration =
|
|
|
102
102
|
{
|
|
103
103
|
display: none;
|
|
104
104
|
}
|
|
105
|
-
/* Collapse toggle */
|
|
106
|
-
.content-editor-sidebar-toggle
|
|
107
|
-
{
|
|
108
|
-
position: absolute;
|
|
109
|
-
top: 8px;
|
|
110
|
-
right: -20px;
|
|
111
|
-
width: 20px;
|
|
112
|
-
height: 28px;
|
|
113
|
-
display: flex;
|
|
114
|
-
align-items: center;
|
|
115
|
-
justify-content: center;
|
|
116
|
-
background: var(--retold-bg-tertiary);
|
|
117
|
-
border: 1px solid var(--retold-border);
|
|
118
|
-
border-left: none;
|
|
119
|
-
border-radius: 0 4px 4px 0;
|
|
120
|
-
cursor: pointer;
|
|
121
|
-
z-index: 10;
|
|
122
|
-
color: var(--retold-text-muted);
|
|
123
|
-
font-size: 11px;
|
|
124
|
-
line-height: 1;
|
|
125
|
-
transition: color 0.15s;
|
|
126
|
-
}
|
|
127
|
-
.content-editor-sidebar-toggle:hover
|
|
128
|
-
{
|
|
129
|
-
color: var(--retold-text-primary);
|
|
130
|
-
}
|
|
131
105
|
/* Resize handle */
|
|
132
106
|
.content-editor-resize-handle
|
|
133
107
|
{
|
|
@@ -186,6 +160,17 @@ const _ViewConfiguration =
|
|
|
186
160
|
background: var(--retold-bg-selected);
|
|
187
161
|
color: var(--retold-accent);
|
|
188
162
|
}
|
|
163
|
+
#ContentEditor-Sidebar-Container .pict-fb-detail-row.sidebar-focused
|
|
164
|
+
{
|
|
165
|
+
outline: 2px solid var(--retold-accent);
|
|
166
|
+
outline-offset: -2px;
|
|
167
|
+
background: var(--retold-bg-hover);
|
|
168
|
+
color: var(--retold-text-primary);
|
|
169
|
+
}
|
|
170
|
+
.content-editor-sidebar-inner.keyboard-focused
|
|
171
|
+
{
|
|
172
|
+
box-shadow: inset 0 0 0 1px var(--retold-accent);
|
|
173
|
+
}
|
|
189
174
|
#ContentEditor-Sidebar-Container .pict-fb-breadcrumbs
|
|
190
175
|
{
|
|
191
176
|
color: var(--retold-text-muted);
|
|
@@ -233,7 +218,6 @@ const _ViewConfiguration =
|
|
|
233
218
|
<div id="ContentEditor-TopBar-Container"></div>
|
|
234
219
|
<div class="content-editor-body">
|
|
235
220
|
<div class="content-editor-sidebar-wrap" style="width: 250px;">
|
|
236
|
-
<div class="content-editor-sidebar-toggle" onclick="pict.views['ContentEditor-Layout'].toggleSidebar()">◀</div>
|
|
237
221
|
<div class="content-editor-sidebar-inner">
|
|
238
222
|
<div class="content-editor-sidebar-tabs">
|
|
239
223
|
<button class="content-editor-sidebar-tab active" data-tab="files" onclick="pict.views['ContentEditor-Layout'].switchSidebarTab('files')">Files</button>
|
|
@@ -412,6 +396,13 @@ class RetoldRemoteLayoutView extends libPictView
|
|
|
412
396
|
}
|
|
413
397
|
|
|
414
398
|
tmpHandle.addEventListener('mousedown', onMouseDown);
|
|
399
|
+
|
|
400
|
+
// Double-click on resize handle collapses the sidebar
|
|
401
|
+
tmpHandle.addEventListener('dblclick', function (pEvent)
|
|
402
|
+
{
|
|
403
|
+
pEvent.preventDefault();
|
|
404
|
+
tmpSelf.toggleSidebar();
|
|
405
|
+
});
|
|
415
406
|
}
|
|
416
407
|
}
|
|
417
408
|
|