retold-remote 0.0.26 → 0.0.27
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/package.json +53 -1
- package/source/cli/RetoldRemote-Server-Setup.js +38 -3
- package/source/cli/commands/RetoldRemote-Command-Serve.js +25 -9
- package/source/server/RetoldRemote-ImageService.js +6 -1
- package/source/views/PictView-Remote-MediaViewer.js +15 -0
- package/web-application/retold-remote.js +6 -1
- package/web-application/retold-remote.js.map +1 -1
- package/web-application/retold-remote.min.js +6 -6
- package/web-application/retold-remote.min.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "retold-remote",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.27",
|
|
4
4
|
"description": "Retold Remote - NAS media browser with gallery views and keyboard navigation",
|
|
5
5
|
"main": "source/Pict-RetoldRemote-Bundle.js",
|
|
6
6
|
"bin": {
|
|
@@ -29,6 +29,58 @@
|
|
|
29
29
|
"docs": "npx quack prepare-docs ./docs -d ./modules",
|
|
30
30
|
"docs-serve": "npx quack docs-serve ./docs"
|
|
31
31
|
},
|
|
32
|
+
"retoldBeacon": {
|
|
33
|
+
"displayName": "Retold Remote",
|
|
34
|
+
"description": "NAS media browser with gallery views and keyboard navigation; serves a content folder over HTTP and registers as a beacon.",
|
|
35
|
+
"category": "content",
|
|
36
|
+
"mode": "standalone-service",
|
|
37
|
+
"bin": "source/cli/RetoldRemote-CLI-Run.js",
|
|
38
|
+
"argTemplate": [
|
|
39
|
+
"serve",
|
|
40
|
+
{
|
|
41
|
+
"fromLabPath": "ContentPath"
|
|
42
|
+
},
|
|
43
|
+
"-p",
|
|
44
|
+
{
|
|
45
|
+
"fromLabPath": "Port"
|
|
46
|
+
},
|
|
47
|
+
"-u",
|
|
48
|
+
{
|
|
49
|
+
"fromLabPath": "UltravisorURL"
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"healthCheck": {
|
|
53
|
+
"path": "/"
|
|
54
|
+
},
|
|
55
|
+
"defaultPort": 7777,
|
|
56
|
+
"requiresUltravisor": true,
|
|
57
|
+
"configForm": {
|
|
58
|
+
"Fields": [
|
|
59
|
+
{
|
|
60
|
+
"Name": "HostContentPath",
|
|
61
|
+
"Label": "Host folder to serve",
|
|
62
|
+
"Type": "text",
|
|
63
|
+
"Required": true,
|
|
64
|
+
"Help": "Absolute path on the host whose contents will be served; bind-mounted read-only into the container at /app/content."
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"docker": {
|
|
69
|
+
"image": "retold-remote",
|
|
70
|
+
"dockerfile": "retold-remote.Dockerfile",
|
|
71
|
+
"dataMountPath": "/app/data",
|
|
72
|
+
"configMountPath": "/app/data/config.json",
|
|
73
|
+
"contentMountPath": "/app/content",
|
|
74
|
+
"exposedPort": 7777,
|
|
75
|
+
"configMounts": [
|
|
76
|
+
{
|
|
77
|
+
"ConfigField": "HostContentPath",
|
|
78
|
+
"Target": "/app/content",
|
|
79
|
+
"ReadOnly": true
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
},
|
|
32
84
|
"author": "steven velozo <steven@velozo.com>",
|
|
33
85
|
"license": "MIT",
|
|
34
86
|
"dependencies": {
|
|
@@ -212,10 +212,25 @@ function setupRetoldRemoteServer(pOptions, fCallback)
|
|
|
212
212
|
});
|
|
213
213
|
|
|
214
214
|
// Set up the large-image preview and DZI tile service
|
|
215
|
-
let
|
|
215
|
+
let tmpImageServiceOptions = { ContentPath: tmpContentPath };
|
|
216
|
+
let tmpDirectMaxBytes = null;
|
|
217
|
+
if (typeof pOptions.DirectDisplayMaxFileSize === 'number' && pOptions.DirectDisplayMaxFileSize >= 0)
|
|
216
218
|
{
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
+
tmpDirectMaxBytes = pOptions.DirectDisplayMaxFileSize;
|
|
220
|
+
}
|
|
221
|
+
else if (process.env.RETOLD_DIRECT_IMAGE_MAX_BYTES)
|
|
222
|
+
{
|
|
223
|
+
let tmpParsed = parseInt(process.env.RETOLD_DIRECT_IMAGE_MAX_BYTES, 10);
|
|
224
|
+
if (!isNaN(tmpParsed) && tmpParsed >= 0)
|
|
225
|
+
{
|
|
226
|
+
tmpDirectMaxBytes = tmpParsed;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (tmpDirectMaxBytes !== null)
|
|
230
|
+
{
|
|
231
|
+
tmpImageServiceOptions.DirectDisplayMaxFileSize = tmpDirectMaxBytes;
|
|
232
|
+
}
|
|
233
|
+
let tmpImageService = new libRetoldRemoteImageService(tmpFable, tmpImageServiceOptions);
|
|
219
234
|
|
|
220
235
|
// Set up the subimage region service
|
|
221
236
|
let tmpSubimageService = new libRetoldRemoteSubimageService(tmpFable,
|
|
@@ -1957,6 +1972,26 @@ function setupRetoldRemoteServer(pOptions, fCallback)
|
|
|
1957
1972
|
return fNext();
|
|
1958
1973
|
}
|
|
1959
1974
|
|
|
1975
|
+
// Always surface the original file size (the manifest's FileSize
|
|
1976
|
+
// field gets overwritten with the generated preview's size when
|
|
1977
|
+
// NeedsPreview=true). The client uses OrigFileSize against
|
|
1978
|
+
// DirectDisplayMaxFileSize to decide whether to bypass the
|
|
1979
|
+
// OpenSeadragon explorer / downscaled preview and load the
|
|
1980
|
+
// source image directly.
|
|
1981
|
+
if (pResult && typeof pResult === 'object')
|
|
1982
|
+
{
|
|
1983
|
+
try
|
|
1984
|
+
{
|
|
1985
|
+
let tmpStat = libFs.statSync(tmpAbsPath);
|
|
1986
|
+
pResult.OrigFileSize = tmpStat.size;
|
|
1987
|
+
}
|
|
1988
|
+
catch (pStatError)
|
|
1989
|
+
{
|
|
1990
|
+
// Non-fatal — client will fall through to existing logic
|
|
1991
|
+
}
|
|
1992
|
+
pResult.DirectDisplayMaxFileSize = tmpImageService.options.DirectDisplayMaxFileSize;
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1960
1995
|
pResponse.send(pResult);
|
|
1961
1996
|
return fNext();
|
|
1962
1997
|
});
|
|
@@ -35,6 +35,9 @@ class RetoldRemoteCommandServe extends libCommandLineCommand
|
|
|
35
35
|
this.options.CommandOptions.push(
|
|
36
36
|
{ Name: '-l, --logfile [path]', Description: 'Write logs to a file (auto-generates timestamped name if path omitted).', Default: '' });
|
|
37
37
|
|
|
38
|
+
this.options.CommandOptions.push(
|
|
39
|
+
{ Name: '--direct-image-max-mb [mb]', Description: 'Max original-file size (MB) to display an image directly instead of via OpenSeadragon. Set to 0 to always use the explorer. Default 15.', Default: '' });
|
|
40
|
+
|
|
38
41
|
this.addCommand();
|
|
39
42
|
}
|
|
40
43
|
|
|
@@ -127,16 +130,29 @@ class RetoldRemoteCommandServe extends libCommandLineCommand
|
|
|
127
130
|
{
|
|
128
131
|
let tmpSetupServer = require('../RetoldRemote-Server-Setup.js');
|
|
129
132
|
|
|
130
|
-
|
|
133
|
+
let tmpSetupOptions =
|
|
134
|
+
{
|
|
135
|
+
ContentPath: tmpContentPath,
|
|
136
|
+
DistPath: tmpDistPath,
|
|
137
|
+
Port: tmpPort,
|
|
138
|
+
HashedFilenames: tmpHashedFilenames,
|
|
139
|
+
CacheRoot: tmpCacheRoot,
|
|
140
|
+
CacheServer: tmpCacheServer,
|
|
141
|
+
UltravisorURL: tmpUltravisorURL
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
let tmpDirectMaxMB = this.CommandOptions.directImageMaxMb;
|
|
145
|
+
if (typeof tmpDirectMaxMB === 'string' && tmpDirectMaxMB.length > 0)
|
|
146
|
+
{
|
|
147
|
+
let tmpMB = parseFloat(tmpDirectMaxMB);
|
|
148
|
+
if (!isNaN(tmpMB) && tmpMB >= 0)
|
|
131
149
|
{
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
UltravisorURL: tmpUltravisorURL
|
|
139
|
-
},
|
|
150
|
+
tmpSetupOptions.DirectDisplayMaxFileSize = Math.round(tmpMB * 1024 * 1024);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
tmpSetupServer(
|
|
155
|
+
tmpSetupOptions,
|
|
140
156
|
function (pError, pServerInfo)
|
|
141
157
|
{
|
|
142
158
|
if (pError)
|
|
@@ -49,7 +49,12 @@ const _DefaultServiceConfiguration =
|
|
|
49
49
|
"DziQuality": 80,
|
|
50
50
|
"PreviewQuality": 85,
|
|
51
51
|
// Only generate preview/tiles for images larger than this (pixels on longest side)
|
|
52
|
-
"LargeImageThreshold": 4096
|
|
52
|
+
"LargeImageThreshold": 4096,
|
|
53
|
+
// Original-file-size (bytes) at or below which the viewer will load the
|
|
54
|
+
// image directly instead of routing through the OpenSeadragon explorer or
|
|
55
|
+
// server-side downscaled preview. Raw camera formats always go through the
|
|
56
|
+
// preview pipeline regardless of size (browsers can't decode raw). 15 MiB.
|
|
57
|
+
"DirectDisplayMaxFileSize": 15 * 1024 * 1024
|
|
53
58
|
};
|
|
54
59
|
|
|
55
60
|
class RetoldRemoteImageService extends libFableServiceProviderBase
|
|
@@ -470,6 +470,7 @@ class RetoldRemoteMediaViewerView extends libPictView
|
|
|
470
470
|
|
|
471
471
|
/**
|
|
472
472
|
* Probe image dimensions, then decide how to display it:
|
|
473
|
+
* - File ≤ DirectDisplayMaxFileSize (default 15 MiB, non-raw): direct content URL
|
|
473
474
|
* - ≤4096px: load direct content URL in the normal viewer
|
|
474
475
|
* - 4096–8192px: load a server preview in the normal viewer, show Explore button
|
|
475
476
|
* - >8192px: auto-launch the OpenSeadragon image explorer
|
|
@@ -495,6 +496,20 @@ class RetoldRemoteMediaViewerView extends libPictView
|
|
|
495
496
|
return;
|
|
496
497
|
}
|
|
497
498
|
|
|
499
|
+
// Small-file short-circuit: if the original is within the configured
|
|
500
|
+
// direct-display budget and the browser can decode it natively,
|
|
501
|
+
// skip both the server preview and the OpenSeadragon explorer.
|
|
502
|
+
// Raw camera formats always go through the preview pipeline.
|
|
503
|
+
if (!pResult.IsRawFormat
|
|
504
|
+
&& typeof pResult.OrigFileSize === 'number'
|
|
505
|
+
&& typeof pResult.DirectDisplayMaxFileSize === 'number'
|
|
506
|
+
&& pResult.DirectDisplayMaxFileSize > 0
|
|
507
|
+
&& pResult.OrigFileSize <= pResult.DirectDisplayMaxFileSize)
|
|
508
|
+
{
|
|
509
|
+
tmpSelf._insertImageTag(pContentURL, pFileName, false);
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
|
|
498
513
|
let tmpLongest = Math.max(pResult.OrigWidth || 0, pResult.OrigHeight || 0);
|
|
499
514
|
|
|
500
515
|
// >8192px: auto-launch the OpenSeadragon image explorer
|
|
@@ -16128,6 +16128,7 @@ let tmpLastTap=0;let tmpOnTouchEnd=function(pEvent){let tmpNow=Date.now();if(tmp
|
|
|
16128
16128
|
* Build a lightweight placeholder while probing image dimensions.
|
|
16129
16129
|
*/_buildImagePlaceholderHTML(pFileName){let tmpEscapedName=this.pict.providers['RetoldRemote-FormattingUtilities'].escapeHTML(pFileName);return'<div id="RetoldRemote-ImagePlaceholder" style="display:flex;align-items:center;justify-content:center;height:100%;color:var(--retold-text-dim);font-size:0.85rem;">'+'Loading '+tmpEscapedName+'\u2026</div>';}/**
|
|
16130
16130
|
* Probe image dimensions, then decide how to display it:
|
|
16131
|
+
* - File ≤ DirectDisplayMaxFileSize (default 15 MiB, non-raw): direct content URL
|
|
16131
16132
|
* - ≤4096px: load direct content URL in the normal viewer
|
|
16132
16133
|
* - 4096–8192px: load a server preview in the normal viewer, show Explore button
|
|
16133
16134
|
* - >8192px: auto-launch the OpenSeadragon image explorer
|
|
@@ -16136,7 +16137,11 @@ let tmpLastTap=0;let tmpOnTouchEnd=function(pEvent){let tmpNow=Date.now();if(tmp
|
|
|
16136
16137
|
* @param {string} pContentURL - Direct content URL (fallback)
|
|
16137
16138
|
* @param {string} pFileName - Display name
|
|
16138
16139
|
*/_probeAndShowImage(pFilePath,pContentURL,pFileName){let tmpSelf=this;let tmpProvider=this.pict.providers['RetoldRemote-Provider'];let tmpPathParam=tmpProvider?tmpProvider._getPathParam(pFilePath):encodeURIComponent(pFilePath);fetch('/api/media/image-preview?path='+tmpPathParam).then(pResponse=>pResponse.json()).then(pResult=>{// If the probe failed or sharp isn't available, fall back to direct load
|
|
16139
|
-
if(!pResult||!pResult.Success){tmpSelf._insertImageTag(pContentURL,pFileName,false);return;}
|
|
16140
|
+
if(!pResult||!pResult.Success){tmpSelf._insertImageTag(pContentURL,pFileName,false);return;}// Small-file short-circuit: if the original is within the configured
|
|
16141
|
+
// direct-display budget and the browser can decode it natively,
|
|
16142
|
+
// skip both the server preview and the OpenSeadragon explorer.
|
|
16143
|
+
// Raw camera formats always go through the preview pipeline.
|
|
16144
|
+
if(!pResult.IsRawFormat&&typeof pResult.OrigFileSize==='number'&&typeof pResult.DirectDisplayMaxFileSize==='number'&&pResult.DirectDisplayMaxFileSize>0&&pResult.OrigFileSize<=pResult.DirectDisplayMaxFileSize){tmpSelf._insertImageTag(pContentURL,pFileName,false);return;}let tmpLongest=Math.max(pResult.OrigWidth||0,pResult.OrigHeight||0);// >8192px: auto-launch the OpenSeadragon image explorer
|
|
16140
16145
|
if(tmpLongest>8192){let tmpIEX=tmpSelf.pict.views['RetoldRemote-ImageExplorer'];if(tmpIEX){tmpIEX.showExplorer(pFilePath);return;}// Fall through if explorer view isn't available
|
|
16141
16146
|
}// 4096–8192px: use the server preview
|
|
16142
16147
|
if(pResult.NeedsPreview&&pResult.CacheKey){let tmpPreviewURL='/api/media/image-preview-file/'+encodeURIComponent(pResult.CacheKey)+'/'+encodeURIComponent(pResult.OutputFilename);tmpSelf._insertImageTag(tmpPreviewURL,pFileName,true,pResult.OrigWidth,pResult.OrigHeight);return;}// ≤4096px: load the direct content URL
|