retold-remote 0.0.4 → 0.0.6
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/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/package.json +21 -7
- package/source/Pict-Application-RetoldRemote.js +143 -2
- package/source/RetoldRemote-ExtensionMaps.js +33 -0
- package/source/cli/RetoldRemote-Server-Setup.js +82 -67
- package/source/cli/commands/RetoldRemote-Command-Serve.js +5 -26
- package/source/providers/Pict-Provider-CollectionManager.js +934 -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 +270 -353
- 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-ArchiveService.js +2 -12
- package/source/server/RetoldRemote-AudioWaveformService.js +7 -16
- package/source/server/RetoldRemote-CollectionService.js +684 -0
- package/source/server/RetoldRemote-EbookService.js +7 -16
- package/source/server/RetoldRemote-MediaService.js +3 -14
- 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 +1087 -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 +410 -20
- package/source/views/PictView-Remote-MediaViewer.js +338 -51
- package/source/views/PictView-Remote-SettingsPanel.js +155 -138
- package/source/views/PictView-Remote-TopBar.js +615 -14
- package/source/views/PictView-Remote-VLCSetup.js +766 -0
- package/source/views/PictView-Remote-VideoExplorer.js +20 -54
- package/web-application/css/docuserve.css +73 -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/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 +2558 -439
- package/web-application/retold-remote.js.map +1 -1
- package/web-application/retold-remote.min.js +41 -11
- package/web-application/retold-remote.min.js.map +1 -1
- package/server.js +0 -43
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Viewer mode keyboard handler.
|
|
3
|
+
*
|
|
4
|
+
* @param {GalleryNavigationProvider} pGalleryNav - The provider instance
|
|
5
|
+
* @param {KeyboardEvent} pEvent - The keyboard event
|
|
6
|
+
*/
|
|
7
|
+
function handleViewerKey(pGalleryNav, pEvent)
|
|
8
|
+
{
|
|
9
|
+
let tmpRemote = pGalleryNav.pict.AppData.RetoldRemote;
|
|
10
|
+
|
|
11
|
+
// Video action menu mode — intercept keys for menu options
|
|
12
|
+
if (tmpRemote.VideoMenuActive && tmpRemote.CurrentViewerMediaType === 'video')
|
|
13
|
+
{
|
|
14
|
+
switch (pEvent.key)
|
|
15
|
+
{
|
|
16
|
+
case 'Escape':
|
|
17
|
+
pEvent.preventDefault();
|
|
18
|
+
pGalleryNav.closeViewer();
|
|
19
|
+
return;
|
|
20
|
+
|
|
21
|
+
case 'ArrowRight':
|
|
22
|
+
case 'j':
|
|
23
|
+
pEvent.preventDefault();
|
|
24
|
+
pGalleryNav.nextFile();
|
|
25
|
+
return;
|
|
26
|
+
|
|
27
|
+
case 'ArrowLeft':
|
|
28
|
+
case 'k':
|
|
29
|
+
pEvent.preventDefault();
|
|
30
|
+
pGalleryNav.prevFile();
|
|
31
|
+
return;
|
|
32
|
+
|
|
33
|
+
case 'e':
|
|
34
|
+
pEvent.preventDefault();
|
|
35
|
+
let tmpVEX = pGalleryNav.pict.views['RetoldRemote-VideoExplorer'];
|
|
36
|
+
if (tmpVEX)
|
|
37
|
+
{
|
|
38
|
+
tmpVEX.showExplorer(tmpRemote.CurrentViewerFile);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
|
|
42
|
+
case ' ':
|
|
43
|
+
case 'Enter':
|
|
44
|
+
pEvent.preventDefault();
|
|
45
|
+
let tmpViewer = pGalleryNav.pict.views['RetoldRemote-MediaViewer'];
|
|
46
|
+
if (tmpViewer)
|
|
47
|
+
{
|
|
48
|
+
tmpViewer.playVideo();
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
|
|
52
|
+
case 't':
|
|
53
|
+
pEvent.preventDefault();
|
|
54
|
+
let tmpMediaViewer = pGalleryNav.pict.views['RetoldRemote-MediaViewer'];
|
|
55
|
+
if (tmpMediaViewer)
|
|
56
|
+
{
|
|
57
|
+
tmpMediaViewer.loadVideoMenuFrame();
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
|
|
61
|
+
case 'v':
|
|
62
|
+
pEvent.preventDefault();
|
|
63
|
+
pGalleryNav._streamWithVLC();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
switch (pEvent.key)
|
|
70
|
+
{
|
|
71
|
+
case 'Escape':
|
|
72
|
+
pEvent.preventDefault();
|
|
73
|
+
pGalleryNav.closeViewer();
|
|
74
|
+
break;
|
|
75
|
+
|
|
76
|
+
case 'ArrowRight':
|
|
77
|
+
case 'j':
|
|
78
|
+
pEvent.preventDefault();
|
|
79
|
+
pGalleryNav.nextFile();
|
|
80
|
+
break;
|
|
81
|
+
|
|
82
|
+
case 'ArrowLeft':
|
|
83
|
+
case 'k':
|
|
84
|
+
pEvent.preventDefault();
|
|
85
|
+
pGalleryNav.prevFile();
|
|
86
|
+
break;
|
|
87
|
+
|
|
88
|
+
case 'f':
|
|
89
|
+
pEvent.preventDefault();
|
|
90
|
+
pGalleryNav._toggleFullscreen();
|
|
91
|
+
break;
|
|
92
|
+
|
|
93
|
+
case 'i':
|
|
94
|
+
pEvent.preventDefault();
|
|
95
|
+
pGalleryNav._toggleFileInfo();
|
|
96
|
+
break;
|
|
97
|
+
|
|
98
|
+
case ' ':
|
|
99
|
+
pEvent.preventDefault();
|
|
100
|
+
pGalleryNav._togglePlayPause();
|
|
101
|
+
break;
|
|
102
|
+
|
|
103
|
+
case '+':
|
|
104
|
+
case '=':
|
|
105
|
+
pEvent.preventDefault();
|
|
106
|
+
pGalleryNav._zoomIn();
|
|
107
|
+
break;
|
|
108
|
+
|
|
109
|
+
case '-':
|
|
110
|
+
pEvent.preventDefault();
|
|
111
|
+
pGalleryNav._zoomOut();
|
|
112
|
+
break;
|
|
113
|
+
|
|
114
|
+
case '0':
|
|
115
|
+
pEvent.preventDefault();
|
|
116
|
+
pGalleryNav._zoomReset();
|
|
117
|
+
break;
|
|
118
|
+
|
|
119
|
+
case 'z':
|
|
120
|
+
pEvent.preventDefault();
|
|
121
|
+
pGalleryNav._cycleFitMode();
|
|
122
|
+
break;
|
|
123
|
+
|
|
124
|
+
case 'Enter':
|
|
125
|
+
pEvent.preventDefault();
|
|
126
|
+
pGalleryNav._streamWithVLC();
|
|
127
|
+
break;
|
|
128
|
+
|
|
129
|
+
case 'v':
|
|
130
|
+
pEvent.preventDefault();
|
|
131
|
+
pGalleryNav._streamWithVLC();
|
|
132
|
+
break;
|
|
133
|
+
|
|
134
|
+
case 'a':
|
|
135
|
+
pEvent.preventDefault();
|
|
136
|
+
{
|
|
137
|
+
let tmpCollMgr = pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];
|
|
138
|
+
if (tmpCollMgr)
|
|
139
|
+
{
|
|
140
|
+
let tmpRemote = pGalleryNav.pict.AppData.RetoldRemote;
|
|
141
|
+
if (tmpRemote.LastUsedCollectionGUID)
|
|
142
|
+
{
|
|
143
|
+
// Quick-add the currently viewed file
|
|
144
|
+
tmpCollMgr.addCurrentFileToCollection(tmpRemote.LastUsedCollectionGUID);
|
|
145
|
+
}
|
|
146
|
+
else
|
|
147
|
+
{
|
|
148
|
+
// No last-used collection — open the picker
|
|
149
|
+
let tmpTopBar = pGalleryNav.pict.views['ContentEditor-TopBar'];
|
|
150
|
+
if (tmpTopBar && typeof tmpTopBar.showAddToCollectionDropdown === 'function')
|
|
151
|
+
{
|
|
152
|
+
tmpTopBar.showAddToCollectionDropdown();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
break;
|
|
158
|
+
|
|
159
|
+
case 'b':
|
|
160
|
+
pEvent.preventDefault();
|
|
161
|
+
{
|
|
162
|
+
let tmpCollManager = pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];
|
|
163
|
+
if (tmpCollManager)
|
|
164
|
+
{
|
|
165
|
+
tmpCollManager.togglePanel();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
|
|
170
|
+
case 'd':
|
|
171
|
+
pEvent.preventDefault();
|
|
172
|
+
pGalleryNav._toggleDistractionFree();
|
|
173
|
+
break;
|
|
174
|
+
|
|
175
|
+
case '1':
|
|
176
|
+
pEvent.preventDefault();
|
|
177
|
+
pGalleryNav.switchViewerType('image');
|
|
178
|
+
break;
|
|
179
|
+
|
|
180
|
+
case '2':
|
|
181
|
+
pEvent.preventDefault();
|
|
182
|
+
pGalleryNav.switchViewerType('video');
|
|
183
|
+
break;
|
|
184
|
+
|
|
185
|
+
case '3':
|
|
186
|
+
pEvent.preventDefault();
|
|
187
|
+
pGalleryNav.switchViewerType('audio');
|
|
188
|
+
break;
|
|
189
|
+
|
|
190
|
+
case '4':
|
|
191
|
+
pEvent.preventDefault();
|
|
192
|
+
pGalleryNav.switchViewerType('text');
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
module.exports = handleViewerKey;
|
|
@@ -59,8 +59,7 @@ const _MimeTypes =
|
|
|
59
59
|
|
|
60
60
|
const _DefaultServiceConfiguration =
|
|
61
61
|
{
|
|
62
|
-
"ContentPath": "."
|
|
63
|
-
"CachePath": null
|
|
62
|
+
"ContentPath": "."
|
|
64
63
|
};
|
|
65
64
|
|
|
66
65
|
class RetoldRemoteArchiveService extends libFableServiceProviderBase
|
|
@@ -82,15 +81,6 @@ class RetoldRemoteArchiveService extends libFableServiceProviderBase
|
|
|
82
81
|
|
|
83
82
|
this.contentPath = libPath.resolve(this.options.ContentPath);
|
|
84
83
|
|
|
85
|
-
this.archiveCachePath = this.options.CachePath
|
|
86
|
-
|| libPath.join(process.cwd(), 'dist', 'retold-cache', 'archives');
|
|
87
|
-
|
|
88
|
-
// Ensure cache directory exists
|
|
89
|
-
if (!libFs.existsSync(this.archiveCachePath))
|
|
90
|
-
{
|
|
91
|
-
libFs.mkdirSync(this.archiveCachePath, { recursive: true });
|
|
92
|
-
}
|
|
93
|
-
|
|
94
84
|
// Detect 7z availability
|
|
95
85
|
let tmpDetector = new libToolDetector();
|
|
96
86
|
let tmpCapabilities = tmpDetector.detect();
|
|
@@ -246,7 +236,7 @@ class RetoldRemoteArchiveService extends libFableServiceProviderBase
|
|
|
246
236
|
|
|
247
237
|
let tmpInput = `${pArchiveAbsPath}:${tmpMtime}`;
|
|
248
238
|
let tmpHash = libCrypto.createHash('sha256').update(tmpInput).digest('hex').substring(0, 16);
|
|
249
|
-
let tmpDir =
|
|
239
|
+
let tmpDir = this.fable.ParimeBinaryStorage.resolvePath('archive-cache', tmpHash);
|
|
250
240
|
|
|
251
241
|
if (!libFs.existsSync(tmpDir))
|
|
252
242
|
{
|
|
@@ -23,7 +23,6 @@ const libChildProcess = require('child_process');
|
|
|
23
23
|
const _DefaultServiceConfiguration =
|
|
24
24
|
{
|
|
25
25
|
"ContentPath": ".",
|
|
26
|
-
"CachePath": null,
|
|
27
26
|
"DefaultPeakCount": 2000,
|
|
28
27
|
"DefaultSegmentFormat": "mp3",
|
|
29
28
|
"MaxSegmentDuration": 600
|
|
@@ -48,19 +47,10 @@ class RetoldRemoteAudioWaveformService extends libFableServiceProviderBase
|
|
|
48
47
|
|
|
49
48
|
this.contentPath = libPath.resolve(this.options.ContentPath);
|
|
50
49
|
|
|
51
|
-
this.cachePath = this.options.CachePath
|
|
52
|
-
|| libPath.join(process.cwd(), 'dist', 'retold-cache', 'audio-waveforms');
|
|
53
|
-
|
|
54
|
-
// Ensure cache directory exists
|
|
55
|
-
if (!libFs.existsSync(this.cachePath))
|
|
56
|
-
{
|
|
57
|
-
libFs.mkdirSync(this.cachePath, { recursive: true });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
50
|
// Detect audiowaveform availability
|
|
61
51
|
this.hasAudiowaveform = this._detectCommand('audiowaveform --version');
|
|
62
52
|
|
|
63
|
-
this.fable.log.info(
|
|
53
|
+
this.fable.log.info('Audio Waveform Service: using ParimeBinaryStorage (categories: audio-waveforms, audio-segments)');
|
|
64
54
|
this.fable.log.info(` audiowaveform tool: ${this.hasAudiowaveform ? 'available' : 'not found (using ffprobe fallback)'}`);
|
|
65
55
|
}
|
|
66
56
|
|
|
@@ -95,7 +85,7 @@ class RetoldRemoteAudioWaveformService extends libFableServiceProviderBase
|
|
|
95
85
|
{
|
|
96
86
|
let tmpInput = `waveform:${pAbsPath}:${pMtimeMs}:${pPeakCount}`;
|
|
97
87
|
let tmpHash = libCrypto.createHash('sha256').update(tmpInput).digest('hex').substring(0, 16);
|
|
98
|
-
return
|
|
88
|
+
return this.fable.ParimeBinaryStorage.resolvePath('audio-waveforms', tmpHash);
|
|
99
89
|
}
|
|
100
90
|
|
|
101
91
|
/**
|
|
@@ -112,7 +102,7 @@ class RetoldRemoteAudioWaveformService extends libFableServiceProviderBase
|
|
|
112
102
|
{
|
|
113
103
|
let tmpInput = `segment:${pAbsPath}:${pMtimeMs}:${pStart}:${pEnd}:${pFormat}`;
|
|
114
104
|
let tmpHash = libCrypto.createHash('sha256').update(tmpInput).digest('hex').substring(0, 16);
|
|
115
|
-
return
|
|
105
|
+
return this.fable.ParimeBinaryStorage.resolvePath('audio-segments', tmpHash);
|
|
116
106
|
}
|
|
117
107
|
|
|
118
108
|
/**
|
|
@@ -652,11 +642,12 @@ class RetoldRemoteAudioWaveformService extends libFableServiceProviderBase
|
|
|
652
642
|
return null;
|
|
653
643
|
}
|
|
654
644
|
|
|
655
|
-
let
|
|
645
|
+
let tmpCacheDir = this.fable.ParimeBinaryStorage.resolvePath('audio-segments', pCacheKey);
|
|
646
|
+
let tmpPath = libPath.join(tmpCacheDir, pFilename);
|
|
656
647
|
|
|
657
|
-
// Double-check it's under
|
|
648
|
+
// Double-check it's under the storage root
|
|
658
649
|
let tmpResolved = libPath.resolve(tmpPath);
|
|
659
|
-
if (!tmpResolved.startsWith(this.
|
|
650
|
+
if (!tmpResolved.startsWith(this.fable.ParimeBinaryStorage.storageRoot))
|
|
660
651
|
{
|
|
661
652
|
return null;
|
|
662
653
|
}
|