retold-remote 0.0.6 → 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.
@@ -9046,7 +9046,7 @@ if(psychotic){result.hostname=isAbsolute?'':srcPath.length?srcPath.shift():'';re
9046
9046
  * url.resolveObject('mailto:local1@domain1', 'local2@domain2')
9047
9047
  */var authInHost=result.host&&result.host.indexOf('@')>0?result.host.split('@'):false;if(authInHost){result.auth=authInHost.shift();result.hostname=authInHost.shift();result.host=result.hostname;}}mustEndAbs=mustEndAbs||result.host&&srcPath.length;if(mustEndAbs&&!isAbsolute){srcPath.unshift('');}if(srcPath.length>0){result.pathname=srcPath.join('/');}else{result.pathname=null;result.path=null;}// to support request.http
9048
9048
  if(result.pathname!==null||result.search!==null){result.path=(result.pathname?result.pathname:'')+(result.search?result.search:'');}result.auth=relative.auth||result.auth;result.slashes=result.slashes||relative.slashes;result.href=result.format();return result;};Url.prototype.parseHost=function(){var host=this.host;var port=portPattern.exec(host);if(port){port=port[0];if(port!==':'){this.port=port.substr(1);}host=host.substr(0,host.length-port.length);}if(host){this.hostname=host;}};exports.parse=urlParse;exports.resolve=urlResolve;exports.resolveObject=urlResolveObject;exports.format=urlFormat;exports.Url=Url;},{"punycode/":78,"qs":80}],111:[function(require,module,exports){module.exports={"Name":"Retold Remote","MainViewportViewIdentifier":"ContentEditor-Layout","AutoSolveAfterInitialize":true,"AutoRenderMainViewportViewAfterInitialize":false,"AutoRenderViewsAfterInitialize":false};},{}],112:[function(require,module,exports){const libContentEditorApplication=require('retold-content-system').PictContentEditor;const libPictSectionFileBrowser=require('pict-section-filebrowser');// Providers
9049
- const libProviderRetoldRemote=require('./providers/Pict-Provider-RetoldRemote.js');const libProviderGalleryNavigation=require('./providers/Pict-Provider-GalleryNavigation.js');const libProviderGalleryFilterSort=require('./providers/Pict-Provider-GalleryFilterSort.js');const libProviderRetoldRemoteIcons=require('./providers/Pict-Provider-RetoldRemoteIcons.js');const libProviderRetoldRemoteTheme=require('./providers/Pict-Provider-RetoldRemoteTheme.js');const libProviderFormattingUtilities=require('./providers/Pict-Provider-FormattingUtilities.js');const libProviderToastNotification=require('./providers/Pict-Provider-ToastNotification.js');const libProviderCollectionManager=require('./providers/Pict-Provider-CollectionManager.js');// Views (replace parent views)
9049
+ const libProviderRetoldRemote=require('./providers/Pict-Provider-RetoldRemote.js');const libProviderGalleryNavigation=require('./providers/Pict-Provider-GalleryNavigation.js');const libProviderGalleryFilterSort=require('./providers/Pict-Provider-GalleryFilterSort.js');const libProviderRetoldRemoteIcons=require('./providers/Pict-Provider-RetoldRemoteIcons.js');const libProviderRetoldRemoteTheme=require('./providers/Pict-Provider-RetoldRemoteTheme.js');const libProviderFormattingUtilities=require('./providers/Pict-Provider-FormattingUtilities.js');const libProviderToastNotification=require('./providers/Pict-Provider-ToastNotification.js');const libProviderCollectionManager=require('./providers/Pict-Provider-CollectionManager.js');const libProviderAISortManager=require('./providers/Pict-Provider-AISortManager.js');// Views (replace parent views)
9050
9050
  const libViewLayout=require('./views/PictView-Remote-Layout.js');const libViewTopBar=require('./views/PictView-Remote-TopBar.js');const libViewSettingsPanel=require('./views/PictView-Remote-SettingsPanel.js');// Views (new)
9051
9051
  const libViewGallery=require('./views/PictView-Remote-Gallery.js');const libViewMediaViewer=require('./views/PictView-Remote-MediaViewer.js');const libViewImageViewer=require('./views/PictView-Remote-ImageViewer.js');const libViewVideoExplorer=require('./views/PictView-Remote-VideoExplorer.js');const libViewAudioExplorer=require('./views/PictView-Remote-AudioExplorer.js');const libViewVLCSetup=require('./views/PictView-Remote-VLCSetup.js');const libViewCollectionsPanel=require('./views/PictView-Remote-CollectionsPanel.js');// Application configuration
9052
9052
  const _DefaultConfiguration=require('./Pict-Application-RetoldRemote-Configuration.json');/**
@@ -9060,7 +9060,7 @@ const _DefaultConfiguration=require('./Pict-Application-RetoldRemote-Configurati
9060
9060
  // Re-registering with the same ViewIdentifier replaces the parent's view.
9061
9061
  this.pict.addView('ContentEditor-Layout',libViewLayout.default_configuration,libViewLayout);this.pict.addView('ContentEditor-TopBar',libViewTopBar.default_configuration,libViewTopBar);// Add new views
9062
9062
  this.pict.addView('RetoldRemote-Gallery',libViewGallery.default_configuration,libViewGallery);this.pict.addView('RetoldRemote-MediaViewer',libViewMediaViewer.default_configuration,libViewMediaViewer);this.pict.addView('RetoldRemote-ImageViewer',libViewImageViewer.default_configuration,libViewImageViewer);this.pict.addView('RetoldRemote-SettingsPanel',libViewSettingsPanel.default_configuration,libViewSettingsPanel);this.pict.addView('RetoldRemote-VideoExplorer',libViewVideoExplorer.default_configuration,libViewVideoExplorer);this.pict.addView('RetoldRemote-AudioExplorer',libViewAudioExplorer.default_configuration,libViewAudioExplorer);this.pict.addView('RetoldRemote-VLCSetup',libViewVLCSetup.default_configuration,libViewVLCSetup);this.pict.addView('RetoldRemote-CollectionsPanel',libViewCollectionsPanel.default_configuration,libViewCollectionsPanel);// Add new providers
9063
- this.pict.addProvider('RetoldRemote-Provider',libProviderRetoldRemote.default_configuration,libProviderRetoldRemote);this.pict.addProvider('RetoldRemote-GalleryNavigation',libProviderGalleryNavigation.default_configuration,libProviderGalleryNavigation);this.pict.addProvider('RetoldRemote-GalleryFilterSort',libProviderGalleryFilterSort.default_configuration,libProviderGalleryFilterSort);this.pict.addProvider('RetoldRemote-Icons',libProviderRetoldRemoteIcons.default_configuration,libProviderRetoldRemoteIcons);this.pict.addProvider('RetoldRemote-Theme',libProviderRetoldRemoteTheme.default_configuration,libProviderRetoldRemoteTheme);this.pict.addProvider('RetoldRemote-FormattingUtilities',libProviderFormattingUtilities.default_configuration,libProviderFormattingUtilities);this.pict.addProvider('RetoldRemote-ToastNotification',libProviderToastNotification.default_configuration,libProviderToastNotification);this.pict.addProvider('RetoldRemote-CollectionManager',libProviderCollectionManager.default_configuration,libProviderCollectionManager);}onAfterInitializeAsync(fCallback){// Expose pict on window for inline onclick handlers
9063
+ this.pict.addProvider('RetoldRemote-Provider',libProviderRetoldRemote.default_configuration,libProviderRetoldRemote);this.pict.addProvider('RetoldRemote-GalleryNavigation',libProviderGalleryNavigation.default_configuration,libProviderGalleryNavigation);this.pict.addProvider('RetoldRemote-GalleryFilterSort',libProviderGalleryFilterSort.default_configuration,libProviderGalleryFilterSort);this.pict.addProvider('RetoldRemote-Icons',libProviderRetoldRemoteIcons.default_configuration,libProviderRetoldRemoteIcons);this.pict.addProvider('RetoldRemote-Theme',libProviderRetoldRemoteTheme.default_configuration,libProviderRetoldRemoteTheme);this.pict.addProvider('RetoldRemote-FormattingUtilities',libProviderFormattingUtilities.default_configuration,libProviderFormattingUtilities);this.pict.addProvider('RetoldRemote-ToastNotification',libProviderToastNotification.default_configuration,libProviderToastNotification);this.pict.addProvider('RetoldRemote-CollectionManager',libProviderCollectionManager.default_configuration,libProviderCollectionManager);this.pict.addProvider('RetoldRemote-AISortManager',libProviderAISortManager.default_configuration,libProviderAISortManager);}onAfterInitializeAsync(fCallback){// Expose pict on window for inline onclick handlers
9064
9064
  if(typeof window!=='undefined'){window.pict=this.pict;}// Initialize RetoldRemote-specific state
9065
9065
  this.pict.AppData.RetoldRemote={ActiveMode:'gallery',// 'gallery' or 'viewer'
9066
9066
  Theme:'twilight',// Theme key (e.g. 'twilight', 'neo-tokyo')
@@ -9091,8 +9091,9 @@ FilterPresets:[],// [{ Name, FilterState, SortField, SortDirection }]
9091
9091
  Collections:[],// Array of collection summaries
9092
9092
  CollectionsPanelOpen:false,CollectionsPanelWidth:300,CollectionsPanelMode:'list',// 'list' | 'detail' | 'edit'
9093
9093
  ActiveCollectionGUID:null,ActiveCollection:null,CollectionSearchQuery:'',LastUsedCollectionGUID:null,BrowsingCollection:false,// true when viewer is navigating collection items
9094
- BrowsingCollectionIndex:-1// index into ActiveCollection.Items
9095
- };// Load persisted settings
9094
+ BrowsingCollectionIndex:-1,// index into ActiveCollection.Items
9095
+ // AI Sort settings
9096
+ AISortSettings:{AIEndpoint:'http://localhost:11434',AIModel:'llama3.1',AIProvider:'ollama',NamingTemplate:'{artist}/{album}/{track} - {title}'}};// Load persisted settings
9096
9097
  this._loadRemoteSettings();// Apply the loaded theme (must happen after _loadRemoteSettings sets Theme)
9097
9098
  let tmpThemeProvider=this.pict.providers['RetoldRemote-Theme'];if(tmpThemeProvider){tmpThemeProvider.applyTheme(this.pict.AppData.RetoldRemote.Theme);}// Initialize parent state (ContentEditor AppData)
9098
9099
  this.pict.AppData.ContentEditor={CurrentFile:'',ActiveEditor:'markdown',IsDirty:false,IsSaving:false,IsLoading:false,Files:[],Document:{Segments:[{Content:''}]},CodeContent:'',SaveStatus:'',SaveStatusClass:'',AutoSegmentMarkdown:false,AutoSegmentDepth:1,AutoContentPreview:false,MarkdownEditingControls:true,MarkdownWordWrap:true,CodeWordWrap:false,SidebarCollapsed:this.pict.AppData.RetoldRemote.SidebarCollapsed,SidebarWidth:this.pict.AppData.RetoldRemote.SidebarWidth,AutoPreviewImages:true,AutoPreviewVideo:false,AutoPreviewAudio:false,ShowHiddenFiles:this.pict.AppData.RetoldRemote.ShowHiddenFiles,TopicsFilePath:''};// Render the layout shell
@@ -9158,11 +9159,11 @@ let tmpFilePath=tmpFragProvider?tmpFragProvider.resolveFragmentIdentifier(tmpRaw
9158
9159
  let tmpExisting=tmpDetailRows.parentElement.querySelector('.retold-remote-sidebar-addfolder');if(tmpExisting){tmpExisting.parentElement.removeChild(tmpExisting);}let tmpBtn=document.createElement('button');tmpBtn.className='retold-remote-sidebar-addfolder';tmpBtn.textContent='+ New Folder';tmpBtn.title='Create a new folder here';tmpBtn.onclick=function(){pict.PictApplication.promptNewFolder();};// Insert after the detail rows container
9159
9160
  tmpDetailRows.parentElement.appendChild(tmpBtn);}/**
9160
9161
  * Save RetoldRemote settings to localStorage.
9161
- */saveSettings(){try{let tmpRemote=this.pict.AppData.RetoldRemote;let tmpSettings={Theme:tmpRemote.Theme,ViewMode:tmpRemote.ViewMode,ThumbnailSize:tmpRemote.ThumbnailSize,GalleryFilter:tmpRemote.GalleryFilter,ShowHiddenFiles:tmpRemote.ShowHiddenFiles,DistractionFreeShowNav:tmpRemote.DistractionFreeShowNav,ImageFitMode:tmpRemote.ImageFitMode,SidebarCollapsed:tmpRemote.SidebarCollapsed,SidebarWidth:tmpRemote.SidebarWidth,SortField:tmpRemote.SortField,SortDirection:tmpRemote.SortDirection,FilterPresets:tmpRemote.FilterPresets,FilterPanelOpen:tmpRemote.FilterPanelOpen,AutoplayVideo:tmpRemote.AutoplayVideo,AutoplayAudio:tmpRemote.AutoplayAudio,ListShowExtension:tmpRemote.ListShowExtension,ListShowSize:tmpRemote.ListShowSize,ListShowDate:tmpRemote.ListShowDate,CollectionsPanelOpen:tmpRemote.CollectionsPanelOpen,CollectionsPanelWidth:tmpRemote.CollectionsPanelWidth,LastUsedCollectionGUID:tmpRemote.LastUsedCollectionGUID};localStorage.setItem('retold-remote-settings',JSON.stringify(tmpSettings));}catch(pError){// localStorage may not be available
9162
+ */saveSettings(){try{let tmpRemote=this.pict.AppData.RetoldRemote;let tmpSettings={Theme:tmpRemote.Theme,ViewMode:tmpRemote.ViewMode,ThumbnailSize:tmpRemote.ThumbnailSize,GalleryFilter:tmpRemote.GalleryFilter,ShowHiddenFiles:tmpRemote.ShowHiddenFiles,DistractionFreeShowNav:tmpRemote.DistractionFreeShowNav,ImageFitMode:tmpRemote.ImageFitMode,SidebarCollapsed:tmpRemote.SidebarCollapsed,SidebarWidth:tmpRemote.SidebarWidth,SortField:tmpRemote.SortField,SortDirection:tmpRemote.SortDirection,FilterPresets:tmpRemote.FilterPresets,FilterPanelOpen:tmpRemote.FilterPanelOpen,AutoplayVideo:tmpRemote.AutoplayVideo,AutoplayAudio:tmpRemote.AutoplayAudio,ListShowExtension:tmpRemote.ListShowExtension,ListShowSize:tmpRemote.ListShowSize,ListShowDate:tmpRemote.ListShowDate,CollectionsPanelOpen:tmpRemote.CollectionsPanelOpen,CollectionsPanelWidth:tmpRemote.CollectionsPanelWidth,LastUsedCollectionGUID:tmpRemote.LastUsedCollectionGUID,AISortSettings:tmpRemote.AISortSettings};localStorage.setItem('retold-remote-settings',JSON.stringify(tmpSettings));}catch(pError){// localStorage may not be available
9162
9163
  }}/**
9163
9164
  * Load RetoldRemote settings from localStorage.
9164
- */_loadRemoteSettings(){try{let tmpStored=localStorage.getItem('retold-remote-settings');if(tmpStored){let tmpSettings=JSON.parse(tmpStored);let tmpRemote=this.pict.AppData.RetoldRemote;if(tmpSettings.Theme)tmpRemote.Theme=tmpSettings.Theme;if(tmpSettings.ViewMode)tmpRemote.ViewMode=tmpSettings.ViewMode;if(tmpSettings.ThumbnailSize)tmpRemote.ThumbnailSize=tmpSettings.ThumbnailSize;if(tmpSettings.GalleryFilter){tmpRemote.GalleryFilter=tmpSettings.GalleryFilter;tmpRemote.FilterState.MediaType=tmpSettings.GalleryFilter;}if(typeof tmpSettings.ShowHiddenFiles==='boolean')tmpRemote.ShowHiddenFiles=tmpSettings.ShowHiddenFiles;if(typeof tmpSettings.DistractionFreeShowNav==='boolean')tmpRemote.DistractionFreeShowNav=tmpSettings.DistractionFreeShowNav;if(tmpSettings.ImageFitMode)tmpRemote.ImageFitMode=tmpSettings.ImageFitMode;if(typeof tmpSettings.SidebarCollapsed==='boolean')tmpRemote.SidebarCollapsed=tmpSettings.SidebarCollapsed;if(tmpSettings.SidebarWidth)tmpRemote.SidebarWidth=tmpSettings.SidebarWidth;if(tmpSettings.SortField)tmpRemote.SortField=tmpSettings.SortField;if(tmpSettings.SortDirection)tmpRemote.SortDirection=tmpSettings.SortDirection;if(Array.isArray(tmpSettings.FilterPresets))tmpRemote.FilterPresets=tmpSettings.FilterPresets;if(typeof tmpSettings.FilterPanelOpen==='boolean')tmpRemote.FilterPanelOpen=tmpSettings.FilterPanelOpen;if(typeof tmpSettings.AutoplayVideo==='boolean')tmpRemote.AutoplayVideo=tmpSettings.AutoplayVideo;if(typeof tmpSettings.AutoplayAudio==='boolean')tmpRemote.AutoplayAudio=tmpSettings.AutoplayAudio;if(typeof tmpSettings.ListShowExtension==='boolean')tmpRemote.ListShowExtension=tmpSettings.ListShowExtension;if(typeof tmpSettings.ListShowSize==='boolean')tmpRemote.ListShowSize=tmpSettings.ListShowSize;if(typeof tmpSettings.ListShowDate==='boolean')tmpRemote.ListShowDate=tmpSettings.ListShowDate;if(typeof tmpSettings.CollectionsPanelOpen==='boolean')tmpRemote.CollectionsPanelOpen=tmpSettings.CollectionsPanelOpen;if(tmpSettings.CollectionsPanelWidth)tmpRemote.CollectionsPanelWidth=tmpSettings.CollectionsPanelWidth;if(tmpSettings.LastUsedCollectionGUID)tmpRemote.LastUsedCollectionGUID=tmpSettings.LastUsedCollectionGUID;}}catch(pError){// localStorage may not be available
9165
- }}}module.exports=RetoldRemoteApplication;},{"./Pict-Application-RetoldRemote-Configuration.json":111,"./providers/Pict-Provider-CollectionManager.js":115,"./providers/Pict-Provider-FormattingUtilities.js":116,"./providers/Pict-Provider-GalleryFilterSort.js":117,"./providers/Pict-Provider-GalleryNavigation.js":118,"./providers/Pict-Provider-RetoldRemote.js":119,"./providers/Pict-Provider-RetoldRemoteIcons.js":120,"./providers/Pict-Provider-RetoldRemoteTheme.js":121,"./providers/Pict-Provider-ToastNotification.js":122,"./views/PictView-Remote-AudioExplorer.js":128,"./views/PictView-Remote-CollectionsPanel.js":129,"./views/PictView-Remote-Gallery.js":130,"./views/PictView-Remote-ImageViewer.js":131,"./views/PictView-Remote-Layout.js":132,"./views/PictView-Remote-MediaViewer.js":133,"./views/PictView-Remote-SettingsPanel.js":134,"./views/PictView-Remote-TopBar.js":135,"./views/PictView-Remote-VLCSetup.js":136,"./views/PictView-Remote-VideoExplorer.js":137,"pict-section-filebrowser":54,"retold-content-system":97}],113:[function(require,module,exports){/**
9165
+ */_loadRemoteSettings(){try{let tmpStored=localStorage.getItem('retold-remote-settings');if(tmpStored){let tmpSettings=JSON.parse(tmpStored);let tmpRemote=this.pict.AppData.RetoldRemote;if(tmpSettings.Theme)tmpRemote.Theme=tmpSettings.Theme;if(tmpSettings.ViewMode)tmpRemote.ViewMode=tmpSettings.ViewMode;if(tmpSettings.ThumbnailSize)tmpRemote.ThumbnailSize=tmpSettings.ThumbnailSize;if(tmpSettings.GalleryFilter){tmpRemote.GalleryFilter=tmpSettings.GalleryFilter;tmpRemote.FilterState.MediaType=tmpSettings.GalleryFilter;}if(typeof tmpSettings.ShowHiddenFiles==='boolean')tmpRemote.ShowHiddenFiles=tmpSettings.ShowHiddenFiles;if(typeof tmpSettings.DistractionFreeShowNav==='boolean')tmpRemote.DistractionFreeShowNav=tmpSettings.DistractionFreeShowNav;if(tmpSettings.ImageFitMode)tmpRemote.ImageFitMode=tmpSettings.ImageFitMode;if(typeof tmpSettings.SidebarCollapsed==='boolean')tmpRemote.SidebarCollapsed=tmpSettings.SidebarCollapsed;if(tmpSettings.SidebarWidth)tmpRemote.SidebarWidth=tmpSettings.SidebarWidth;if(tmpSettings.SortField)tmpRemote.SortField=tmpSettings.SortField;if(tmpSettings.SortDirection)tmpRemote.SortDirection=tmpSettings.SortDirection;if(Array.isArray(tmpSettings.FilterPresets))tmpRemote.FilterPresets=tmpSettings.FilterPresets;if(typeof tmpSettings.FilterPanelOpen==='boolean')tmpRemote.FilterPanelOpen=tmpSettings.FilterPanelOpen;if(typeof tmpSettings.AutoplayVideo==='boolean')tmpRemote.AutoplayVideo=tmpSettings.AutoplayVideo;if(typeof tmpSettings.AutoplayAudio==='boolean')tmpRemote.AutoplayAudio=tmpSettings.AutoplayAudio;if(typeof tmpSettings.ListShowExtension==='boolean')tmpRemote.ListShowExtension=tmpSettings.ListShowExtension;if(typeof tmpSettings.ListShowSize==='boolean')tmpRemote.ListShowSize=tmpSettings.ListShowSize;if(typeof tmpSettings.ListShowDate==='boolean')tmpRemote.ListShowDate=tmpSettings.ListShowDate;if(typeof tmpSettings.CollectionsPanelOpen==='boolean')tmpRemote.CollectionsPanelOpen=tmpSettings.CollectionsPanelOpen;if(tmpSettings.CollectionsPanelWidth)tmpRemote.CollectionsPanelWidth=tmpSettings.CollectionsPanelWidth;if(tmpSettings.LastUsedCollectionGUID)tmpRemote.LastUsedCollectionGUID=tmpSettings.LastUsedCollectionGUID;if(tmpSettings.AISortSettings&&typeof tmpSettings.AISortSettings==='object'){if(tmpSettings.AISortSettings.AIEndpoint)tmpRemote.AISortSettings.AIEndpoint=tmpSettings.AISortSettings.AIEndpoint;if(tmpSettings.AISortSettings.AIModel)tmpRemote.AISortSettings.AIModel=tmpSettings.AISortSettings.AIModel;if(tmpSettings.AISortSettings.AIProvider)tmpRemote.AISortSettings.AIProvider=tmpSettings.AISortSettings.AIProvider;if(tmpSettings.AISortSettings.NamingTemplate)tmpRemote.AISortSettings.NamingTemplate=tmpSettings.AISortSettings.NamingTemplate;}}}catch(pError){// localStorage may not be available
9166
+ }}}module.exports=RetoldRemoteApplication;},{"./Pict-Application-RetoldRemote-Configuration.json":111,"./providers/Pict-Provider-AISortManager.js":115,"./providers/Pict-Provider-CollectionManager.js":116,"./providers/Pict-Provider-FormattingUtilities.js":117,"./providers/Pict-Provider-GalleryFilterSort.js":118,"./providers/Pict-Provider-GalleryNavigation.js":119,"./providers/Pict-Provider-RetoldRemote.js":120,"./providers/Pict-Provider-RetoldRemoteIcons.js":121,"./providers/Pict-Provider-RetoldRemoteTheme.js":122,"./providers/Pict-Provider-ToastNotification.js":123,"./views/PictView-Remote-AudioExplorer.js":129,"./views/PictView-Remote-CollectionsPanel.js":130,"./views/PictView-Remote-Gallery.js":131,"./views/PictView-Remote-ImageViewer.js":132,"./views/PictView-Remote-Layout.js":133,"./views/PictView-Remote-MediaViewer.js":134,"./views/PictView-Remote-SettingsPanel.js":135,"./views/PictView-Remote-TopBar.js":136,"./views/PictView-Remote-VLCSetup.js":137,"./views/PictView-Remote-VideoExplorer.js":138,"pict-section-filebrowser":54,"retold-content-system":97}],113:[function(require,module,exports){/**
9166
9167
  * Retold Remote -- Browser Bundle Entry
9167
9168
  *
9168
9169
  * Exports the RetoldRemote application class for browser consumption.
@@ -9177,6 +9178,78 @@ tmpDetailRows.parentElement.appendChild(tmpBtn);}/**
9177
9178
  * @param {string} pExtension - Extension with or without leading dot (e.g. '.png' or 'png')
9178
9179
  * @returns {string} 'image', 'video', 'audio', 'document', or 'other'
9179
9180
  */function getCategory(pExtension){let tmpExt=(pExtension||'').replace(/^\./,'').toLowerCase();if(ImageExtensions[tmpExt])return'image';if(VideoExtensions[tmpExt])return'video';if(AudioExtensions[tmpExt])return'audio';if(DocumentExtensions[tmpExt])return'document';return'other';}module.exports.ImageExtensions=ImageExtensions;module.exports.VideoExtensions=VideoExtensions;module.exports.AudioExtensions=AudioExtensions;module.exports.DocumentExtensions=DocumentExtensions;module.exports.getCategory=getCategory;},{}],115:[function(require,module,exports){/**
9181
+ * Retold Remote -- AI Sort Manager Provider
9182
+ *
9183
+ * Client-side state management and API communication for the
9184
+ * AI-powered file sorting feature. Manages AI endpoint settings,
9185
+ * connection testing, folder scanning, and sort plan generation.
9186
+ *
9187
+ * Sort plans are created as operation-plan collections, so all
9188
+ * preview, editing, and execution happens through the existing
9189
+ * collections infrastructure.
9190
+ *
9191
+ * Settings are persisted via localStorage alongside other RetoldRemote
9192
+ * settings.
9193
+ *
9194
+ * @license MIT
9195
+ */const libPictProvider=require('pict-provider');const _DefaultProviderConfiguration={ProviderIdentifier:'RetoldRemote-AISortManager',AutoInitialize:true,AutoSolveWithApp:false};class AISortManagerProvider extends libPictProvider{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);// Track in-progress operations
9196
+ this._generating=false;this._scanning=false;this._testingConnection=false;}// -- State Accessors --------------------------------------------------
9197
+ /**
9198
+ * Shortcut to the RetoldRemote AppData namespace.
9199
+ */_getRemote(){return this.pict.AppData.RetoldRemote;}/**
9200
+ * Get the AI sort settings from AppData.
9201
+ */_getSettings(){let tmpRemote=this._getRemote();if(!tmpRemote.AISortSettings){tmpRemote.AISortSettings={AIEndpoint:'http://localhost:11434',AIModel:'llama3.1',AIProvider:'ollama',NamingTemplate:'{artist}/{album}/{track} - {title}'};}return tmpRemote.AISortSettings;}/**
9202
+ * Get the toast notification provider.
9203
+ */_getToast(){return this.pict.providers['RetoldRemote-ToastNotification'];}/**
9204
+ * Get the collection manager provider.
9205
+ */_getCollectionManager(){return this.pict.providers['RetoldRemote-CollectionManager'];}// -- Settings Management ----------------------------------------------
9206
+ /**
9207
+ * Update AI sort settings.
9208
+ *
9209
+ * @param {object} pSettings - Settings object with any of: AIEndpoint, AIModel, AIProvider, NamingTemplate
9210
+ */updateSettings(pSettings){let tmpSettings=this._getSettings();if(pSettings.AIEndpoint!==undefined){tmpSettings.AIEndpoint=pSettings.AIEndpoint;}if(pSettings.AIModel!==undefined){tmpSettings.AIModel=pSettings.AIModel;}if(pSettings.AIProvider!==undefined){tmpSettings.AIProvider=pSettings.AIProvider;}if(pSettings.NamingTemplate!==undefined){tmpSettings.NamingTemplate=pSettings.NamingTemplate;}// Persist settings
9211
+ this.pict.PictApplication.saveSettings();}// -- API Methods ------------------------------------------------------
9212
+ /**
9213
+ * Test the AI endpoint connection.
9214
+ *
9215
+ * @param {Function} [fCallback] - Optional callback(pError, pResult)
9216
+ */testConnection(fCallback){let tmpSelf=this;let tmpCallback=typeof fCallback==='function'?fCallback:()=>{};if(this._testingConnection){return tmpCallback(new Error('Connection test already in progress'));}this._testingConnection=true;let tmpSettings=this._getSettings();let tmpToast=this._getToast();fetch('/api/ai-sort/test-connection',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({AIEndpoint:tmpSettings.AIEndpoint,AIModel:tmpSettings.AIModel,AIProvider:tmpSettings.AIProvider})}).then(pResponse=>pResponse.json()).then(pData=>{tmpSelf._testingConnection=false;if(pData.Success){if(tmpToast){tmpToast.show('AI connected ('+pData.ResponseTime+'ms)');}}else{if(tmpToast){tmpToast.show('AI connection failed: '+(pData.Error||'Unknown error'));}}// Update the test button state if settings panel is open
9217
+ tmpSelf._updateTestButtonState(pData.Success);return tmpCallback(null,pData);}).catch(pError=>{tmpSelf._testingConnection=false;if(tmpToast){tmpToast.show('AI connection error: '+pError.message);}tmpSelf._updateTestButtonState(false);return tmpCallback(pError);});}/**
9218
+ * Scan a folder for audio files and return metadata.
9219
+ *
9220
+ * @param {string} pPath - Folder path relative to content root
9221
+ * @param {boolean} [pRecursive] - Scan subdirectories
9222
+ * @param {Function} [fCallback] - Optional callback(pError, pResult)
9223
+ */scanFolder(pPath,pRecursive,fCallback){let tmpSelf=this;let tmpCallback=typeof fCallback==='function'?fCallback:()=>{};if(this._scanning){return tmpCallback(new Error('Scan already in progress'));}this._scanning=true;fetch('/api/ai-sort/scan',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({Path:pPath||'',Recursive:pRecursive||false})}).then(pResponse=>pResponse.json()).then(pData=>{tmpSelf._scanning=false;let tmpToast=tmpSelf._getToast();if(tmpToast){if(pData.Success){tmpToast.show('Scanned '+pData.FileCount+' audio files');}else{tmpToast.show('Scan failed: '+(pData.Error||'Unknown error'));}}return tmpCallback(null,pData);}).catch(pError=>{tmpSelf._scanning=false;let tmpToast=tmpSelf._getToast();if(tmpToast){tmpToast.show('Scan error: '+pError.message);}return tmpCallback(pError);});}/**
9224
+ * Generate a sort plan for a folder.
9225
+ *
9226
+ * Creates an operation-plan collection and opens it in the
9227
+ * collections panel for preview and editing.
9228
+ *
9229
+ * @param {string} pPath - Folder path relative to content root
9230
+ * @param {Function} [fCallback] - Optional callback(pError, pResult)
9231
+ */generateSortPlan(pPath,fCallback){let tmpSelf=this;let tmpCallback=typeof fCallback==='function'?fCallback:()=>{};if(this._generating){let tmpToast=this._getToast();if(tmpToast){tmpToast.show('Sort plan generation already in progress...');}return tmpCallback(new Error('Generation already in progress'));}this._generating=true;let tmpSettings=this._getSettings();let tmpToast=this._getToast();if(tmpToast){tmpToast.show('Generating sort plan...');}fetch('/api/ai-sort/generate-plan',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({Path:pPath||'',NamingTemplate:tmpSettings.NamingTemplate,Recursive:true,AIEndpoint:tmpSettings.AIEndpoint,AIModel:tmpSettings.AIModel,AIProvider:tmpSettings.AIProvider})}).then(pResponse=>pResponse.json()).then(pData=>{tmpSelf._generating=false;if(!pData.Success){if(tmpToast){tmpToast.show('Sort plan failed: '+(pData.Error||pData.Message||'Unknown error'));}return tmpCallback(new Error(pData.Error||pData.Message));}if(!pData.CollectionGUID){if(tmpToast){tmpToast.show(pData.Message||'No audio files found');}return tmpCallback(null,pData);}// Open the generated collection in the panel
9232
+ let tmpCollManager=tmpSelf._getCollectionManager();if(tmpCollManager){let tmpRemote=tmpSelf._getRemote();tmpRemote.CollectionsPanelMode='detail';if(!tmpRemote.CollectionsPanelOpen){tmpCollManager.togglePanel();}tmpCollManager.fetchCollection(pData.CollectionGUID);tmpCollManager.fetchCollections();}if(tmpToast){let tmpMsg='Sort plan created: '+pData.TotalFiles+' files';if(pData.TaggedFiles>0){tmpMsg+=' ('+pData.TaggedFiles+' by tags';if(pData.AIFiles>0){tmpMsg+=', '+pData.AIFiles+' by AI';}tmpMsg+=')';}tmpToast.show(tmpMsg);}return tmpCallback(null,pData);}).catch(pError=>{tmpSelf._generating=false;if(tmpToast){tmpToast.show('Sort plan error: '+pError.message);}return tmpCallback(pError);});}// -- UI Helpers --------------------------------------------------------
9233
+ /**
9234
+ * Update the test connection button state in the settings panel.
9235
+ *
9236
+ * @param {boolean} pSuccess - Whether the test was successful
9237
+ */_updateTestButtonState(pSuccess){let tmpBtn=document.getElementById('RetoldRemote-AISortTestBtn');if(!tmpBtn){return;}tmpBtn.disabled=false;if(pSuccess===true){tmpBtn.style.borderColor='var(--retold-accent)';tmpBtn.style.color='var(--retold-accent)';tmpBtn.textContent='Connected';setTimeout(()=>{tmpBtn.textContent='Test Connection';tmpBtn.style.borderColor='';tmpBtn.style.color='';},3000);}else if(pSuccess===false){tmpBtn.style.borderColor='var(--retold-danger-muted)';tmpBtn.style.color='var(--retold-danger-muted)';tmpBtn.textContent='Failed';setTimeout(()=>{tmpBtn.textContent='Test Connection';tmpBtn.style.borderColor='';tmpBtn.style.color='';},3000);}}/**
9238
+ * Get a preview of the naming template with sample data.
9239
+ *
9240
+ * @param {string} pTemplate - Naming template
9241
+ * @returns {string} Preview string
9242
+ */getTemplatePreview(pTemplate){let tmpTemplate=pTemplate||'{artist}/{album}/{track} - {title}';let tmpPreview=tmpTemplate.replace(/\{artist\}/gi,'Pink Floyd').replace(/\{album\}/gi,'Dark Side of the Moon').replace(/\{title\}/gi,'Time').replace(/\{track\}/gi,'04').replace(/\{year\}/gi,'1973').replace(/\{genre\}/gi,'Progressive Rock');return tmpPreview+'.mp3';}/**
9243
+ * Whether the AI sort button should be visible for the current folder.
9244
+ *
9245
+ * Returns true if we're in gallery mode (browsing a folder).
9246
+ *
9247
+ * @returns {boolean}
9248
+ */isAvailable(){let tmpRemote=this._getRemote();return tmpRemote.ActiveMode==='gallery';}/**
9249
+ * Whether a generation is currently in progress.
9250
+ *
9251
+ * @returns {boolean}
9252
+ */isGenerating(){return this._generating;}}AISortManagerProvider.default_configuration=_DefaultProviderConfiguration;module.exports=AISortManagerProvider;},{"pict-provider":46}],116:[function(require,module,exports){/**
9180
9253
  * Retold Remote -- Collection Manager Provider
9181
9254
  *
9182
9255
  * Client-side state management and API communication for the
@@ -9335,7 +9408,39 @@ fetch('/api/collections/'+encodeURIComponent(tmpCollection.GUID),{method:'PUT',h
9335
9408
  *
9336
9409
  * @param {string} pQuery - Search query
9337
9410
  * @returns {Array} Filtered collection summaries
9338
- */searchCollections(pQuery){let tmpRemote=this._getRemote();let tmpQuery=(pQuery||'').toLowerCase();if(!tmpQuery){return tmpRemote.Collections;}return tmpRemote.Collections.filter(pCollection=>{let tmpName=(pCollection.Name||'').toLowerCase();let tmpDesc=(pCollection.Description||'').toLowerCase();let tmpTags=(pCollection.Tags||[]).join(' ').toLowerCase();return tmpName.indexOf(tmpQuery)>=0||tmpDesc.indexOf(tmpQuery)>=0||tmpTags.indexOf(tmpQuery)>=0;});}}CollectionManagerProvider.default_configuration=_DefaultProviderConfiguration;module.exports=CollectionManagerProvider;},{"pict-provider":46}],116:[function(require,module,exports){const libPictProvider=require('pict-provider');const _DefaultProviderConfiguration={ProviderIdentifier:'RetoldRemote-FormattingUtilities',AutoInitialize:true,AutoSolveWithApp:false};class FormattingUtilitiesProvider extends libPictProvider{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='RetoldRemoteProvider';}/**
9411
+ */searchCollections(pQuery){let tmpRemote=this._getRemote();let tmpQuery=(pQuery||'').toLowerCase();if(!tmpQuery){return tmpRemote.Collections;}return tmpRemote.Collections.filter(pCollection=>{let tmpName=(pCollection.Name||'').toLowerCase();let tmpDesc=(pCollection.Description||'').toLowerCase();let tmpTags=(pCollection.Tags||[]).join(' ').toLowerCase();return tmpName.indexOf(tmpQuery)>=0||tmpDesc.indexOf(tmpQuery)>=0||tmpTags.indexOf(tmpQuery)>=0;});}// -- Operation Plan Methods -------------------------------------------
9412
+ /**
9413
+ * Create an operation-plan collection with pre-populated items.
9414
+ *
9415
+ * @param {string} pName - Plan name
9416
+ * @param {Array} pItems - Items with Operation and DestinationPath set
9417
+ * @param {Function} [fCallback] - Optional callback(pError, pCollection)
9418
+ */createOperationPlan(pName,pItems,fCallback){let tmpSelf=this;let tmpCallback=typeof fCallback==='function'?fCallback:()=>{};let tmpGUID=this.fable.getUUID();let tmpCollectionData={Name:pName||'Sort Plan',CollectionType:'operation-plan',Items:pItems||[]};fetch('/api/collections/'+encodeURIComponent(tmpGUID),{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(tmpCollectionData)}).then(pResponse=>pResponse.json()).then(pData=>{let tmpRemote=tmpSelf._getRemote();// Open the panel and navigate to this collection
9419
+ tmpRemote.ActiveCollectionGUID=tmpGUID;tmpRemote.ActiveCollection=pData;tmpRemote.CollectionsPanelMode='detail';if(!tmpRemote.CollectionsPanelOpen){tmpSelf.togglePanel();}else{let tmpPanel=tmpSelf._getPanelView();if(tmpPanel){tmpPanel.renderContent();}}// Refresh the list
9420
+ tmpSelf.fetchCollections();let tmpToast=tmpSelf._getToast();if(tmpToast){tmpToast.show('Sort plan created: '+(pData.Name||pName));}return tmpCallback(null,pData);}).catch(pError=>{tmpSelf.log.error('Failed to create operation plan: '+pError.message);return tmpCallback(pError);});}/**
9421
+ * Execute all pending operations in a collection.
9422
+ *
9423
+ * @param {string} pGUID - Collection GUID
9424
+ * @param {Function} [fCallback] - Optional callback(pError, pResult)
9425
+ */executeCollectionOperations(pGUID,fCallback){let tmpSelf=this;let tmpCallback=typeof fCallback==='function'?fCallback:()=>{};fetch('/api/collections/'+encodeURIComponent(pGUID)+'/execute',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({})}).then(pResponse=>pResponse.json()).then(pData=>{let tmpRemote=tmpSelf._getRemote();if(pData.Collection&&tmpRemote.ActiveCollectionGUID===pGUID){tmpRemote.ActiveCollection=pData.Collection;}let tmpPanel=tmpSelf._getPanelView();if(tmpPanel){tmpPanel.renderContent();}let tmpToast=tmpSelf._getToast();if(tmpToast){if(pData.TotalFailed>0){tmpToast.show('Moved '+pData.TotalMoved+' files ('+pData.TotalFailed+' failed)');}else{tmpToast.show('Successfully moved '+pData.TotalMoved+' files');}}return tmpCallback(null,pData);}).catch(pError=>{tmpSelf.log.error('Failed to execute operations: '+pError.message);let tmpToast=tmpSelf._getToast();if(tmpToast){tmpToast.show('Failed to execute operations: '+pError.message);}return tmpCallback(pError);});}/**
9426
+ * Undo the last batch of operations for a collection.
9427
+ *
9428
+ * @param {string} pGUID - Collection GUID
9429
+ * @param {Function} [fCallback] - Optional callback(pError, pResult)
9430
+ */undoCollectionOperations(pGUID,fCallback){let tmpSelf=this;let tmpCallback=typeof fCallback==='function'?fCallback:()=>{};let tmpRemote=this._getRemote();let tmpCollection=tmpRemote.ActiveCollection;if(!tmpCollection||!tmpCollection.OperationBatchGUID){let tmpToast=tmpSelf._getToast();if(tmpToast){tmpToast.show('No batch to undo');}return tmpCallback(new Error('No batch to undo'));}fetch('/api/files/undo-batch',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({BatchGUID:tmpCollection.OperationBatchGUID})}).then(pResponse=>pResponse.json()).then(pData=>{// Reset operation statuses back to pending
9431
+ if(tmpCollection.Items){for(let i=0;i<tmpCollection.Items.length;i++){if(tmpCollection.Items[i].OperationStatus==='completed'){tmpCollection.Items[i].OperationStatus='pending';}}}tmpCollection.OperationBatchGUID=null;// Save updated collection
9432
+ tmpSelf.updateCollection(tmpCollection);let tmpPanel=tmpSelf._getPanelView();if(tmpPanel){tmpPanel.renderContent();}let tmpToast=tmpSelf._getToast();if(tmpToast){tmpToast.show('Undo complete: '+pData.TotalReversed+' files restored');}return tmpCallback(null,pData);}).catch(pError=>{tmpSelf.log.error('Failed to undo operations: '+pError.message);let tmpToast=tmpSelf._getToast();if(tmpToast){tmpToast.show('Failed to undo: '+pError.message);}return tmpCallback(pError);});}/**
9433
+ * Update a single item's destination path in the active collection.
9434
+ *
9435
+ * @param {string} pItemID - Item ID
9436
+ * @param {string} pNewDestPath - New destination path
9437
+ */setItemDestination(pItemID,pNewDestPath){let tmpRemote=this._getRemote();let tmpCollection=tmpRemote.ActiveCollection;if(!tmpCollection||!tmpCollection.Items){return;}for(let i=0;i<tmpCollection.Items.length;i++){if(tmpCollection.Items[i].ID===pItemID){tmpCollection.Items[i].DestinationPath=pNewDestPath;break;}}// Save to server in background
9438
+ this.updateCollection(tmpCollection);}/**
9439
+ * Skip an item's operation (set status to 'skipped').
9440
+ *
9441
+ * @param {string} pItemID - Item ID
9442
+ */skipItemOperation(pItemID){let tmpRemote=this._getRemote();let tmpCollection=tmpRemote.ActiveCollection;if(!tmpCollection||!tmpCollection.Items){return;}for(let i=0;i<tmpCollection.Items.length;i++){if(tmpCollection.Items[i].ID===pItemID){tmpCollection.Items[i].OperationStatus='skipped';break;}}let tmpPanel=this._getPanelView();if(tmpPanel){tmpPanel.renderContent();}// Save to server in background
9443
+ this.updateCollection(tmpCollection);}}CollectionManagerProvider.default_configuration=_DefaultProviderConfiguration;module.exports=CollectionManagerProvider;},{"pict-provider":46}],117:[function(require,module,exports){const libPictProvider=require('pict-provider');const _DefaultProviderConfiguration={ProviderIdentifier:'RetoldRemote-FormattingUtilities',AutoInitialize:true,AutoSolveWithApp:false};class FormattingUtilitiesProvider extends libPictProvider{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='RetoldRemoteProvider';}/**
9339
9444
  * Escape HTML special characters for safe insertion into markup.
9340
9445
  *
9341
9446
  * @param {string} pText - Raw text to escape
@@ -9357,7 +9462,7 @@ fetch('/api/collections/'+encodeURIComponent(tmpCollection.GUID),{method:'PUT',h
9357
9462
  * @param {number} pSeconds - Duration in seconds
9358
9463
  * @param {boolean} pIncludeMilliseconds - If true, append tenths of a second
9359
9464
  * @returns {string} Formatted string like "1:23" or "1:02:34.5"
9360
- */formatTimestamp(pSeconds,pIncludeMilliseconds){if(pSeconds===null||pSeconds===undefined||isNaN(pSeconds)){return'--';}let tmpHours=Math.floor(pSeconds/3600);let tmpMinutes=Math.floor(pSeconds%3600/60);let tmpSecs=Math.floor(pSeconds%60);let tmpResult;if(tmpHours>0){tmpResult=tmpHours+':'+String(tmpMinutes).padStart(2,'0')+':'+String(tmpSecs).padStart(2,'0');}else{tmpResult=tmpMinutes+':'+String(tmpSecs).padStart(2,'0');}if(pIncludeMilliseconds){let tmpMs=Math.floor(pSeconds%1*10);tmpResult+='.'+tmpMs;}return tmpResult;}}FormattingUtilitiesProvider.default_configuration=_DefaultProviderConfiguration;module.exports=FormattingUtilitiesProvider;},{"pict-provider":46}],117:[function(require,module,exports){const libPictProvider=require('pict-provider');const libExtensionMaps=require('../RetoldRemote-ExtensionMaps.js');const _DefaultProviderConfiguration={ProviderIdentifier:'RetoldRemote-GalleryFilterSort',AutoInitialize:true,AutoInitializeOrdinal:0,AutoSolveWithApp:false};class GalleryFilterSortProvider extends libPictProvider{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);}// ──────────────────────────────────────────────
9465
+ */formatTimestamp(pSeconds,pIncludeMilliseconds){if(pSeconds===null||pSeconds===undefined||isNaN(pSeconds)){return'--';}let tmpHours=Math.floor(pSeconds/3600);let tmpMinutes=Math.floor(pSeconds%3600/60);let tmpSecs=Math.floor(pSeconds%60);let tmpResult;if(tmpHours>0){tmpResult=tmpHours+':'+String(tmpMinutes).padStart(2,'0')+':'+String(tmpSecs).padStart(2,'0');}else{tmpResult=tmpMinutes+':'+String(tmpSecs).padStart(2,'0');}if(pIncludeMilliseconds){let tmpMs=Math.floor(pSeconds%1*10);tmpResult+='.'+tmpMs;}return tmpResult;}}FormattingUtilitiesProvider.default_configuration=_DefaultProviderConfiguration;module.exports=FormattingUtilitiesProvider;},{"pict-provider":46}],118:[function(require,module,exports){const libPictProvider=require('pict-provider');const libExtensionMaps=require('../RetoldRemote-ExtensionMaps.js');const _DefaultProviderConfiguration={ProviderIdentifier:'RetoldRemote-GalleryFilterSort',AutoInitialize:true,AutoInitializeOrdinal:0,AutoSolveWithApp:false};class GalleryFilterSortProvider extends libPictProvider{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);}// ──────────────────────────────────────────────
9361
9466
  // Pipeline
9362
9467
  // ──────────────────────────────────────────────
9363
9468
  /**
@@ -9451,7 +9556,7 @@ if(tmpRemote.SearchQuery){let tmpSearchLabel='Search: "'+tmpRemote.SearchQuery+'
9451
9556
  * Delete a saved preset.
9452
9557
  *
9453
9558
  * @param {number} pIndex - index into FilterPresets array
9454
- */deletePreset(pIndex){let tmpRemote=this.pict.AppData.RetoldRemote;if(!tmpRemote||!tmpRemote.FilterPresets){return;}tmpRemote.FilterPresets.splice(pIndex,1);}}GalleryFilterSortProvider.default_configuration=_DefaultProviderConfiguration;module.exports=GalleryFilterSortProvider;},{"../RetoldRemote-ExtensionMaps.js":114,"pict-provider":46}],118:[function(require,module,exports){const libPictProvider=require('pict-provider');const libHandleGalleryKey=require('./keyboard-handlers/KeyHandler-Gallery.js');const libHandleViewerKey=require('./keyboard-handlers/KeyHandler-Viewer.js');const libHandleSidebarKey=require('./keyboard-handlers/KeyHandler-Sidebar.js');const libHandleVideoExplorerKey=require('./keyboard-handlers/KeyHandler-VideoExplorer.js');const libHandleAudioExplorerKey=require('./keyboard-handlers/KeyHandler-AudioExplorer.js');const _DefaultProviderConfiguration={ProviderIdentifier:'RetoldRemote-GalleryNavigation',AutoInitialize:true,AutoSolveWithApp:false};class GalleryNavigationProvider extends libPictProvider{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this._columnsPerRow=4;this._keydownBound=false;this._helpPanelVisible=false;this._sidebarFocused=false;this._sidebarCursorIndex=0;}/**
9559
+ */deletePreset(pIndex){let tmpRemote=this.pict.AppData.RetoldRemote;if(!tmpRemote||!tmpRemote.FilterPresets){return;}tmpRemote.FilterPresets.splice(pIndex,1);}}GalleryFilterSortProvider.default_configuration=_DefaultProviderConfiguration;module.exports=GalleryFilterSortProvider;},{"../RetoldRemote-ExtensionMaps.js":114,"pict-provider":46}],119:[function(require,module,exports){const libPictProvider=require('pict-provider');const libHandleGalleryKey=require('./keyboard-handlers/KeyHandler-Gallery.js');const libHandleViewerKey=require('./keyboard-handlers/KeyHandler-Viewer.js');const libHandleSidebarKey=require('./keyboard-handlers/KeyHandler-Sidebar.js');const libHandleVideoExplorerKey=require('./keyboard-handlers/KeyHandler-VideoExplorer.js');const libHandleAudioExplorerKey=require('./keyboard-handlers/KeyHandler-AudioExplorer.js');const _DefaultProviderConfiguration={ProviderIdentifier:'RetoldRemote-GalleryNavigation',AutoInitialize:true,AutoSolveWithApp:false};class GalleryNavigationProvider extends libPictProvider{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this._columnsPerRow=4;this._keydownBound=false;this._helpPanelVisible=false;this._sidebarFocused=false;this._sidebarCursorIndex=0;}/**
9455
9560
  * Calculate how many columns are in the current gallery grid by
9456
9561
  * inspecting the rendered DOM. In list mode this is always 1.
9457
9562
  */recalculateColumns(){let tmpRemote=this.pict.AppData.RetoldRemote;// List mode is always a single column
@@ -9615,7 +9720,7 @@ fetch('/api/media/open',{method:'POST',headers:{'Content-Type':'application/json
9615
9720
  // On macOS/Linux our custom handlers URL-decode, so we encode.
9616
9721
  let tmpIsWindows=/Windows/.test(navigator.userAgent);let tmpVLCURL=tmpIsWindows?'vlc://'+tmpStreamURL:'vlc://'+encodeURIComponent(tmpStreamURL);this.pict.providers['RetoldRemote-ToastNotification'].showOverlayIndicator('Opening VLC...');// Use a temporary anchor element to trigger the protocol handler
9617
9722
  // without navigating the current page away
9618
- let tmpLink=document.createElement('a');tmpLink.href=tmpVLCURL;tmpLink.style.display='none';document.body.appendChild(tmpLink);tmpLink.click();document.body.removeChild(tmpLink);}}GalleryNavigationProvider.default_configuration=_DefaultProviderConfiguration;module.exports=GalleryNavigationProvider;},{"./keyboard-handlers/KeyHandler-AudioExplorer.js":123,"./keyboard-handlers/KeyHandler-Gallery.js":124,"./keyboard-handlers/KeyHandler-Sidebar.js":125,"./keyboard-handlers/KeyHandler-VideoExplorer.js":126,"./keyboard-handlers/KeyHandler-Viewer.js":127,"pict-provider":46}],119:[function(require,module,exports){const libPictProvider=require('pict-provider');const _DefaultProviderConfiguration={ProviderIdentifier:'RetoldRemote-Provider',AutoInitialize:true,AutoSolveWithApp:false};class RetoldRemoteProvider extends libPictProvider{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);// Client-side cache: path -> hash and hash -> path
9723
+ let tmpLink=document.createElement('a');tmpLink.href=tmpVLCURL;tmpLink.style.display='none';document.body.appendChild(tmpLink);tmpLink.click();document.body.removeChild(tmpLink);}}GalleryNavigationProvider.default_configuration=_DefaultProviderConfiguration;module.exports=GalleryNavigationProvider;},{"./keyboard-handlers/KeyHandler-AudioExplorer.js":124,"./keyboard-handlers/KeyHandler-Gallery.js":125,"./keyboard-handlers/KeyHandler-Sidebar.js":126,"./keyboard-handlers/KeyHandler-VideoExplorer.js":127,"./keyboard-handlers/KeyHandler-Viewer.js":128,"pict-provider":46}],120:[function(require,module,exports){const libPictProvider=require('pict-provider');const _DefaultProviderConfiguration={ProviderIdentifier:'RetoldRemote-Provider',AutoInitialize:true,AutoSolveWithApp:false};class RetoldRemoteProvider extends libPictProvider{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);// Client-side cache: path -> hash and hash -> path
9619
9724
  this._pathToHash={};this._hashToPath={};}/**
9620
9725
  * Fetch the server's media processing capabilities.
9621
9726
  *
@@ -9697,7 +9802,7 @@ if(pData&&pData.Hash&&pData.Path){this.registerHash(pData.Path,pData.Hash);}fCal
9697
9802
  *
9698
9803
  * @param {string} pExtension - Lowercase extension
9699
9804
  * @returns {boolean}
9700
- */_isImageExtension(pExtension){let tmpImageExtensions={'png':true,'jpg':true,'jpeg':true,'gif':true,'webp':true,'svg':true,'bmp':true,'ico':true,'avif':true,'tiff':true,'tif':true};return!!tmpImageExtensions[pExtension];}}RetoldRemoteProvider.default_configuration=_DefaultProviderConfiguration;module.exports=RetoldRemoteProvider;},{"pict-provider":46}],120:[function(require,module,exports){const libPictProvider=require('pict-provider');const _DefaultProviderConfiguration={"ProviderIdentifier":"RetoldRemote-Icons","AutoInitialize":true,"AutoInitializeOrdinal":0,"AutoSolveWithApp":true,"AutoSolveOrdinal":0};// ====================================================================
9805
+ */_isImageExtension(pExtension){let tmpImageExtensions={'png':true,'jpg':true,'jpeg':true,'gif':true,'webp':true,'svg':true,'bmp':true,'ico':true,'avif':true,'tiff':true,'tif':true};return!!tmpImageExtensions[pExtension];}}RetoldRemoteProvider.default_configuration=_DefaultProviderConfiguration;module.exports=RetoldRemoteProvider;},{"pict-provider":46}],121:[function(require,module,exports){const libPictProvider=require('pict-provider');const _DefaultProviderConfiguration={"ProviderIdentifier":"RetoldRemote-Icons","AutoInitialize":true,"AutoInitializeOrdinal":0,"AutoSolveWithApp":true,"AutoSolveOrdinal":0};// ====================================================================
9701
9806
  // DEFAULT DARK-THEME COLOR PALETTE
9702
9807
  //
9703
9808
  // Designed for retold-remote's dark navy background (#16162B).
@@ -9838,7 +9943,7 @@ return this.getIcon('file',tmpSize);}/**
9838
9943
  * @returns {Object} Extension-to-icon name map
9839
9944
  */getExtensionMap(){return Object.assign({},this._extensionMap);}/**
9840
9945
  * Inject CSS classes for icon sizing into the pict CSSMap.
9841
- */injectCSS(){if(this._cssInjected){return;}if(this.pict&&this.pict.CSSMap){this.pict.CSSMap.addCSS('RetoldRemoteIcons','.retold-remote-icon { display: inline-flex; align-items: center; justify-content: center; vertical-align: middle; }\n'+'.retold-remote-icon svg { display: block; }\n'+'.retold-remote-icon-sm svg { width: 16px; height: 16px; }\n'+'.retold-remote-icon-md svg { width: 48px; height: 48px; }\n'+'.retold-remote-icon-lg svg { width: 64px; height: 64px; }\n'+'.retold-remote-icon-xl svg { width: 96px; height: 96px; }\n');this._cssInjected=true;}}onAfterInitialize(){this.injectCSS();return super.onAfterInitialize();}}module.exports=RetoldRemoteIconProvider;module.exports.default_configuration=_DefaultProviderConfiguration;module.exports.DefaultColors=_DefaultColors;},{"pict-provider":46,"pict-section-filebrowser/source/providers/Pict-Provider-FileBrowserIcons.js":56}],121:[function(require,module,exports){const libPictProvider=require('pict-provider');const _ProviderConfiguration={ProviderIdentifier:'RetoldRemote-Theme',AutoInitialize:true,AutoInitializeOrdinal:0};/**
9946
+ */injectCSS(){if(this._cssInjected){return;}if(this.pict&&this.pict.CSSMap){this.pict.CSSMap.addCSS('RetoldRemoteIcons','.retold-remote-icon { display: inline-flex; align-items: center; justify-content: center; vertical-align: middle; }\n'+'.retold-remote-icon svg { display: block; }\n'+'.retold-remote-icon-sm svg { width: 16px; height: 16px; }\n'+'.retold-remote-icon-md svg { width: 48px; height: 48px; }\n'+'.retold-remote-icon-lg svg { width: 64px; height: 64px; }\n'+'.retold-remote-icon-xl svg { width: 96px; height: 96px; }\n');this._cssInjected=true;}}onAfterInitialize(){this.injectCSS();return super.onAfterInitialize();}}module.exports=RetoldRemoteIconProvider;module.exports.default_configuration=_DefaultProviderConfiguration;module.exports.DefaultColors=_DefaultColors;},{"pict-provider":46,"pict-section-filebrowser/source/providers/Pict-Provider-FileBrowserIcons.js":56}],122:[function(require,module,exports){const libPictProvider=require('pict-provider');const _ProviderConfiguration={ProviderIdentifier:'RetoldRemote-Theme',AutoInitialize:true,AutoInitializeOrdinal:0};/**
9842
9947
  * Theme provider for retold-remote.
9843
9948
  *
9844
9949
  * Manages 15 themes (5 grey-only + 10 fun) via CSS custom properties.
@@ -9877,7 +9982,7 @@ let tmpRemote=this.pict.AppData.RetoldRemote;if(tmpRemote){tmpRemote.Theme=pThem
9877
9982
  *
9878
9983
  * @param {string} pThemeKey
9879
9984
  * @returns {Object|null}
9880
- */getTheme(pThemeKey){return this._themes[pThemeKey]||null;}}RetoldRemoteThemeProvider.default_configuration=_ProviderConfiguration;module.exports=RetoldRemoteThemeProvider;},{"pict-provider":46}],122:[function(require,module,exports){const libPictProvider=require('pict-provider');const _DefaultProviderConfiguration={ProviderIdentifier:'RetoldRemote-ToastNotification',AutoInitialize:true,AutoSolveWithApp:false};class ToastNotificationProvider extends libPictProvider{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='RetoldRemoteProvider';this._overlayTimeout=null;}/**
9985
+ */getTheme(pThemeKey){return this._themes[pThemeKey]||null;}}RetoldRemoteThemeProvider.default_configuration=_ProviderConfiguration;module.exports=RetoldRemoteThemeProvider;},{"pict-provider":46}],123:[function(require,module,exports){const libPictProvider=require('pict-provider');const _DefaultProviderConfiguration={ProviderIdentifier:'RetoldRemote-ToastNotification',AutoInitialize:true,AutoSolveWithApp:false};class ToastNotificationProvider extends libPictProvider{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='RetoldRemoteProvider';this._overlayTimeout=null;}/**
9881
9986
  * Show a brief overlay indicator inside the viewer body.
9882
9987
  *
9883
9988
  * Reuses the #RetoldRemote-FitIndicator element, creating it if needed.
@@ -9892,12 +9997,12 @@ let tmpRemote=this.pict.AppData.RetoldRemote;if(tmpRemote){tmpRemote.Theme=pThem
9892
9997
  *
9893
9998
  * @param {string} pMessage - Text to display
9894
9999
  * @param {number} pDuration - Milliseconds before removal (default 2000)
9895
- */showToast(pMessage,pDuration){let tmpDuration=pDuration||2000;let tmpExisting=document.querySelector('.retold-remote-toast');if(tmpExisting){tmpExisting.remove();}let tmpToast=document.createElement('div');tmpToast.className='retold-remote-toast';tmpToast.textContent=pMessage;document.body.appendChild(tmpToast);setTimeout(function(){if(tmpToast.parentNode){tmpToast.remove();}},tmpDuration);}}ToastNotificationProvider.default_configuration=_DefaultProviderConfiguration;module.exports=ToastNotificationProvider;},{"pict-provider":46}],123:[function(require,module,exports){/**
10000
+ */showToast(pMessage,pDuration){let tmpDuration=pDuration||2000;let tmpExisting=document.querySelector('.retold-remote-toast');if(tmpExisting){tmpExisting.remove();}let tmpToast=document.createElement('div');tmpToast.className='retold-remote-toast';tmpToast.textContent=pMessage;document.body.appendChild(tmpToast);setTimeout(function(){if(tmpToast.parentNode){tmpToast.remove();}},tmpDuration);}}ToastNotificationProvider.default_configuration=_DefaultProviderConfiguration;module.exports=ToastNotificationProvider;},{"pict-provider":46}],124:[function(require,module,exports){/**
9896
10001
  * Audio explorer mode keyboard handler.
9897
10002
  *
9898
10003
  * @param {GalleryNavigationProvider} pGalleryNav - The provider instance
9899
10004
  * @param {KeyboardEvent} pEvent - The keyboard event
9900
- */function handleAudioExplorerKey(pGalleryNav,pEvent){let tmpAEX=pGalleryNav.pict.views['RetoldRemote-AudioExplorer'];if(!tmpAEX){return;}switch(pEvent.key){case'Escape':pEvent.preventDefault();if(tmpAEX._selectionStart>=0){tmpAEX.clearSelection();}else{tmpAEX.goBack();}break;case'+':case'=':pEvent.preventDefault();tmpAEX.zoomIn();break;case'-':case'_':pEvent.preventDefault();tmpAEX.zoomOut();break;case'0':pEvent.preventDefault();tmpAEX.zoomToFit();break;case'z':case'Z':pEvent.preventDefault();tmpAEX.zoomToSelection();break;case' ':pEvent.preventDefault();tmpAEX.playSelection();break;case'a':pEvent.preventDefault();{let tmpRemote=pGalleryNav.pict.AppData.RetoldRemote;let tmpCollMgr=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollMgr){if(tmpRemote.LastUsedCollectionGUID){tmpCollMgr.addAudioSnippetToCollection(tmpRemote.LastUsedCollectionGUID);}else{let tmpTopBar=pGalleryNav.pict.views['ContentEditor-TopBar'];if(tmpTopBar&&typeof tmpTopBar.showAddToCollectionDropdown==='function'){tmpTopBar.showAddToCollectionDropdown();}}}}break;case'b':pEvent.preventDefault();{let tmpCollManager=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollManager){tmpCollManager.togglePanel();}}break;}}module.exports=handleAudioExplorerKey;},{}],124:[function(require,module,exports){/**
10005
+ */function handleAudioExplorerKey(pGalleryNav,pEvent){let tmpAEX=pGalleryNav.pict.views['RetoldRemote-AudioExplorer'];if(!tmpAEX){return;}switch(pEvent.key){case'Escape':pEvent.preventDefault();if(tmpAEX._selectionStart>=0){tmpAEX.clearSelection();}else{tmpAEX.goBack();}break;case'+':case'=':pEvent.preventDefault();tmpAEX.zoomIn();break;case'-':case'_':pEvent.preventDefault();tmpAEX.zoomOut();break;case'0':pEvent.preventDefault();tmpAEX.zoomToFit();break;case'z':case'Z':pEvent.preventDefault();tmpAEX.zoomToSelection();break;case' ':pEvent.preventDefault();tmpAEX.playSelection();break;case'a':pEvent.preventDefault();{let tmpRemote=pGalleryNav.pict.AppData.RetoldRemote;let tmpCollMgr=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollMgr){if(tmpRemote.LastUsedCollectionGUID){tmpCollMgr.addAudioSnippetToCollection(tmpRemote.LastUsedCollectionGUID);}else{let tmpTopBar=pGalleryNav.pict.views['ContentEditor-TopBar'];if(tmpTopBar&&typeof tmpTopBar.showAddToCollectionDropdown==='function'){tmpTopBar.showAddToCollectionDropdown();}}}}break;case'b':pEvent.preventDefault();{let tmpCollManager=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollManager){tmpCollManager.togglePanel();}}break;}}module.exports=handleAudioExplorerKey;},{}],125:[function(require,module,exports){/**
9901
10006
  * Gallery mode keyboard handler.
9902
10007
  *
9903
10008
  * @param {GalleryNavigationProvider} pGalleryNav - The provider instance
@@ -9906,7 +10011,7 @@ let tmpRemote=this.pict.AppData.RetoldRemote;if(tmpRemote){tmpRemote.Theme=pThem
9906
10011
  pGalleryNav._showFilterBar();let tmpGalleryView=pGalleryNav.pict.views['RetoldRemote-Gallery'];if(tmpGalleryView){tmpGalleryView.toggleFilterPanel();}}break;case's':pEvent.preventDefault();{// Ensure the filter bar is visible first
9907
10012
  pGalleryNav._showFilterBar();setTimeout(()=>{let tmpSortSelect=document.getElementById('RetoldRemote-Gallery-Sort');if(tmpSortSelect){tmpSortSelect.focus();}},50);}break;case'c':pEvent.preventDefault();pGalleryNav._toggleSettingsPanel();break;case'a':pEvent.preventDefault();{let tmpCollMgr=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollMgr){let tmpCursorItem=tmpItems[tmpIndex];if(tmpCursorItem&&tmpRemote.LastUsedCollectionGUID){// Quick-add the highlighted gallery item to the last-used collection
9908
10013
  let tmpAddItem={Type:tmpCursorItem.Type==='folder'||tmpCursorItem.Type==='archive'?'folder':'file',Path:tmpCursorItem.Path||'',Hash:tmpCursorItem.Hash||'',Label:''};tmpCollMgr.addItemsToCollection(tmpRemote.LastUsedCollectionGUID,[tmpAddItem]);}else{// No last-used collection or no item — open the topbar dropdown
9909
- let tmpTopBar=pGalleryNav.pict.views['ContentEditor-TopBar'];if(tmpTopBar&&typeof tmpTopBar.showAddToCollectionDropdown==='function'){tmpTopBar.showAddToCollectionDropdown();}}}}break;case'b':pEvent.preventDefault();{let tmpCollManager=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollManager){tmpCollManager.togglePanel();}}break;case'd':pEvent.preventDefault();pGalleryNav._toggleDistractionFree();break;case'e':pEvent.preventDefault();{let tmpItem=tmpItems[tmpIndex];if(tmpItem&&tmpItem.Type!=='folder'&&tmpItem.Type!=='archive'){let tmpFilterSort=pGalleryNav.pict.providers['RetoldRemote-GalleryFilterSort'];let tmpCat=tmpFilterSort?tmpFilterSort.getCategory(tmpItem.Extension):'';if(tmpCat==='video'){let tmpVEX=pGalleryNav.pict.views['RetoldRemote-VideoExplorer'];if(tmpVEX){tmpVEX.showExplorer(tmpItem.Path);}}}}break;}}module.exports=handleGalleryKey;},{}],125:[function(require,module,exports){/**
10014
+ let tmpTopBar=pGalleryNav.pict.views['ContentEditor-TopBar'];if(tmpTopBar&&typeof tmpTopBar.showAddToCollectionDropdown==='function'){tmpTopBar.showAddToCollectionDropdown();}}}}break;case'b':pEvent.preventDefault();{let tmpCollManager=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollManager){tmpCollManager.togglePanel();}}break;case'd':pEvent.preventDefault();pGalleryNav._toggleDistractionFree();break;case'e':pEvent.preventDefault();{let tmpItem=tmpItems[tmpIndex];if(tmpItem&&tmpItem.Type!=='folder'&&tmpItem.Type!=='archive'){let tmpFilterSort=pGalleryNav.pict.providers['RetoldRemote-GalleryFilterSort'];let tmpCat=tmpFilterSort?tmpFilterSort.getCategory(tmpItem.Extension):'';if(tmpCat==='video'){let tmpVEX=pGalleryNav.pict.views['RetoldRemote-VideoExplorer'];if(tmpVEX){tmpVEX.showExplorer(tmpItem.Path);}}}}break;}}module.exports=handleGalleryKey;},{}],126:[function(require,module,exports){/**
9910
10015
  * Sidebar file list keyboard handler.
9911
10016
  *
9912
10017
  * @param {GalleryNavigationProvider} pGalleryNav - The provider instance
@@ -9914,12 +10019,12 @@ let tmpTopBar=pGalleryNav.pict.views['ContentEditor-TopBar'];if(tmpTopBar&&typeo
9914
10019
  */function handleSidebarKey(pGalleryNav,pEvent){let tmpRows=document.querySelectorAll('#Pict-FileBrowser-DetailRows .pict-fb-detail-row');let tmpCount=tmpRows.length;if(tmpCount===0){// Nothing in the sidebar, bail back to gallery
9915
10020
  pGalleryNav._blurSidebar();return;}switch(pEvent.key){case'ArrowDown':pEvent.preventDefault();pGalleryNav._moveSidebarCursor(Math.min(pGalleryNav._sidebarCursorIndex+1,tmpCount-1));break;case'ArrowUp':pEvent.preventDefault();pGalleryNav._moveSidebarCursor(Math.max(pGalleryNav._sidebarCursorIndex-1,0));break;case'Home':pEvent.preventDefault();pGalleryNav._moveSidebarCursor(0);break;case'End':pEvent.preventDefault();pGalleryNav._moveSidebarCursor(tmpCount-1);break;case'Enter':pEvent.preventDefault();{// Click the focused row to open it (folder or file)
9916
10021
  let tmpRow=tmpRows[pGalleryNav._sidebarCursorIndex];if(tmpRow){// Fire the dblclick handler which opens folders / selects files
9917
- let tmpDblClickHandler=tmpRow.getAttribute('ondblclick');if(tmpDblClickHandler){new Function(tmpDblClickHandler).call(tmpRow);}}}break;case'Escape':pEvent.preventDefault();pGalleryNav._blurSidebar();break;}}module.exports=handleSidebarKey;},{}],126:[function(require,module,exports){/**
10022
+ let tmpDblClickHandler=tmpRow.getAttribute('ondblclick');if(tmpDblClickHandler){new Function(tmpDblClickHandler).call(tmpRow);}}}break;case'Escape':pEvent.preventDefault();pGalleryNav._blurSidebar();break;}}module.exports=handleSidebarKey;},{}],127:[function(require,module,exports){/**
9918
10023
  * Video explorer mode keyboard handler.
9919
10024
  *
9920
10025
  * @param {GalleryNavigationProvider} pGalleryNav - The provider instance
9921
10026
  * @param {KeyboardEvent} pEvent - The keyboard event
9922
- */function handleVideoExplorerKey(pGalleryNav,pEvent){let tmpRemote=pGalleryNav.pict.AppData.RetoldRemote;switch(pEvent.key){case'Escape':pEvent.preventDefault();let tmpVEX=pGalleryNav.pict.views['RetoldRemote-VideoExplorer'];if(tmpVEX){tmpVEX.goBack();}break;case'a':pEvent.preventDefault();{let tmpCollMgr=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollMgr){if(tmpRemote.LastUsedCollectionGUID){tmpCollMgr.addVideoFrameToCollection(tmpRemote.LastUsedCollectionGUID);}else{let tmpTopBar=pGalleryNav.pict.views['ContentEditor-TopBar'];if(tmpTopBar&&typeof tmpTopBar.showAddToCollectionDropdown==='function'){tmpTopBar.showAddToCollectionDropdown();}}}}break;case'b':pEvent.preventDefault();{let tmpCollManager=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollManager){tmpCollManager.togglePanel();}}break;}}module.exports=handleVideoExplorerKey;},{}],127:[function(require,module,exports){/**
10027
+ */function handleVideoExplorerKey(pGalleryNav,pEvent){let tmpRemote=pGalleryNav.pict.AppData.RetoldRemote;switch(pEvent.key){case'Escape':pEvent.preventDefault();let tmpVEX=pGalleryNav.pict.views['RetoldRemote-VideoExplorer'];if(tmpVEX){tmpVEX.goBack();}break;case'a':pEvent.preventDefault();{let tmpCollMgr=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollMgr){if(tmpRemote.LastUsedCollectionGUID){tmpCollMgr.addVideoFrameToCollection(tmpRemote.LastUsedCollectionGUID);}else{let tmpTopBar=pGalleryNav.pict.views['ContentEditor-TopBar'];if(tmpTopBar&&typeof tmpTopBar.showAddToCollectionDropdown==='function'){tmpTopBar.showAddToCollectionDropdown();}}}}break;case'b':pEvent.preventDefault();{let tmpCollManager=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollManager){tmpCollManager.togglePanel();}}break;}}module.exports=handleVideoExplorerKey;},{}],128:[function(require,module,exports){/**
9923
10028
  * Viewer mode keyboard handler.
9924
10029
  *
9925
10030
  * @param {GalleryNavigationProvider} pGalleryNav - The provider instance
@@ -9927,7 +10032,7 @@ let tmpDblClickHandler=tmpRow.getAttribute('ondblclick');if(tmpDblClickHandler){
9927
10032
  */function handleViewerKey(pGalleryNav,pEvent){let tmpRemote=pGalleryNav.pict.AppData.RetoldRemote;// Video action menu mode — intercept keys for menu options
9928
10033
  if(tmpRemote.VideoMenuActive&&tmpRemote.CurrentViewerMediaType==='video'){switch(pEvent.key){case'Escape':pEvent.preventDefault();pGalleryNav.closeViewer();return;case'ArrowRight':case'j':pEvent.preventDefault();pGalleryNav.nextFile();return;case'ArrowLeft':case'k':pEvent.preventDefault();pGalleryNav.prevFile();return;case'e':pEvent.preventDefault();let tmpVEX=pGalleryNav.pict.views['RetoldRemote-VideoExplorer'];if(tmpVEX){tmpVEX.showExplorer(tmpRemote.CurrentViewerFile);}return;case' ':case'Enter':pEvent.preventDefault();let tmpViewer=pGalleryNav.pict.views['RetoldRemote-MediaViewer'];if(tmpViewer){tmpViewer.playVideo();}return;case't':pEvent.preventDefault();let tmpMediaViewer=pGalleryNav.pict.views['RetoldRemote-MediaViewer'];if(tmpMediaViewer){tmpMediaViewer.loadVideoMenuFrame();}return;case'v':pEvent.preventDefault();pGalleryNav._streamWithVLC();return;}return;}switch(pEvent.key){case'Escape':pEvent.preventDefault();pGalleryNav.closeViewer();break;case'ArrowRight':case'j':pEvent.preventDefault();pGalleryNav.nextFile();break;case'ArrowLeft':case'k':pEvent.preventDefault();pGalleryNav.prevFile();break;case'f':pEvent.preventDefault();pGalleryNav._toggleFullscreen();break;case'i':pEvent.preventDefault();pGalleryNav._toggleFileInfo();break;case' ':pEvent.preventDefault();pGalleryNav._togglePlayPause();break;case'+':case'=':pEvent.preventDefault();pGalleryNav._zoomIn();break;case'-':pEvent.preventDefault();pGalleryNav._zoomOut();break;case'0':pEvent.preventDefault();pGalleryNav._zoomReset();break;case'z':pEvent.preventDefault();pGalleryNav._cycleFitMode();break;case'Enter':pEvent.preventDefault();pGalleryNav._streamWithVLC();break;case'v':pEvent.preventDefault();pGalleryNav._streamWithVLC();break;case'a':pEvent.preventDefault();{let tmpCollMgr=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollMgr){let tmpRemote=pGalleryNav.pict.AppData.RetoldRemote;if(tmpRemote.LastUsedCollectionGUID){// Quick-add the currently viewed file
9929
10034
  tmpCollMgr.addCurrentFileToCollection(tmpRemote.LastUsedCollectionGUID);}else{// No last-used collection — open the picker
9930
- let tmpTopBar=pGalleryNav.pict.views['ContentEditor-TopBar'];if(tmpTopBar&&typeof tmpTopBar.showAddToCollectionDropdown==='function'){tmpTopBar.showAddToCollectionDropdown();}}}}break;case'b':pEvent.preventDefault();{let tmpCollManager=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollManager){tmpCollManager.togglePanel();}}break;case'd':pEvent.preventDefault();pGalleryNav._toggleDistractionFree();break;case'1':pEvent.preventDefault();pGalleryNav.switchViewerType('image');break;case'2':pEvent.preventDefault();pGalleryNav.switchViewerType('video');break;case'3':pEvent.preventDefault();pGalleryNav.switchViewerType('audio');break;case'4':pEvent.preventDefault();pGalleryNav.switchViewerType('text');break;}}module.exports=handleViewerKey;},{}],128:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-AudioExplorer",DefaultRenderable:"RetoldRemote-AudioExplorer",DefaultDestinationAddress:"#RetoldRemote-Viewer-Container",AutoRender:false,CSS:/*css*/`
10035
+ let tmpTopBar=pGalleryNav.pict.views['ContentEditor-TopBar'];if(tmpTopBar&&typeof tmpTopBar.showAddToCollectionDropdown==='function'){tmpTopBar.showAddToCollectionDropdown();}}}}break;case'b':pEvent.preventDefault();{let tmpCollManager=pGalleryNav.pict.providers['RetoldRemote-CollectionManager'];if(tmpCollManager){tmpCollManager.togglePanel();}}break;case'd':pEvent.preventDefault();pGalleryNav._toggleDistractionFree();break;case'1':pEvent.preventDefault();pGalleryNav.switchViewerType('image');break;case'2':pEvent.preventDefault();pGalleryNav.switchViewerType('video');break;case'3':pEvent.preventDefault();pGalleryNav.switchViewerType('audio');break;case'4':pEvent.preventDefault();pGalleryNav.switchViewerType('text');break;}}module.exports=handleViewerKey;},{}],129:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-AudioExplorer",DefaultRenderable:"RetoldRemote-AudioExplorer",DefaultDestinationAddress:"#RetoldRemote-Viewer-Container",AutoRender:false,CSS:/*css*/`
9931
10036
  .retold-remote-aex
9932
10037
  {
9933
10038
  display: flex;
@@ -10283,7 +10388,7 @@ if(this._resizeObserver){this._resizeObserver.disconnect();this._resizeObserver=
10283
10388
  * Show an error message.
10284
10389
  *
10285
10390
  * @param {string} pMessage - Error message
10286
- */_showError(pMessage){let tmpBody=document.getElementById('RetoldRemote-AEX-Body');if(tmpBody){tmpBody.innerHTML='<div class="retold-remote-aex-error">'+'<div class="retold-remote-aex-error-message">'+this.pict.providers['RetoldRemote-FormattingUtilities'].escapeHTML(pMessage||'An error occurred.')+'</div>'+'<button class="retold-remote-aex-nav-btn" onclick="pict.views[\'RetoldRemote-AudioExplorer\'].goBack()">Back to Audio</button>'+'</div>';}}}RetoldRemoteAudioExplorerView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteAudioExplorerView;},{"pict-view":76}],129:[function(require,module,exports){/**
10391
+ */_showError(pMessage){let tmpBody=document.getElementById('RetoldRemote-AEX-Body');if(tmpBody){tmpBody.innerHTML='<div class="retold-remote-aex-error">'+'<div class="retold-remote-aex-error-message">'+this.pict.providers['RetoldRemote-FormattingUtilities'].escapeHTML(pMessage||'An error occurred.')+'</div>'+'<button class="retold-remote-aex-nav-btn" onclick="pict.views[\'RetoldRemote-AudioExplorer\'].goBack()">Back to Audio</button>'+'</div>';}}}RetoldRemoteAudioExplorerView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteAudioExplorerView;},{"pict-view":76}],130:[function(require,module,exports){/**
10287
10392
  * Retold Remote -- Collections Panel View
10288
10393
  *
10289
10394
  * Right-side flyout panel for managing user-defined collections.
@@ -10560,6 +10665,155 @@ if(this._resizeObserver){this._resizeObserver.disconnect();this._resizeObserver=
10560
10665
  color: var(--retold-danger-muted, #e55);
10561
10666
  background: rgba(200, 50, 50, 0.1);
10562
10667
  }
10668
+ /* ---- Operation Plan mode ---- */
10669
+ .retold-remote-collections-op-controls
10670
+ {
10671
+ flex-direction: column;
10672
+ gap: 6px;
10673
+ }
10674
+ .retold-remote-collections-op-summary
10675
+ {
10676
+ font-size: 0.75rem;
10677
+ color: var(--retold-text-dim);
10678
+ padding: 4px 0;
10679
+ }
10680
+ .retold-remote-collections-op-buttons
10681
+ {
10682
+ display: flex;
10683
+ gap: 6px;
10684
+ }
10685
+ .retold-remote-collections-op-execute-btn
10686
+ {
10687
+ flex: 1;
10688
+ padding: 6px 12px;
10689
+ border: none;
10690
+ border-radius: 3px;
10691
+ background: var(--retold-accent, #4a90d9);
10692
+ color: #fff;
10693
+ font-size: 0.78rem;
10694
+ font-weight: 600;
10695
+ cursor: pointer;
10696
+ }
10697
+ .retold-remote-collections-op-execute-btn:hover
10698
+ {
10699
+ opacity: 0.9;
10700
+ }
10701
+ .retold-remote-collections-op-execute-btn:disabled
10702
+ {
10703
+ opacity: 0.5;
10704
+ cursor: default;
10705
+ }
10706
+ .retold-remote-collections-op-undo-btn
10707
+ {
10708
+ padding: 6px 12px;
10709
+ border: 1px solid var(--retold-border);
10710
+ border-radius: 3px;
10711
+ background: transparent;
10712
+ color: var(--retold-text-secondary);
10713
+ font-size: 0.78rem;
10714
+ cursor: pointer;
10715
+ }
10716
+ .retold-remote-collections-op-undo-btn:hover
10717
+ {
10718
+ background: var(--retold-bg-tertiary);
10719
+ }
10720
+ .retold-remote-collection-op-item
10721
+ {
10722
+ display: flex;
10723
+ align-items: center;
10724
+ gap: 4px;
10725
+ padding: 6px 8px;
10726
+ border-bottom: 1px solid var(--retold-border);
10727
+ font-size: 0.75rem;
10728
+ flex-wrap: wrap;
10729
+ }
10730
+ .retold-remote-collection-op-item.op-status-completed
10731
+ {
10732
+ opacity: 0.6;
10733
+ }
10734
+ .retold-remote-collection-op-item.op-status-skipped
10735
+ {
10736
+ opacity: 0.4;
10737
+ text-decoration: line-through;
10738
+ }
10739
+ .retold-remote-collection-op-item.op-status-failed
10740
+ {
10741
+ background: rgba(200, 50, 50, 0.05);
10742
+ }
10743
+ .retold-remote-collection-op-status
10744
+ {
10745
+ flex-shrink: 0;
10746
+ width: 16px;
10747
+ text-align: center;
10748
+ font-size: 0.8rem;
10749
+ }
10750
+ .op-status-completed .retold-remote-collection-op-status
10751
+ {
10752
+ color: var(--retold-success, #4a4);
10753
+ }
10754
+ .op-status-failed .retold-remote-collection-op-status
10755
+ {
10756
+ color: var(--retold-danger-muted, #e55);
10757
+ }
10758
+ .op-status-pending .retold-remote-collection-op-status
10759
+ {
10760
+ color: var(--retold-text-dim);
10761
+ }
10762
+ .retold-remote-collection-op-source
10763
+ {
10764
+ flex: 1;
10765
+ min-width: 0;
10766
+ overflow: hidden;
10767
+ text-overflow: ellipsis;
10768
+ white-space: nowrap;
10769
+ color: var(--retold-text-dim);
10770
+ }
10771
+ .retold-remote-collection-op-arrow
10772
+ {
10773
+ flex-shrink: 0;
10774
+ color: var(--retold-text-dim);
10775
+ padding: 0 2px;
10776
+ }
10777
+ .retold-remote-collection-op-dest
10778
+ {
10779
+ flex: 2;
10780
+ min-width: 0;
10781
+ overflow: hidden;
10782
+ text-overflow: ellipsis;
10783
+ white-space: nowrap;
10784
+ color: var(--retold-text-secondary);
10785
+ }
10786
+ .retold-remote-collection-op-dest-input
10787
+ {
10788
+ width: 100%;
10789
+ padding: 2px 4px;
10790
+ border: 1px solid var(--retold-accent);
10791
+ border-radius: 2px;
10792
+ background: var(--retold-bg-tertiary);
10793
+ color: var(--retold-text-secondary);
10794
+ font-size: 0.75rem;
10795
+ font-family: inherit;
10796
+ box-sizing: border-box;
10797
+ }
10798
+ .retold-remote-collection-op-badge
10799
+ {
10800
+ flex-shrink: 0;
10801
+ font-size: 0.6rem;
10802
+ padding: 1px 4px;
10803
+ border-radius: 2px;
10804
+ background: var(--retold-bg-tertiary);
10805
+ color: var(--retold-text-dim);
10806
+ text-transform: uppercase;
10807
+ font-weight: 600;
10808
+ letter-spacing: 0.3px;
10809
+ }
10810
+ .retold-remote-collection-op-error
10811
+ {
10812
+ width: 100%;
10813
+ font-size: 0.68rem;
10814
+ color: var(--retold-danger-muted, #e55);
10815
+ padding: 2px 0 0 20px;
10816
+ }
10563
10817
  /* ---- Edit mode ---- */
10564
10818
  .retold-remote-collections-edit
10565
10819
  {
@@ -10677,9 +10931,12 @@ let tmpBody=document.createElement('div');tmpBody.className='retold-remote-colle
10677
10931
  let tmpIconDiv=document.createElement('div');tmpIconDiv.className='retold-remote-collection-card-icon';if(tmpIconProvider&&typeof tmpIconProvider.getIcon==='function'){tmpIconDiv.innerHTML=tmpIconProvider.getIcon('bookmark',18);}else{tmpIconDiv.textContent='\u2630';}// Info
10678
10932
  let tmpInfoDiv=document.createElement('div');tmpInfoDiv.className='retold-remote-collection-card-info';let tmpNameDiv=document.createElement('div');tmpNameDiv.className='retold-remote-collection-card-name';tmpNameDiv.textContent=tmpCollection.Name||'Untitled';let tmpMetaDiv=document.createElement('div');tmpMetaDiv.className='retold-remote-collection-card-meta';tmpMetaDiv.textContent=tmpCollection.ItemCount+' item'+(tmpCollection.ItemCount!==1?'s':'');tmpInfoDiv.appendChild(tmpNameDiv);tmpInfoDiv.appendChild(tmpMetaDiv);tmpCard.appendChild(tmpIconDiv);tmpCard.appendChild(tmpInfoDiv);pBody.appendChild(tmpCard);}}// -- Detail Mode ------------------------------------------------------
10679
10933
  _renderDetailMode(pRoot){let tmpSelf=this;let tmpRemote=this.pict.AppData.RetoldRemote;let tmpManager=this.pict.providers['RetoldRemote-CollectionManager'];let tmpCollection=tmpRemote.ActiveCollection;pRoot.innerHTML='';if(!tmpCollection){pRoot.innerHTML='<div class="retold-remote-collections-empty">Loading...</div>';return;}// Header with back button and collection name
10680
- let tmpHeader=document.createElement('div');tmpHeader.className='retold-remote-collections-header';let tmpBackBtn=document.createElement('button');tmpBackBtn.className='retold-remote-collections-header-btn';tmpBackBtn.title='Back to list';tmpBackBtn.textContent='\u2190';tmpBackBtn.onclick=()=>{tmpRemote.CollectionsPanelMode='list';tmpRemote.ActiveCollectionGUID=null;tmpRemote.ActiveCollection=null;tmpSelf.renderContent();};let tmpTitle=document.createElement('div');tmpTitle.className='retold-remote-collections-header-title';tmpTitle.textContent=tmpCollection.Name||'Untitled';let tmpEditBtn=document.createElement('button');tmpEditBtn.className='retold-remote-collections-header-btn';tmpEditBtn.title='Edit collection';tmpEditBtn.textContent='\u270E';tmpEditBtn.onclick=()=>{tmpRemote.CollectionsPanelMode='edit';tmpSelf.renderContent();};tmpHeader.appendChild(tmpBackBtn);tmpHeader.appendChild(tmpTitle);tmpHeader.appendChild(tmpEditBtn);pRoot.appendChild(tmpHeader);// Sort controls
10681
- let tmpControls=document.createElement('div');tmpControls.className='retold-remote-collections-detail-controls';let tmpSortSelect=document.createElement('select');tmpSortSelect.className='retold-remote-collections-sort-select';let tmpSortOptions=[{value:'manual',label:'Manual'},{value:'name',label:'Name'},{value:'modified',label:'Date Added'},{value:'type',label:'Type'}];for(let i=0;i<tmpSortOptions.length;i++){let tmpOpt=document.createElement('option');tmpOpt.value=tmpSortOptions[i].value;tmpOpt.textContent=tmpSortOptions[i].label;if(tmpCollection.SortMode===tmpSortOptions[i].value){tmpOpt.selected=true;}tmpSortSelect.appendChild(tmpOpt);}tmpSortSelect.onchange=pEvent=>{tmpManager.sortActiveCollection(pEvent.target.value,null);};let tmpDirBtn=document.createElement('button');tmpDirBtn.className='retold-remote-collections-sort-dir';tmpDirBtn.textContent=tmpCollection.SortDirection==='desc'?'\u2193':'\u2191';tmpDirBtn.title=tmpCollection.SortDirection==='desc'?'Descending':'Ascending';tmpDirBtn.onclick=()=>{let tmpNewDir=tmpRemote.ActiveCollection.SortDirection==='desc'?'asc':'desc';tmpManager.sortActiveCollection(null,tmpNewDir);};tmpControls.appendChild(tmpSortSelect);tmpControls.appendChild(tmpDirBtn);pRoot.appendChild(tmpControls);// Item list
10682
- let tmpBody=document.createElement('div');tmpBody.className='retold-remote-collections-body';pRoot.appendChild(tmpBody);this._renderItemList(tmpBody,tmpCollection);}_renderItemList(pBody,pCollection){let tmpSelf=this;let tmpRemote=this.pict.AppData.RetoldRemote;let tmpManager=this.pict.providers['RetoldRemote-CollectionManager'];let tmpItems=pCollection.Items||[];pBody.innerHTML='';if(tmpItems.length===0){let tmpEmpty=document.createElement('div');tmpEmpty.className='retold-remote-collections-empty';tmpEmpty.textContent='No items yet. Browse files and add them to this collection.';pBody.appendChild(tmpEmpty);return;}for(let i=0;i<tmpItems.length;i++){let tmpItem=tmpItems[i];let tmpRow=document.createElement('div');tmpRow.className='retold-remote-collection-item';tmpRow.setAttribute('data-item-id',tmpItem.ID);// Drag handle (for manual sort)
10934
+ let tmpHeader=document.createElement('div');tmpHeader.className='retold-remote-collections-header';let tmpBackBtn=document.createElement('button');tmpBackBtn.className='retold-remote-collections-header-btn';tmpBackBtn.title='Back to list';tmpBackBtn.textContent='\u2190';tmpBackBtn.onclick=()=>{tmpRemote.CollectionsPanelMode='list';tmpRemote.ActiveCollectionGUID=null;tmpRemote.ActiveCollection=null;tmpSelf.renderContent();};let tmpTitle=document.createElement('div');tmpTitle.className='retold-remote-collections-header-title';tmpTitle.textContent=tmpCollection.Name||'Untitled';let tmpEditBtn=document.createElement('button');tmpEditBtn.className='retold-remote-collections-header-btn';tmpEditBtn.title='Edit collection';tmpEditBtn.textContent='\u270E';tmpEditBtn.onclick=()=>{tmpRemote.CollectionsPanelMode='edit';tmpSelf.renderContent();};tmpHeader.appendChild(tmpBackBtn);tmpHeader.appendChild(tmpTitle);tmpHeader.appendChild(tmpEditBtn);pRoot.appendChild(tmpHeader);// Check if this is an operation-plan collection
10935
+ let tmpIsOperationPlan=tmpCollection.CollectionType==='operation-plan';if(tmpIsOperationPlan){// Operation plan controls: summary + execute/undo buttons
10936
+ let tmpOpControls=document.createElement('div');tmpOpControls.className='retold-remote-collections-detail-controls retold-remote-collections-op-controls';// Count pending, completed, failed, skipped
10937
+ let tmpItems=tmpCollection.Items||[];let tmpPending=0;let tmpCompleted=0;let tmpFailed=0;let tmpSkipped=0;for(let i=0;i<tmpItems.length;i++){let tmpStatus=tmpItems[i].OperationStatus;if(tmpStatus==='completed')tmpCompleted++;else if(tmpStatus==='failed')tmpFailed++;else if(tmpStatus==='skipped')tmpSkipped++;else if(tmpItems[i].Operation)tmpPending++;}let tmpSummary=document.createElement('div');tmpSummary.className='retold-remote-collections-op-summary';let tmpSummaryParts=[];if(tmpPending>0)tmpSummaryParts.push(tmpPending+' pending');if(tmpCompleted>0)tmpSummaryParts.push(tmpCompleted+' done');if(tmpFailed>0)tmpSummaryParts.push(tmpFailed+' failed');if(tmpSkipped>0)tmpSummaryParts.push(tmpSkipped+' skipped');tmpSummary.textContent=tmpSummaryParts.join(' \u00b7 ')||'No operations';tmpOpControls.appendChild(tmpSummary);let tmpBtnRow=document.createElement('div');tmpBtnRow.className='retold-remote-collections-op-buttons';if(tmpPending>0){let tmpExecBtn=document.createElement('button');tmpExecBtn.className='retold-remote-collections-op-execute-btn';tmpExecBtn.textContent='Execute '+tmpPending+' Move'+(tmpPending>1?'s':'');tmpExecBtn.onclick=()=>{tmpExecBtn.disabled=true;tmpExecBtn.textContent='Moving...';tmpManager.executeCollectionOperations(tmpCollection.GUID);};tmpBtnRow.appendChild(tmpExecBtn);}if(tmpCollection.OperationBatchGUID&&tmpCompleted>0){let tmpUndoBtn=document.createElement('button');tmpUndoBtn.className='retold-remote-collections-op-undo-btn';tmpUndoBtn.textContent='Undo';tmpUndoBtn.onclick=()=>{tmpUndoBtn.disabled=true;tmpUndoBtn.textContent='Undoing...';tmpManager.undoCollectionOperations(tmpCollection.GUID);};tmpBtnRow.appendChild(tmpUndoBtn);}tmpOpControls.appendChild(tmpBtnRow);pRoot.appendChild(tmpOpControls);}else{// Standard sort controls for bookmark collections
10938
+ let tmpControls=document.createElement('div');tmpControls.className='retold-remote-collections-detail-controls';let tmpSortSelect=document.createElement('select');tmpSortSelect.className='retold-remote-collections-sort-select';let tmpSortOptions=[{value:'manual',label:'Manual'},{value:'name',label:'Name'},{value:'modified',label:'Date Added'},{value:'type',label:'Type'}];for(let i=0;i<tmpSortOptions.length;i++){let tmpOpt=document.createElement('option');tmpOpt.value=tmpSortOptions[i].value;tmpOpt.textContent=tmpSortOptions[i].label;if(tmpCollection.SortMode===tmpSortOptions[i].value){tmpOpt.selected=true;}tmpSortSelect.appendChild(tmpOpt);}tmpSortSelect.onchange=pEvent=>{tmpManager.sortActiveCollection(pEvent.target.value,null);};let tmpDirBtn=document.createElement('button');tmpDirBtn.className='retold-remote-collections-sort-dir';tmpDirBtn.textContent=tmpCollection.SortDirection==='desc'?'\u2193':'\u2191';tmpDirBtn.title=tmpCollection.SortDirection==='desc'?'Descending':'Ascending';tmpDirBtn.onclick=()=>{let tmpNewDir=tmpRemote.ActiveCollection.SortDirection==='desc'?'asc':'desc';tmpManager.sortActiveCollection(null,tmpNewDir);};tmpControls.appendChild(tmpSortSelect);tmpControls.appendChild(tmpDirBtn);pRoot.appendChild(tmpControls);}// Item list
10939
+ let tmpBody=document.createElement('div');tmpBody.className='retold-remote-collections-body';pRoot.appendChild(tmpBody);if(tmpIsOperationPlan){this._renderOperationItemList(tmpBody,tmpCollection);}else{this._renderItemList(tmpBody,tmpCollection);}}_renderItemList(pBody,pCollection){let tmpSelf=this;let tmpRemote=this.pict.AppData.RetoldRemote;let tmpManager=this.pict.providers['RetoldRemote-CollectionManager'];let tmpItems=pCollection.Items||[];pBody.innerHTML='';if(tmpItems.length===0){let tmpEmpty=document.createElement('div');tmpEmpty.className='retold-remote-collections-empty';tmpEmpty.textContent='No items yet. Browse files and add them to this collection.';pBody.appendChild(tmpEmpty);return;}for(let i=0;i<tmpItems.length;i++){let tmpItem=tmpItems[i];let tmpRow=document.createElement('div');tmpRow.className='retold-remote-collection-item';tmpRow.setAttribute('data-item-id',tmpItem.ID);// Drag handle (for manual sort)
10683
10940
  if(pCollection.SortMode==='manual'){let tmpDrag=document.createElement('div');tmpDrag.className='retold-remote-collection-item-drag';tmpDrag.textContent='\u2630';tmpDrag.draggable=true;tmpDrag.ondragstart=pEvent=>{tmpSelf._draggedItemId=tmpItem.ID;tmpRow.classList.add('dragging');pEvent.dataTransfer.effectAllowed='move';};tmpDrag.ondragend=()=>{tmpRow.classList.remove('dragging');tmpSelf._draggedItemId=null;// Remove all drag-over classes
10684
10941
  let tmpAllItems=pBody.querySelectorAll('.retold-remote-collection-item');for(let j=0;j<tmpAllItems.length;j++){tmpAllItems[j].classList.remove('drag-over');}};tmpRow.appendChild(tmpDrag);}// Drop target events
10685
10942
  tmpRow.ondragover=pEvent=>{pEvent.preventDefault();pEvent.dataTransfer.dropEffect='move';tmpRow.classList.add('drag-over');};tmpRow.ondragleave=()=>{tmpRow.classList.remove('drag-over');};tmpRow.ondrop=pEvent=>{pEvent.preventDefault();tmpRow.classList.remove('drag-over');if(tmpSelf._draggedItemId&&tmpSelf._draggedItemId!==tmpItem.ID){// Build new order: move dragged item before this item
@@ -10689,7 +10946,19 @@ let tmpNameDiv=document.createElement('div');tmpNameDiv.className='retold-remote
10689
10946
  let tmpTypeDiv=document.createElement('div');tmpTypeDiv.className='retold-remote-collection-item-type';tmpTypeDiv.textContent=tmpItem.Type||'file';// Remove button
10690
10947
  let tmpRemoveBtn=document.createElement('button');tmpRemoveBtn.className='retold-remote-collection-item-remove';tmpRemoveBtn.title='Remove from collection';tmpRemoveBtn.textContent='\u00d7';tmpRemoveBtn.onclick=pEvent=>{pEvent.stopPropagation();tmpManager.removeItemFromCollection(pCollection.GUID,tmpItem.ID);};// Click to navigate — set up collection browsing context
10691
10948
  let tmpItemIndex=i;tmpRow.onclick=()=>{if(tmpItem.Type==='file'||tmpItem.Type==='subfile'||tmpItem.Type==='image-crop'||tmpItem.Type==='video-clip'||tmpItem.Type==='video-frame'){// Enter collection browsing mode so next/prev navigate through collection items
10692
- tmpRemote.BrowsingCollection=true;tmpRemote.BrowsingCollectionIndex=tmpItemIndex;tmpSelf.pict.PictApplication.navigateToFile(tmpItem.Path);}else if(tmpItem.Type==='folder'||tmpItem.Type==='folder-contents'){tmpSelf.pict.PictApplication.loadFileList(tmpItem.Path);}};tmpRow.appendChild(tmpIconDiv);tmpRow.appendChild(tmpNameDiv);tmpRow.appendChild(tmpTypeDiv);tmpRow.appendChild(tmpRemoveBtn);pBody.appendChild(tmpRow);}}// -- Edit Mode --------------------------------------------------------
10949
+ tmpRemote.BrowsingCollection=true;tmpRemote.BrowsingCollectionIndex=tmpItemIndex;tmpSelf.pict.PictApplication.navigateToFile(tmpItem.Path);}else if(tmpItem.Type==='folder'||tmpItem.Type==='folder-contents'){tmpSelf.pict.PictApplication.loadFileList(tmpItem.Path);}};tmpRow.appendChild(tmpIconDiv);tmpRow.appendChild(tmpNameDiv);tmpRow.appendChild(tmpTypeDiv);tmpRow.appendChild(tmpRemoveBtn);pBody.appendChild(tmpRow);}}// -- Operation Plan Item Rendering ------------------------------------
10950
+ _renderOperationItemList(pBody,pCollection){let tmpSelf=this;let tmpManager=this.pict.providers['RetoldRemote-CollectionManager'];let tmpItems=pCollection.Items||[];pBody.innerHTML='';if(tmpItems.length===0){let tmpEmpty=document.createElement('div');tmpEmpty.className='retold-remote-collections-empty';tmpEmpty.textContent='No items in this sort plan.';pBody.appendChild(tmpEmpty);return;}for(let i=0;i<tmpItems.length;i++){let tmpItem=tmpItems[i];let tmpRow=document.createElement('div');tmpRow.className='retold-remote-collection-op-item';// Status color
10951
+ let tmpStatus=tmpItem.OperationStatus||'pending';tmpRow.classList.add('op-status-'+tmpStatus);// Status indicator
10952
+ let tmpStatusDiv=document.createElement('div');tmpStatusDiv.className='retold-remote-collection-op-status';if(tmpStatus==='completed'){tmpStatusDiv.textContent='\u2713';tmpStatusDiv.title='Completed';}else if(tmpStatus==='failed'){tmpStatusDiv.textContent='\u2717';tmpStatusDiv.title=tmpItem.OperationError||'Failed';}else if(tmpStatus==='skipped'){tmpStatusDiv.textContent='\u2014';tmpStatusDiv.title='Skipped';}else{tmpStatusDiv.textContent='\u25CB';tmpStatusDiv.title='Pending';}// Source path (filename only, full path in tooltip)
10953
+ let tmpSourceDiv=document.createElement('div');tmpSourceDiv.className='retold-remote-collection-op-source';let tmpSourcePath=tmpItem.Path||'';tmpSourceDiv.textContent=tmpSourcePath.split('/').pop()||tmpSourcePath;tmpSourceDiv.title=tmpSourcePath;// Arrow
10954
+ let tmpArrow=document.createElement('div');tmpArrow.className='retold-remote-collection-op-arrow';tmpArrow.textContent='\u2192';// Destination path (editable)
10955
+ let tmpDestDiv=document.createElement('div');tmpDestDiv.className='retold-remote-collection-op-dest';let tmpDestPath=tmpItem.DestinationPath||'';tmpDestDiv.textContent=tmpDestPath||'(no destination)';tmpDestDiv.title=tmpDestPath;// Make destination editable on click (only for pending items)
10956
+ if(tmpStatus==='pending'){tmpDestDiv.style.cursor='pointer';tmpDestDiv.onclick=pEvent=>{pEvent.stopPropagation();tmpSelf._startEditDestination(tmpDestDiv,tmpItem,pCollection);};}// Operation badge
10957
+ let tmpOpBadge=document.createElement('div');tmpOpBadge.className='retold-remote-collection-op-badge';tmpOpBadge.textContent=(tmpItem.Operation||'move').toUpperCase();// Skip/remove button (only for pending items)
10958
+ let tmpSkipBtn=document.createElement('button');tmpSkipBtn.className='retold-remote-collection-item-remove';tmpSkipBtn.title='Skip this operation';tmpSkipBtn.textContent='\u00d7';if(tmpStatus==='pending'){tmpSkipBtn.onclick=pEvent=>{pEvent.stopPropagation();tmpManager.skipItemOperation(tmpItem.ID);};}else{tmpSkipBtn.style.visibility='hidden';}// Error message (if failed)
10959
+ if(tmpStatus==='failed'&&tmpItem.OperationError){let tmpErrorDiv=document.createElement('div');tmpErrorDiv.className='retold-remote-collection-op-error';tmpErrorDiv.textContent=tmpItem.OperationError;tmpRow.appendChild(tmpErrorDiv);}tmpRow.appendChild(tmpStatusDiv);tmpRow.appendChild(tmpSourceDiv);tmpRow.appendChild(tmpArrow);tmpRow.appendChild(tmpDestDiv);tmpRow.appendChild(tmpOpBadge);tmpRow.appendChild(tmpSkipBtn);pBody.appendChild(tmpRow);}}/**
10960
+ * Start inline editing of an operation item's destination path.
10961
+ */_startEditDestination(pDestDiv,pItem,pCollection){let tmpSelf=this;let tmpManager=this.pict.providers['RetoldRemote-CollectionManager'];let tmpInput=document.createElement('input');tmpInput.type='text';tmpInput.className='retold-remote-collection-op-dest-input';tmpInput.value=pItem.DestinationPath||'';let tmpFinishEdit=()=>{let tmpNewDest=tmpInput.value.trim();if(tmpNewDest&&tmpNewDest!==pItem.DestinationPath){tmpManager.setItemDestination(pItem.ID,tmpNewDest);}pDestDiv.textContent=tmpNewDest||pItem.DestinationPath||'(no destination)';pDestDiv.title=tmpNewDest||pItem.DestinationPath||'';};tmpInput.onblur=tmpFinishEdit;tmpInput.onkeydown=pEvent=>{if(pEvent.key==='Enter'){pEvent.preventDefault();tmpInput.blur();}else if(pEvent.key==='Escape'){pEvent.preventDefault();pDestDiv.textContent=pItem.DestinationPath||'(no destination)';pDestDiv.title=pItem.DestinationPath||'';}};pDestDiv.textContent='';pDestDiv.appendChild(tmpInput);tmpInput.focus();tmpInput.select();}// -- Edit Mode --------------------------------------------------------
10693
10962
  _renderEditMode(pRoot){let tmpSelf=this;let tmpRemote=this.pict.AppData.RetoldRemote;let tmpManager=this.pict.providers['RetoldRemote-CollectionManager'];let tmpCollection=tmpRemote.ActiveCollection;pRoot.innerHTML='';if(!tmpCollection){pRoot.innerHTML='<div class="retold-remote-collections-empty">No collection selected.</div>';return;}// Header
10694
10963
  let tmpHeader=document.createElement('div');tmpHeader.className='retold-remote-collections-header';let tmpBackBtn=document.createElement('button');tmpBackBtn.className='retold-remote-collections-header-btn';tmpBackBtn.title='Back to detail';tmpBackBtn.textContent='\u2190';tmpBackBtn.onclick=()=>{tmpRemote.CollectionsPanelMode='detail';tmpSelf.renderContent();};let tmpTitle=document.createElement('div');tmpTitle.className='retold-remote-collections-header-title';tmpTitle.textContent='Edit Collection';tmpHeader.appendChild(tmpBackBtn);tmpHeader.appendChild(tmpTitle);pRoot.appendChild(tmpHeader);// Edit form
10695
10964
  let tmpBody=document.createElement('div');tmpBody.className='retold-remote-collections-body';let tmpForm=document.createElement('div');tmpForm.className='retold-remote-collections-edit';// Name
@@ -10704,7 +10973,7 @@ let tmpDeleteBtn=document.createElement('button');tmpDeleteBtn.className='retold
10704
10973
  */_createEditGroup(pLabel,pType,pValue,pId){let tmpGroup=document.createElement('div');tmpGroup.className='retold-remote-collections-edit-group';let tmpLabel=document.createElement('div');tmpLabel.className='retold-remote-collections-edit-label';tmpLabel.textContent=pLabel;let tmpInput;if(pType==='textarea'){tmpInput=document.createElement('textarea');tmpInput.className='retold-remote-collections-edit-textarea';}else{tmpInput=document.createElement('input');tmpInput.className='retold-remote-collections-edit-input';tmpInput.type='text';}tmpInput.value=pValue;tmpInput.id='retold-remote-'+pId;tmpGroup.appendChild(tmpLabel);tmpGroup.appendChild(tmpInput);return tmpGroup;}// -- Helpers ----------------------------------------------------------
10705
10974
  /**
10706
10975
  * Get a text icon character for an item type.
10707
- */_getTypeIcon(pType,pMediaType){switch(pType){case'folder':case'folder-contents':return'\uD83D\uDCC1';case'subfile':return'\uD83D\uDDC4';case'image-crop':return'\u2702';case'video-clip':case'video-frame':return'\uD83C\uDFAC';default:break;}switch(pMediaType){case'image':return'\uD83D\uDDBC';case'video':return'\uD83C\uDFAC';case'audio':return'\uD83C\uDFB5';case'document':return'\uD83D\uDCC4';default:return'\uD83D\uDCC4';}}}RetoldRemoteCollectionsPanelView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteCollectionsPanelView;},{"pict-view":76}],130:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-Gallery",DefaultRenderable:"RetoldRemote-Gallery-Grid",DefaultDestinationAddress:"#RetoldRemote-Gallery-Container",AutoRender:false,CSS:/*css*/`
10976
+ */_getTypeIcon(pType,pMediaType){switch(pType){case'folder':case'folder-contents':return'\uD83D\uDCC1';case'subfile':return'\uD83D\uDDC4';case'image-crop':return'\u2702';case'video-clip':case'video-frame':return'\uD83C\uDFAC';default:break;}switch(pMediaType){case'image':return'\uD83D\uDDBC';case'video':return'\uD83C\uDFAC';case'audio':return'\uD83C\uDFB5';case'document':return'\uD83D\uDCC4';default:return'\uD83D\uDCC4';}}}RetoldRemoteCollectionsPanelView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteCollectionsPanelView;},{"pict-view":76}],131:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-Gallery",DefaultRenderable:"RetoldRemote-Gallery-Grid",DefaultDestinationAddress:"#RetoldRemote-Gallery-Container",AutoRender:false,CSS:/*css*/`
10708
10977
  .retold-remote-gallery-header
10709
10978
  {
10710
10979
  display: flex;
@@ -11529,7 +11798,7 @@ pEvent.preventDefault();}_hideLongPressTooltip(){if(this._longPressTooltipEl){if
11529
11798
  * Get the media category for a file.
11530
11799
  */_getCategory(pExtension,pType){if(pType==='folder')return'folder';if(pType==='archive')return'archive';// Delegate to the filter/sort provider if available
11531
11800
  let tmpFilterSort=this.pict.providers['RetoldRemote-GalleryFilterSort'];if(tmpFilterSort){return tmpFilterSort.getCategory(pExtension);}// Fallback
11532
- let tmpExt=(pExtension||'').replace(/^\./,'').toLowerCase();if(tmpExt==='png'||tmpExt==='jpg'||tmpExt==='jpeg'||tmpExt==='gif'||tmpExt==='webp')return'image';if(tmpExt==='mp4'||tmpExt==='webm'||tmpExt==='mov')return'video';if(tmpExt==='mp3'||tmpExt==='wav'||tmpExt==='ogg')return'audio';if(tmpExt==='pdf')return'document';return'other';}}RetoldRemoteGalleryView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteGalleryView;},{"pict-view":76}],131:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-ImageViewer",DefaultRenderable:"RetoldRemote-ImageViewer",DefaultDestinationAddress:"#RetoldRemote-Viewer-Container",AutoRender:false,CSS:/*css*/`
11801
+ let tmpExt=(pExtension||'').replace(/^\./,'').toLowerCase();if(tmpExt==='png'||tmpExt==='jpg'||tmpExt==='jpeg'||tmpExt==='gif'||tmpExt==='webp')return'image';if(tmpExt==='mp4'||tmpExt==='webm'||tmpExt==='mov')return'video';if(tmpExt==='mp3'||tmpExt==='wav'||tmpExt==='ogg')return'audio';if(tmpExt==='pdf')return'document';return'other';}}RetoldRemoteGalleryView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteGalleryView;},{"pict-view":76}],132:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-ImageViewer",DefaultRenderable:"RetoldRemote-ImageViewer",DefaultDestinationAddress:"#RetoldRemote-Viewer-Container",AutoRender:false,CSS:/*css*/`
11533
11802
  #RetoldRemote-ImageViewer-Img
11534
11803
  {
11535
11804
  image-orientation: from-image;
@@ -11595,12 +11864,13 @@ return{width:tmpNW,height:tmpNH};}}}/**
11595
11864
  * @param {string} pMode - The mode identifier
11596
11865
  */_showFitModeIndicator(pMode){let tmpLabels={'fit':'Fit to Window','auto':'Original if Smaller','original':'Original Size'};let tmpLabel=tmpLabels[pMode]||pMode;this.pict.providers['RetoldRemote-ToastNotification'].showOverlayIndicator(tmpLabel,1200);}/**
11597
11866
  * Clean up resize handler when navigating away.
11598
- */cleanup(){if(this._resizeHandler){window.removeEventListener('resize',this._resizeHandler);this._resizeHandler=null;}}}RetoldRemoteImageViewerView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteImageViewerView;},{"pict-view":76}],132:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"ContentEditor-Layout",DefaultRenderable:"RetoldRemote-Layout-Shell",DefaultDestinationAddress:"#ContentEditor-Application-Container",AutoRender:false,CSS:/*css*/`
11867
+ */cleanup(){if(this._resizeHandler){window.removeEventListener('resize',this._resizeHandler);this._resizeHandler=null;}}}RetoldRemoteImageViewerView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteImageViewerView;},{"pict-view":76}],133:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"ContentEditor-Layout",DefaultRenderable:"RetoldRemote-Layout-Shell",DefaultDestinationAddress:"#ContentEditor-Application-Container",AutoRender:false,CSS:/*css*/`
11599
11868
  #ContentEditor-Application-Container
11600
11869
  {
11601
11870
  display: flex;
11602
11871
  flex-direction: column;
11603
11872
  height: 100vh;
11873
+ height: 100dvh;
11604
11874
  background: var(--retold-bg-primary);
11605
11875
  color: var(--retold-text-primary);
11606
11876
  font-family: var(--retold-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif);
@@ -11864,6 +12134,7 @@ return{width:tmpNW,height:tmpNH};}}}/**
11864
12134
  {
11865
12135
  width: 100% !important;
11866
12136
  height: 33vh;
12137
+ height: 33dvh;
11867
12138
  transition: height 0.2s ease;
11868
12139
  flex-direction: column;
11869
12140
  }
@@ -12027,7 +12298,7 @@ tmpHandle.addEventListener('dblclick',function(pEvent){pEvent.preventDefault();t
12027
12298
  */_setupCollectionsResizeHandle(){let tmpHandle=document.querySelector('.retold-remote-collections-resize-handle');let tmpWrap=document.getElementById('RetoldRemote-Collections-Wrap');if(!tmpHandle||!tmpWrap){return;}let tmpSelf=this;let tmpStartX=0;let tmpStartWidth=0;function onDragStart(pEvent){if(tmpWrap.classList.contains('collapsed')){return;}pEvent.preventDefault();tmpSelf._collectionsDragging=true;tmpHandle.classList.add('dragging');let tmpClientX=pEvent.touches?pEvent.touches[0].clientX:pEvent.clientX;tmpStartX=tmpClientX;tmpStartWidth=tmpWrap.getBoundingClientRect().width;document.addEventListener('mousemove',onDragMove);document.addEventListener('mouseup',onDragEnd);document.addEventListener('touchmove',onDragMove,{passive:false});document.addEventListener('touchend',onDragEnd);}function onDragMove(pEvent){if(!tmpSelf._collectionsDragging){return;}pEvent.preventDefault();let tmpClientX=pEvent.touches?pEvent.touches[0].clientX:pEvent.clientX;// Dragging left (negative deltaX) increases width
12028
12299
  let tmpDelta=tmpStartX-tmpClientX;let tmpNewWidth=Math.max(150,Math.min(600,tmpStartWidth+tmpDelta));tmpWrap.style.width=tmpNewWidth+'px';}function onDragEnd(){if(!tmpSelf._collectionsDragging){return;}tmpSelf._collectionsDragging=false;tmpHandle.classList.remove('dragging');let tmpRemote=tmpSelf.pict.AppData.RetoldRemote;tmpRemote.CollectionsPanelWidth=tmpWrap.getBoundingClientRect().width;tmpSelf.pict.PictApplication.saveSettings();document.removeEventListener('mousemove',onDragMove);document.removeEventListener('mouseup',onDragEnd);document.removeEventListener('touchmove',onDragMove);document.removeEventListener('touchend',onDragEnd);// Recalculate gallery columns
12029
12300
  let tmpGalleryNav=tmpSelf.pict.providers['RetoldRemote-GalleryNavigation'];if(tmpGalleryNav&&typeof tmpGalleryNav.recalculateColumns==='function'){tmpGalleryNav.recalculateColumns();}}tmpHandle.addEventListener('mousedown',onDragStart);tmpHandle.addEventListener('touchstart',onDragStart,{passive:false});// Double-click collapses the collections panel
12030
- tmpHandle.addEventListener('dblclick',function(pEvent){pEvent.preventDefault();tmpSelf.toggleCollectionsPanel();});}}RetoldRemoteLayoutView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteLayoutView;},{"pict-view":76}],133:[function(require,module,exports){const libPictView=require('pict-view');const libPictSectionCode=require('pict-section-code');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-MediaViewer",DefaultRenderable:"RetoldRemote-MediaViewer",DefaultDestinationAddress:"#RetoldRemote-Viewer-Container",AutoRender:false,CSS:/*css*/`
12301
+ tmpHandle.addEventListener('dblclick',function(pEvent){pEvent.preventDefault();tmpSelf.toggleCollectionsPanel();});}}RetoldRemoteLayoutView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteLayoutView;},{"pict-view":76}],134:[function(require,module,exports){const libPictView=require('pict-view');const libPictSectionCode=require('pict-section-code');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-MediaViewer",DefaultRenderable:"RetoldRemote-MediaViewer",DefaultDestinationAddress:"#RetoldRemote-Viewer-Container",AutoRender:false,CSS:/*css*/`
12031
12302
  .retold-remote-viewer
12032
12303
  {
12033
12304
  display: flex;
@@ -12646,7 +12917,7 @@ tmpBook.loaded.navigation.then(pNav=>{tmpSelf._renderEbookTOC(pNav.toc);});}).ca
12646
12917
  */_loadFileInfo(pFilePath){let tmpSelf=this;let tmpProvider=this.pict.providers['RetoldRemote-Provider'];if(!tmpProvider){return;}tmpProvider.fetchMediaProbe(pFilePath,(pError,pData)=>{if(!pData){return;}// Populate the info overlay
12647
12918
  let tmpOverlay=document.getElementById('RetoldRemote-FileInfo-Overlay');if(tmpOverlay){let tmpHTML='';if(pData.Size!==undefined){tmpHTML+='<div class="retold-remote-fileinfo-row"><span class="retold-remote-fileinfo-label">Size</span><span class="retold-remote-fileinfo-value">'+tmpSelf.pict.providers['RetoldRemote-FormattingUtilities'].formatFileSize(pData.Size)+'</span></div>';}if(pData.Width&&pData.Height){tmpHTML+='<div class="retold-remote-fileinfo-row"><span class="retold-remote-fileinfo-label">Dimensions</span><span class="retold-remote-fileinfo-value">'+pData.Width+' x '+pData.Height+'</span></div>';}if(pData.Duration){let tmpMin=Math.floor(pData.Duration/60);let tmpSec=Math.floor(pData.Duration%60);tmpHTML+='<div class="retold-remote-fileinfo-row"><span class="retold-remote-fileinfo-label">Duration</span><span class="retold-remote-fileinfo-value">'+tmpMin+':'+(tmpSec<10?'0':'')+tmpSec+'</span></div>';}if(pData.Codec){tmpHTML+='<div class="retold-remote-fileinfo-row"><span class="retold-remote-fileinfo-label">Codec</span><span class="retold-remote-fileinfo-value">'+pData.Codec+'</span></div>';}if(pData.Format){tmpHTML+='<div class="retold-remote-fileinfo-row"><span class="retold-remote-fileinfo-label">Format</span><span class="retold-remote-fileinfo-value">'+pData.Format+'</span></div>';}if(pData.Modified){tmpHTML+='<div class="retold-remote-fileinfo-row"><span class="retold-remote-fileinfo-label">Modified</span><span class="retold-remote-fileinfo-value">'+new Date(pData.Modified).toLocaleString()+'</span></div>';}if(pData.Path){tmpHTML+='<div class="retold-remote-fileinfo-row"><span class="retold-remote-fileinfo-label">Path</span><span class="retold-remote-fileinfo-value">'+pData.Path+'</span></div>';}tmpOverlay.innerHTML=tmpHTML;}// Populate the video stats bar (if viewing a video)
12648
12919
  let tmpStatsBar=document.getElementById('RetoldRemote-VideoStats');if(tmpStatsBar){let tmpStatsHTML='';if(pData.Duration){let tmpMin=Math.floor(pData.Duration/60);let tmpSec=Math.floor(pData.Duration%60);tmpStatsHTML+='<span><span class="retold-remote-video-stat-label">Duration</span> <span class="retold-remote-video-stat-value">'+tmpMin+':'+(tmpSec<10?'0':'')+tmpSec+'</span></span>';}if(pData.Width&&pData.Height){tmpStatsHTML+='<span><span class="retold-remote-video-stat-label">Resolution</span> <span class="retold-remote-video-stat-value">'+pData.Width+'×'+pData.Height+'</span></span>';}if(pData.Codec){tmpStatsHTML+='<span><span class="retold-remote-video-stat-label">Codec</span> <span class="retold-remote-video-stat-value">'+pData.Codec+'</span></span>';}if(pData.Bitrate){let tmpBitrate=pData.Bitrate;let tmpBitrateStr;if(tmpBitrate>=1000000){tmpBitrateStr=(tmpBitrate/1000000).toFixed(1)+' Mbps';}else if(tmpBitrate>=1000){tmpBitrateStr=Math.round(tmpBitrate/1000)+' kbps';}else{tmpBitrateStr=tmpBitrate+' bps';}tmpStatsHTML+='<span><span class="retold-remote-video-stat-label">Bitrate</span> <span class="retold-remote-video-stat-value">'+tmpBitrateStr+'</span></span>';}if(pData.Size!==undefined){tmpStatsHTML+='<span><span class="retold-remote-video-stat-label">Size</span> <span class="retold-remote-video-stat-value">'+tmpSelf.pict.providers['RetoldRemote-FormattingUtilities'].formatFileSize(pData.Size)+'</span></span>';}// Preserve the Explore and VLC buttons if they exist
12649
- let tmpExploreBtn=tmpStatsBar.querySelector('.retold-remote-explore-btn');let tmpExploreHTML=tmpExploreBtn?tmpExploreBtn.outerHTML:'';let tmpVLCBtn=tmpStatsBar.querySelector('.retold-remote-vlc-btn');let tmpVLCHTML=tmpVLCBtn?tmpVLCBtn.outerHTML:'';tmpStatsBar.innerHTML=tmpStatsHTML+tmpExploreHTML+tmpVLCHTML;}});}}RetoldRemoteMediaViewerView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteMediaViewerView;},{"pict-section-code":49,"pict-view":76}],134:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-SettingsPanel",DefaultRenderable:"RetoldRemote-SettingsPanel",DefaultDestinationAddress:"#RetoldRemote-Settings-Container",AutoRender:false,CSS:/*css*/`
12920
+ let tmpExploreBtn=tmpStatsBar.querySelector('.retold-remote-explore-btn');let tmpExploreHTML=tmpExploreBtn?tmpExploreBtn.outerHTML:'';let tmpVLCBtn=tmpStatsBar.querySelector('.retold-remote-vlc-btn');let tmpVLCHTML=tmpVLCBtn?tmpVLCBtn.outerHTML:'';tmpStatsBar.innerHTML=tmpStatsHTML+tmpExploreHTML+tmpVLCHTML;}});}}RetoldRemoteMediaViewerView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteMediaViewerView;},{"pict-section-code":49,"pict-view":76}],135:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-SettingsPanel",DefaultRenderable:"RetoldRemote-SettingsPanel",DefaultDestinationAddress:"#RetoldRemote-Settings-Container",AutoRender:false,CSS:/*css*/`
12650
12921
  .retold-remote-settings
12651
12922
  {
12652
12923
  padding: 12px;
@@ -12736,6 +13007,42 @@ let tmpExploreBtn=tmpStatsBar.querySelector('.retold-remote-explore-btn');let tm
12736
13007
  background: var(--retold-bg-hover);
12737
13008
  color: var(--retold-text-primary);
12738
13009
  }
13010
+ .retold-remote-settings-input
13011
+ {
13012
+ width: 100%;
13013
+ padding: 5px 8px;
13014
+ border: 1px solid var(--retold-border);
13015
+ border-radius: 3px;
13016
+ background: var(--retold-bg-tertiary);
13017
+ color: var(--retold-text-secondary);
13018
+ font-size: 0.75rem;
13019
+ font-family: inherit;
13020
+ box-sizing: border-box;
13021
+ }
13022
+ .retold-remote-settings-input:focus
13023
+ {
13024
+ outline: none;
13025
+ border-color: var(--retold-accent);
13026
+ }
13027
+ .retold-remote-settings-input-row
13028
+ {
13029
+ margin-bottom: 8px;
13030
+ }
13031
+ .retold-remote-settings-input-label
13032
+ {
13033
+ display: block;
13034
+ font-size: 0.72rem;
13035
+ color: var(--retold-text-dim);
13036
+ margin-bottom: 3px;
13037
+ }
13038
+ .retold-remote-settings-template-preview
13039
+ {
13040
+ font-size: 0.68rem;
13041
+ color: var(--retold-text-dim);
13042
+ margin-top: 3px;
13043
+ font-style: italic;
13044
+ word-break: break-all;
13045
+ }
12739
13046
  `};class RetoldRemoteSettingsPanelView extends libPictView{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);}onAfterRender(){super.onAfterRender();this._renderSettingsContent();}_renderSettingsContent(){let tmpContainer=document.getElementById('RetoldRemote-Settings-Container');if(!tmpContainer){return;}let tmpRemote=this.pict.AppData.RetoldRemote;let tmpCapabilities=tmpRemote.ServerCapabilities||{};let tmpHTML='<div class="retold-remote-settings">';// Appearance section (theme dropdown)
12740
13047
  tmpHTML+='<div class="retold-remote-settings-section">';tmpHTML+='<div class="retold-remote-settings-section-title">Appearance</div>';tmpHTML+='<div class="retold-remote-settings-row">';tmpHTML+='<span class="retold-remote-settings-label">Theme</span>';tmpHTML+='<select class="retold-remote-settings-select" onchange="pict.views[\'RetoldRemote-SettingsPanel\'].changeTheme(this.value)">';let tmpThemeProvider=this.pict.providers['RetoldRemote-Theme'];if(tmpThemeProvider){let tmpThemes=tmpThemeProvider.getThemeList();let tmpCurrentTheme=tmpThemeProvider.getCurrentTheme();let tmpCurrentCategory='';for(let i=0;i<tmpThemes.length;i++){let tmpTheme=tmpThemes[i];if(tmpTheme.category!==tmpCurrentCategory){if(tmpCurrentCategory){tmpHTML+='</optgroup>';}tmpHTML+='<optgroup label="'+tmpTheme.category+'">';tmpCurrentCategory=tmpTheme.category;}tmpHTML+='<option value="'+tmpTheme.key+'"'+(tmpTheme.key===tmpCurrentTheme?' selected':'')+'>'+tmpTheme.name+'</option>';}if(tmpCurrentCategory){tmpHTML+='</optgroup>';}}tmpHTML+='</select>';tmpHTML+='</div>';tmpHTML+='</div>';// end appearance section
12741
13048
  // Gallery section
@@ -12755,6 +13062,14 @@ tmpHTML+='<div class="retold-remote-settings-row">';tmpHTML+='<span class="retol
12755
13062
  // Server capabilities
12756
13063
  tmpHTML+='<div class="retold-remote-settings-section">';tmpHTML+='<div class="retold-remote-settings-section-title">Server Capabilities</div>';tmpHTML+='<div class="retold-remote-settings-capabilities">';let tmpTools=[{key:'sharp',label:'Sharp (image thumbnails)'},{key:'imagemagick',label:'ImageMagick (image fallback)'},{key:'ffmpeg',label:'ffmpeg (video thumbnails)'},{key:'ffprobe',label:'ffprobe (media metadata)'}];for(let i=0;i<tmpTools.length;i++){let tmpTool=tmpTools[i];let tmpAvailable=tmpCapabilities[tmpTool.key];tmpHTML+='<div class="retold-remote-settings-cap-row">';tmpHTML+='<span class="retold-remote-settings-cap-label">'+tmpTool.label+'</span>';tmpHTML+='<span class="'+(tmpAvailable?'retold-remote-settings-cap-yes':'retold-remote-settings-cap-no')+'">'+(tmpAvailable?'Available':'Not found')+'</span>';tmpHTML+='</div>';}// Hashed filenames status
12757
13064
  tmpHTML+='<div class="retold-remote-settings-cap-row" style="margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--retold-border);">';tmpHTML+='<span class="retold-remote-settings-cap-label">Hashed filenames</span>';tmpHTML+='<span class="'+(tmpRemote.HashedFilenames?'retold-remote-settings-cap-yes':'retold-remote-settings-cap-no')+'">'+(tmpRemote.HashedFilenames?'Enabled':'Disabled')+'</span>';tmpHTML+='</div>';tmpHTML+='</div>';tmpHTML+='</div>';// end capabilities section
13065
+ // AI File Sort
13066
+ tmpHTML+='<div class="retold-remote-settings-section">';tmpHTML+='<div class="retold-remote-settings-section-title">AI File Sort</div>';let tmpAISortManager=this.pict.providers['RetoldRemote-AISortManager'];let tmpAISettings=tmpRemote.AISortSettings||{AIEndpoint:'http://localhost:11434',AIModel:'llama3.1',AIProvider:'ollama',NamingTemplate:'{artist}/{album}/{track} - {title}'};// AI Endpoint
13067
+ tmpHTML+='<div class="retold-remote-settings-input-row">';tmpHTML+='<label class="retold-remote-settings-input-label">AI Endpoint URL</label>';tmpHTML+='<input class="retold-remote-settings-input" type="text" id="RetoldRemote-AISortEndpoint" value="'+this._escapeAttr(tmpAISettings.AIEndpoint)+'" onchange="pict.views[\'RetoldRemote-SettingsPanel\'].changeAISetting(\'AIEndpoint\', this.value)" placeholder="http://localhost:11434">';tmpHTML+='</div>';// AI Model
13068
+ tmpHTML+='<div class="retold-remote-settings-input-row">';tmpHTML+='<label class="retold-remote-settings-input-label">Model</label>';tmpHTML+='<input class="retold-remote-settings-input" type="text" id="RetoldRemote-AISortModel" value="'+this._escapeAttr(tmpAISettings.AIModel)+'" onchange="pict.views[\'RetoldRemote-SettingsPanel\'].changeAISetting(\'AIModel\', this.value)" placeholder="llama3.1">';tmpHTML+='</div>';// AI Provider
13069
+ tmpHTML+='<div class="retold-remote-settings-row">';tmpHTML+='<span class="retold-remote-settings-label">Provider</span>';tmpHTML+='<select class="retold-remote-settings-select" onchange="pict.views[\'RetoldRemote-SettingsPanel\'].changeAISetting(\'AIProvider\', this.value)">';tmpHTML+='<option value="ollama"'+(tmpAISettings.AIProvider==='ollama'?' selected':'')+'>Ollama</option>';tmpHTML+='<option value="openai"'+(tmpAISettings.AIProvider==='openai'?' selected':'')+'>OpenAI-compatible</option>';tmpHTML+='</select>';tmpHTML+='</div>';// Naming Template
13070
+ tmpHTML+='<div class="retold-remote-settings-input-row" style="margin-top: 8px;">';tmpHTML+='<label class="retold-remote-settings-input-label">Naming Template</label>';tmpHTML+='<input class="retold-remote-settings-input" type="text" id="RetoldRemote-AISortTemplate" value="'+this._escapeAttr(tmpAISettings.NamingTemplate)+'" onchange="pict.views[\'RetoldRemote-SettingsPanel\'].changeAISetting(\'NamingTemplate\', this.value)" placeholder="{artist}/{album}/{track} - {title}">';// Template preview
13071
+ let tmpTemplatePreview=tmpAISortManager?tmpAISortManager.getTemplatePreview(tmpAISettings.NamingTemplate):'';if(tmpTemplatePreview){tmpHTML+='<div class="retold-remote-settings-template-preview">Preview: '+this._escapeHTML(tmpTemplatePreview)+'</div>';}tmpHTML+='</div>';// Test Connection button
13072
+ tmpHTML+='<button class="retold-remote-settings-vlc-btn" id="RetoldRemote-AISortTestBtn" onclick="pict.views[\'RetoldRemote-SettingsPanel\'].testAIConnection()" style="margin-top: 8px;">';tmpHTML+='Test Connection';tmpHTML+='</button>';tmpHTML+='</div>';// end AI sort section
12758
13073
  // VLC Setup
12759
13074
  tmpHTML+='<div class="retold-remote-settings-section">';tmpHTML+='<div class="retold-remote-settings-section-title">VLC Streaming</div>';tmpHTML+='<button class="retold-remote-settings-vlc-btn" onclick="pict.views[\'RetoldRemote-VLCSetup\'].openModal()">';tmpHTML+='VLC Protocol Setup';tmpHTML+='</button>';tmpHTML+='</div>';// Help button
12760
13075
  tmpHTML+='<div class="retold-remote-settings-section">';tmpHTML+='<div class="retold-remote-settings-section-title">Help</div>';tmpHTML+='<button class="retold-remote-settings-vlc-btn" onclick="pict.providers[\'RetoldRemote-GalleryNavigation\']._toggleHelpPanel()">';tmpHTML+='Help (F1)';tmpHTML+='</button>';tmpHTML+='</div>';tmpHTML+='</div>';// end settings
@@ -12762,8 +13077,26 @@ tmpContainer.innerHTML=tmpHTML;}changeTheme(pThemeKey){let tmpThemeProvider=this
12762
13077
  this._renderSettingsContent();}}changeSetting(pKey,pValue){let tmpRemote=this.pict.AppData.RetoldRemote;tmpRemote[pKey]=pValue;this.pict.PictApplication.saveSettings();// Re-render gallery if visible
12763
13078
  if(tmpRemote.ActiveMode==='gallery'){let tmpGalleryView=this.pict.views['RetoldRemote-Gallery'];if(tmpGalleryView){tmpGalleryView.renderGallery();}}}toggleHiddenFiles(pChecked){let tmpRemote=this.pict.AppData.RetoldRemote;tmpRemote.ShowHiddenFiles=pChecked;this.pict.PictApplication.saveSettings();this.pict.PictApplication.syncHiddenFilesSetting(()=>{this.pict.PictApplication.loadFileList();});}toggleAutoplay(pKey,pChecked){let tmpRemote=this.pict.AppData.RetoldRemote;tmpRemote[pKey]=pChecked;this.pict.PictApplication.saveSettings();}toggleDistractionFreeNav(pChecked){let tmpRemote=this.pict.AppData.RetoldRemote;tmpRemote.DistractionFreeShowNav=pChecked;this.pict.PictApplication.saveSettings();// If currently in distraction-free mode, apply immediately
12764
13079
  if(tmpRemote._distractionFreeMode){let tmpViewerHeader=document.querySelector('.retold-remote-viewer-header');if(tmpViewerHeader){tmpViewerHeader.style.display=pChecked?'':'none';}}}changeImageFitMode(pMode){let tmpImageViewer=this.pict.views['RetoldRemote-ImageViewer'];if(tmpImageViewer){tmpImageViewer.setFitMode(pMode);}else{let tmpRemote=this.pict.AppData.RetoldRemote;tmpRemote.ImageFitMode=pMode;this.pict.PictApplication.saveSettings();}}changeSortField(pValue){let tmpRemote=this.pict.AppData.RetoldRemote;tmpRemote.SortField=pValue;this.pict.PictApplication.saveSettings();this._refilterGallery();}changeSortDirection(pValue){let tmpRemote=this.pict.AppData.RetoldRemote;tmpRemote.SortDirection=pValue;this.pict.PictApplication.saveSettings();this._refilterGallery();}changeMediaFilter(pValue){let tmpRemote=this.pict.AppData.RetoldRemote;tmpRemote.GalleryFilter=pValue;if(tmpRemote.FilterState){tmpRemote.FilterState.MediaType=pValue;}this.pict.PictApplication.saveSettings();this._refilterGallery();}/**
13080
+ * Change an AI sort setting.
13081
+ *
13082
+ * @param {string} pKey - Setting key (AIEndpoint, AIModel, AIProvider, NamingTemplate)
13083
+ * @param {string} pValue - New value
13084
+ */changeAISetting(pKey,pValue){let tmpAISortManager=this.pict.providers['RetoldRemote-AISortManager'];if(tmpAISortManager){let tmpUpdate={};tmpUpdate[pKey]=pValue;tmpAISortManager.updateSettings(tmpUpdate);}// Update the template preview if the template changed
13085
+ if(pKey==='NamingTemplate'){this._renderSettingsContent();}}/**
13086
+ * Test the AI endpoint connection.
13087
+ */testAIConnection(){let tmpBtn=document.getElementById('RetoldRemote-AISortTestBtn');if(tmpBtn){tmpBtn.disabled=true;tmpBtn.textContent='Testing...';}let tmpAISortManager=this.pict.providers['RetoldRemote-AISortManager'];if(tmpAISortManager){tmpAISortManager.testConnection();}}/**
13088
+ * Escape HTML attribute values.
13089
+ *
13090
+ * @param {string} pStr
13091
+ * @returns {string}
13092
+ */_escapeAttr(pStr){if(!pStr)return'';return String(pStr).replace(/&/g,'&amp;').replace(/"/g,'&quot;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}/**
13093
+ * Escape HTML text content.
13094
+ *
13095
+ * @param {string} pStr
13096
+ * @returns {string}
13097
+ */_escapeHTML(pStr){if(!pStr)return'';return String(pStr).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}/**
12765
13098
  * Re-run the filter/sort pipeline and refresh the gallery.
12766
- */_refilterGallery(){let tmpRemote=this.pict.AppData.RetoldRemote;let tmpFilterSort=this.pict.providers['RetoldRemote-GalleryFilterSort'];if(tmpFilterSort){tmpFilterSort.runFilterPipeline();}if(tmpRemote.ActiveMode==='gallery'){let tmpGalleryView=this.pict.views['RetoldRemote-Gallery'];if(tmpGalleryView){tmpGalleryView.renderGallery();}}}}RetoldRemoteSettingsPanelView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteSettingsPanelView;},{"pict-view":76}],135:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"ContentEditor-TopBar",DefaultRenderable:"RetoldRemote-TopBar",DefaultDestinationAddress:"#ContentEditor-TopBar-Container",AutoRender:false,CSS:/*css*/`
13099
+ */_refilterGallery(){let tmpRemote=this.pict.AppData.RetoldRemote;let tmpFilterSort=this.pict.providers['RetoldRemote-GalleryFilterSort'];if(tmpFilterSort){tmpFilterSort.runFilterPipeline();}if(tmpRemote.ActiveMode==='gallery'){let tmpGalleryView=this.pict.views['RetoldRemote-Gallery'];if(tmpGalleryView){tmpGalleryView.renderGallery();}}}}RetoldRemoteSettingsPanelView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteSettingsPanelView;},{"pict-view":76}],136:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"ContentEditor-TopBar",DefaultRenderable:"RetoldRemote-TopBar",DefaultDestinationAddress:"#ContentEditor-TopBar-Container",AutoRender:false,CSS:/*css*/`
12767
13100
  .retold-remote-topbar
12768
13101
  {
12769
13102
  display: flex;
@@ -13087,6 +13420,31 @@ if(tmpRemote._distractionFreeMode){let tmpViewerHeader=document.querySelector('.
13087
13420
  border-color: var(--retold-text-muted);
13088
13421
  background: rgba(128, 128, 128, 0.06);
13089
13422
  }
13423
+ .retold-remote-topbar-aisort-btn
13424
+ {
13425
+ padding: 4px 8px;
13426
+ border: 1px solid var(--retold-border);
13427
+ border-radius: 3px;
13428
+ background: transparent;
13429
+ color: var(--retold-text-muted);
13430
+ font-size: 0.72rem;
13431
+ cursor: pointer;
13432
+ transition: color 0.15s, border-color 0.15s, background 0.15s;
13433
+ font-family: inherit;
13434
+ white-space: nowrap;
13435
+ }
13436
+ .retold-remote-topbar-aisort-btn:hover
13437
+ {
13438
+ color: var(--retold-text-primary);
13439
+ border-color: var(--retold-accent);
13440
+ background: rgba(128, 128, 128, 0.1);
13441
+ }
13442
+ .retold-remote-topbar-aisort-btn.generating
13443
+ {
13444
+ color: var(--retold-accent);
13445
+ border-color: var(--retold-accent);
13446
+ cursor: wait;
13447
+ }
13090
13448
  .retold-remote-topbar-filter-badge
13091
13449
  {
13092
13450
  position: absolute;
@@ -13110,6 +13468,7 @@ if(tmpRemote._distractionFreeMode){let tmpViewerHeader=document.querySelector('.
13110
13468
  <div class="retold-remote-topbar-location" id="RetoldRemote-TopBar-Location"></div>
13111
13469
  <div class="retold-remote-topbar-info" id="RetoldRemote-TopBar-Info"></div>
13112
13470
  <div class="retold-remote-topbar-actions">
13471
+ <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>
13113
13472
  <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">+&#9733;</button>
13114
13473
  <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)">&#9733;</button>
13115
13474
  <button class="retold-remote-topbar-filter-btn" id="RetoldRemote-TopBar-FilterBtn" onclick="pict.views['ContentEditor-TopBar'].toggleFilterBar()" title="Toggle filter bar (/)">&#9698;</button>
@@ -13160,7 +13519,16 @@ tmpBtn.classList.add('filter-active');tmpBtn.innerHTML='&#9683;<span class="reto
13160
13519
  tmpBtn.classList.add('filter-bar-open');tmpBtn.innerHTML='&#9698;';tmpBtn.title='Hide filter bar (/)';}else{// Default: no filters, bar hidden
13161
13520
  tmpBtn.innerHTML='&#9698;';tmpBtn.title='Toggle filter bar (/)';}}/**
13162
13521
  * Update the info display with folder summary.
13163
- */updateInfo(){let tmpInfoEl=document.getElementById('RetoldRemote-TopBar-Info');if(!tmpInfoEl){return;}let tmpRemote=this.pict.AppData.RetoldRemote;let tmpSummary=tmpRemote.FolderSummary;if(tmpRemote.ActiveMode==='viewer'){let tmpItems=tmpRemote.GalleryItems||[];let tmpIndex=tmpRemote.GalleryCursorIndex||0;let tmpItem=tmpItems[tmpIndex];if(tmpItem){let tmpPos=tmpIndex+1+'/'+tmpItems.length;tmpInfoEl.textContent=tmpPos+' \u00b7 '+tmpItem.Name;}return;}let tmpItems=tmpRemote.GalleryItems||[];let tmpIndex=tmpRemote.GalleryCursorIndex||0;let tmpCursorText='';if(tmpItems.length>0){tmpCursorText=tmpIndex+1+'/'+tmpItems.length;}if(!tmpSummary){tmpInfoEl.textContent=tmpCursorText;return;}let tmpParts=[];if(tmpCursorText)tmpParts.push(tmpCursorText);if(tmpSummary.Folders>0)tmpParts.push(tmpSummary.Folders+' folders');if(tmpSummary.Images>0)tmpParts.push(tmpSummary.Images+' images');if(tmpSummary.Videos>0)tmpParts.push(tmpSummary.Videos+' videos');if(tmpSummary.Audio>0)tmpParts.push(tmpSummary.Audio+' audio');if(tmpSummary.Documents>0)tmpParts.push(tmpSummary.Documents+' docs');if(tmpSummary.Other>0)tmpParts.push(tmpSummary.Other+' other');tmpInfoEl.textContent=tmpParts.join(' \u00b7 ');}// -- Collections Panel ------------------------------------------------
13522
+ * Also updates the AI Sort button visibility.
13523
+ */updateInfo(){this.updateAISortButton();let tmpInfoEl=document.getElementById('RetoldRemote-TopBar-Info');if(!tmpInfoEl){return;}let tmpRemote=this.pict.AppData.RetoldRemote;let tmpSummary=tmpRemote.FolderSummary;if(tmpRemote.ActiveMode==='viewer'){let tmpItems=tmpRemote.GalleryItems||[];let tmpIndex=tmpRemote.GalleryCursorIndex||0;let tmpItem=tmpItems[tmpIndex];if(tmpItem){let tmpPos=tmpIndex+1+'/'+tmpItems.length;tmpInfoEl.textContent=tmpPos+' \u00b7 '+tmpItem.Name;}return;}let tmpItems=tmpRemote.GalleryItems||[];let tmpIndex=tmpRemote.GalleryCursorIndex||0;let tmpCursorText='';if(tmpItems.length>0){tmpCursorText=tmpIndex+1+'/'+tmpItems.length;}if(!tmpSummary){tmpInfoEl.textContent=tmpCursorText;return;}let tmpParts=[];if(tmpCursorText)tmpParts.push(tmpCursorText);if(tmpSummary.Folders>0)tmpParts.push(tmpSummary.Folders+' folders');if(tmpSummary.Images>0)tmpParts.push(tmpSummary.Images+' images');if(tmpSummary.Videos>0)tmpParts.push(tmpSummary.Videos+' videos');if(tmpSummary.Audio>0)tmpParts.push(tmpSummary.Audio+' audio');if(tmpSummary.Documents>0)tmpParts.push(tmpSummary.Documents+' docs');if(tmpSummary.Other>0)tmpParts.push(tmpSummary.Other+' other');tmpInfoEl.textContent=tmpParts.join(' \u00b7 ');}// -- AI Sort ----------------------------------------------------------
13524
+ /**
13525
+ * Trigger AI sort for the current folder.
13526
+ */triggerAISort(){let tmpAISortManager=this.pict.providers['RetoldRemote-AISortManager'];if(!tmpAISortManager){return;}let tmpCurrentPath=this.pict.AppData.PictFileBrowser&&this.pict.AppData.PictFileBrowser.CurrentLocation||'';// Show generating state
13527
+ let tmpBtn=document.getElementById('RetoldRemote-TopBar-AISortBtn');if(tmpBtn){tmpBtn.classList.add('generating');tmpBtn.textContent='Sorting...';}tmpAISortManager.generateSortPlan(tmpCurrentPath,(pError,pResult)=>{// Reset button state
13528
+ if(tmpBtn){tmpBtn.classList.remove('generating');tmpBtn.textContent='AI Sort';}});}/**
13529
+ * Update the AI Sort button visibility.
13530
+ * Shows only when browsing a folder (gallery mode).
13531
+ */updateAISortButton(){let tmpBtn=document.getElementById('RetoldRemote-TopBar-AISortBtn');if(!tmpBtn){return;}let tmpAISortManager=this.pict.providers['RetoldRemote-AISortManager'];if(tmpAISortManager&&tmpAISortManager.isAvailable()){tmpBtn.style.display='';}else{tmpBtn.style.display='none';}}// -- Collections Panel ------------------------------------------------
13164
13532
  /**
13165
13533
  * Toggle the collections panel.
13166
13534
  */toggleCollections(){let tmpManager=this.pict.providers['RetoldRemote-CollectionManager'];if(tmpManager){tmpManager.togglePanel();}}/**
@@ -13185,7 +13553,7 @@ for(let i=0;i<tmpCollections.length;i++){let tmpCollection=tmpCollections[i];let
13185
13553
  tmpBtn.style.position='relative';tmpBtn.appendChild(tmpDropdown);// Close on outside click
13186
13554
  setTimeout(()=>{document.addEventListener('click',tmpSelf._boundCloseDropdown=pClickEvent=>{if(!tmpDropdown.contains(pClickEvent.target)&&pClickEvent.target!==tmpBtn){tmpSelf._closeAddToCollectionDropdown();}});},10);});}/**
13187
13555
  * Close the add-to-collection dropdown.
13188
- */_closeAddToCollectionDropdown(){let tmpDropdown=document.getElementById('RetoldRemote-AddToCollection-Dropdown');if(tmpDropdown){tmpDropdown.remove();}if(this._boundCloseDropdown){document.removeEventListener('click',this._boundCloseDropdown);this._boundCloseDropdown=null;}}}RetoldRemoteTopBarView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteTopBarView;},{"pict-view":76}],136:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-VLCSetup",DefaultRenderable:"RetoldRemote-VLCSetup",DefaultDestinationAddress:"#ContentEditor-Application-Container",AutoRender:false,CSS:/*css*/`
13556
+ */_closeAddToCollectionDropdown(){let tmpDropdown=document.getElementById('RetoldRemote-AddToCollection-Dropdown');if(tmpDropdown){tmpDropdown.remove();}if(this._boundCloseDropdown){document.removeEventListener('click',this._boundCloseDropdown);this._boundCloseDropdown=null;}}}RetoldRemoteTopBarView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteTopBarView;},{"pict-view":76}],137:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-VLCSetup",DefaultRenderable:"RetoldRemote-VLCSetup",DefaultDestinationAddress:"#ContentEditor-Application-Container",AutoRender:false,CSS:/*css*/`
13189
13557
  .retold-remote-vlc-modal-backdrop
13190
13558
  {
13191
13559
  position: fixed;
@@ -13437,7 +13805,7 @@ tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="r
13437
13805
  tmpHTML+='<div class="retold-remote-vlc-setup-status">';tmpHTML+='<div class="retold-remote-vlc-setup-status-dot '+(this._detectPlatform()===tmpPlatform?'detected':'unknown')+'"></div>';tmpHTML+='<span>Detected platform: <b>'+this._getPlatformLabel(this._detectPlatform())+'</b></span>';tmpHTML+='</div>';// Platform tabs
13438
13806
  tmpHTML+='<div class="retold-remote-vlc-setup-platform-tabs">';tmpHTML+=this._buildPlatformTab('macos','macOS',tmpPlatform);tmpHTML+=this._buildPlatformTab('windows','Windows',tmpPlatform);tmpHTML+=this._buildPlatformTab('linux','Linux',tmpPlatform);tmpHTML+='</div>';// Platform-specific content
13439
13807
  tmpHTML+=this._buildMacOSContent(tmpPlatform);tmpHTML+=this._buildWindowsContent(tmpPlatform);tmpHTML+=this._buildLinuxContent(tmpPlatform);// Test section
13440
- tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Test</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='Click below to test whether the vlc:// protocol handler is registered. VLC should open.';tmpHTML+='</div>';tmpHTML+='<button class="retold-remote-vlc-setup-btn" onclick="pict.views[\'RetoldRemote-VLCSetup\'].testProtocol()">Test VLC Protocol</button>';tmpHTML+='</div>';tmpContainer.innerHTML=tmpHTML;}_buildPlatformTab(pKey,pLabel,pActive){let tmpClass='retold-remote-vlc-setup-platform-tab';if(pKey===pActive){tmpClass+=' active';}return'<button class="'+tmpClass+'" onclick="pict.views[\'RetoldRemote-VLCSetup\'].switchPlatformTab(\''+pKey+'\')">'+pLabel+'</button>';}_getPlatformLabel(pKey){if(pKey==='macos')return'macOS';if(pKey==='windows')return'Windows';return'Linux';}_buildMacOSContent(pActive){let tmpClass='retold-remote-vlc-setup-platform'+(pActive==='macos'?' active':'');let tmpHTML='<div class="'+tmpClass+'" data-platform="macos">';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Setup (macOS)</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='VLC on macOS does not register a vlc:// protocol handler by default. ';tmpHTML+='An AppleScript app bundle is needed to bridge vlc:// links to VLC. ';tmpHTML+='Run the command below in Terminal to create and register the handler automatically.';tmpHTML+='</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Automatic Setup</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='Copy and paste this into Terminal:';tmpHTML+='</div>';let tmpScript=this._getMacSetupScript();tmpHTML+='<div class="retold-remote-vlc-setup-code">'+this.pict.providers['RetoldRemote-FormattingUtilities'].escapeHTML(tmpScript)+'</div>';tmpHTML+='<button class="retold-remote-vlc-setup-btn primary" onclick="pict.views[\'RetoldRemote-VLCSetup\'].copyMacSetup()">Copy to Clipboard</button>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">What This Does</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">1</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Creates an AppleScript at <code>/tmp/VLCProtocol.applescript</code> that handles vlc:// URLs</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">2</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Compiles it into an app bundle at <code>/Applications/VLCProtocol.app</code></div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">3</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Adds the vlc:// URL scheme to the app\'s Info.plist</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">4</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Registers the protocol handler with macOS Launch Services</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-note">Requires VLC installed at /Applications/VLC.app and Python 3 (included with macOS).</div>';tmpHTML+='</div>';tmpHTML+='</div>';return tmpHTML;}_buildWindowsContent(pActive){let tmpClass='retold-remote-vlc-setup-platform'+(pActive==='windows'?' active':'');let tmpHTML='<div class="'+tmpClass+'" data-platform="windows">';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Setup (Windows)</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='VLC on Windows registers the vlc:// protocol handler during installation. ';tmpHTML+='If it is not working, you can re-register it by saving and running the registry file below.';tmpHTML+='</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Option A: Reinstall VLC</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">1</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Reinstall VLC and ensure "Register VLC as handler for vlc:// protocol" is checked during installation.</div>';tmpHTML+='</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Option B: Registry File</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='Save this as <code>vlc-protocol.reg</code> and double-click to import. ';tmpHTML+='Adjust the VLC path if yours differs.';tmpHTML+='</div>';let tmpRegFile=this._getWindowsRegFile();tmpHTML+='<div class="retold-remote-vlc-setup-code">'+this.pict.providers['RetoldRemote-FormattingUtilities'].escapeHTML(tmpRegFile)+'</div>';tmpHTML+='<button class="retold-remote-vlc-setup-btn primary" onclick="pict.views[\'RetoldRemote-VLCSetup\'].copyWindowsReg()">Copy to Clipboard</button>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Option C: Batch Script</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='Alternatively, save this as <code>vlc-protocol-setup.bat</code> and run as Administrator. ';tmpHTML+='This creates a wrapper script that URL-decodes the vlc:// link before passing it to VLC.';tmpHTML+='</div>';let tmpBatchScript=this._getWindowsBatchScript();tmpHTML+='<div class="retold-remote-vlc-setup-code">'+this.pict.providers['RetoldRemote-FormattingUtilities'].escapeHTML(tmpBatchScript)+'</div>';tmpHTML+='<button class="retold-remote-vlc-setup-btn primary" onclick="pict.views[\'RetoldRemote-VLCSetup\'].copyWindowsBatch()">Copy to Clipboard</button>';tmpHTML+='</div>';tmpHTML+='</div>';return tmpHTML;}_buildLinuxContent(pActive){let tmpClass='retold-remote-vlc-setup-platform'+(pActive==='linux'?' active':'');let tmpHTML='<div class="'+tmpClass+'" data-platform="linux">';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Setup (Linux)</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='Register a vlc:// protocol handler using a .desktop file and xdg-mime. ';tmpHTML+='Run the command below in a terminal.';tmpHTML+='</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Setup Command</div>';let tmpScript=this._getLinuxSetupScript();tmpHTML+='<div class="retold-remote-vlc-setup-code">'+this.pict.providers['RetoldRemote-FormattingUtilities'].escapeHTML(tmpScript)+'</div>';tmpHTML+='<button class="retold-remote-vlc-setup-btn primary" onclick="pict.views[\'RetoldRemote-VLCSetup\'].copyLinuxSetup()">Copy to Clipboard</button>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">What This Does</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">1</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Creates a handler script at <code>~/.local/bin/vlc-protocol</code> that URL-decodes and opens VLC</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">2</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Creates a .desktop file at <code>~/.local/share/applications/vlc-protocol.desktop</code></div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">3</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Registers vlc:// as a URL scheme via <code>xdg-mime</code></div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-note">Requires VLC and Python 3 installed.</div>';tmpHTML+='</div>';tmpHTML+='</div>';return tmpHTML;}_getMacSetupScript(){return["# Create the AppleScript handler","cat > /tmp/VLCProtocol.applescript << 'EOF'","on open location theURL","\tset theURL to text 7 thru -1 of theURL","\tset theURL to do shell script \"python3 -c 'import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))' \" & quoted form of theURL","\tdo shell script \"open -a VLC \" & quoted form of theURL","end open location","EOF","","# Compile into app bundle","osacompile -o /Applications/VLCProtocol.app /tmp/VLCProtocol.applescript","","# Add vlc:// URL scheme to Info.plist","/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes array\" \\"," /Applications/VLCProtocol.app/Contents/Info.plist 2>/dev/null","/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:0 dict\" \\"," /Applications/VLCProtocol.app/Contents/Info.plist 2>/dev/null","/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:0:CFBundleURLName string 'VLC Protocol'\" \\"," /Applications/VLCProtocol.app/Contents/Info.plist 2>/dev/null","/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:0:CFBundleURLSchemes array\" \\"," /Applications/VLCProtocol.app/Contents/Info.plist 2>/dev/null","/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:0:CFBundleURLSchemes:0 string vlc\" \\"," /Applications/VLCProtocol.app/Contents/Info.plist 2>/dev/null","","# Register with Launch Services","/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister \\"," -f /Applications/VLCProtocol.app","","echo \"VLC protocol handler installed successfully.\""].join('\n');}_getWindowsRegFile(){return["Windows Registry Editor Version 5.00","","[HKEY_CLASSES_ROOT\\vlc]","@=\"URL:VLC Protocol\"","\"URL Protocol\"=\"\"","","[HKEY_CLASSES_ROOT\\vlc\\shell]","","[HKEY_CLASSES_ROOT\\vlc\\shell\\open]","","[HKEY_CLASSES_ROOT\\vlc\\shell\\open\\command]","@=\"\\\"C:\\\\Program Files\\\\VideoLAN\\\\VLC\\\\vlc.exe\\\" \\\"%1\\\"\""].join('\n');}_getWindowsBatchScript(){return["@echo off","REM VLC Protocol Handler Setup for Windows","REM Run this as Administrator","","REM Create the handler script","mkdir \"%APPDATA%\\VLCProtocol\" 2>nul","(","echo import sys, urllib.parse, subprocess","echo url = sys.argv[1] if len(sys.argv^) ^> 1 else ''","echo if url.startswith('vlc://'^): url = url[6:]","echo url = urllib.parse.unquote(url^)","echo subprocess.Popen(['C:\\\\Program Files\\\\VideoLAN\\\\VLC\\\\vlc.exe', url]^)",") > \"%APPDATA%\\VLCProtocol\\handler.py\"","","REM Register the protocol in the registry","reg add \"HKCU\\Software\\Classes\\vlc\" /ve /d \"URL:VLC Protocol\" /f","reg add \"HKCU\\Software\\Classes\\vlc\" /v \"URL Protocol\" /d \"\" /f","reg add \"HKCU\\Software\\Classes\\vlc\\shell\\open\\command\" /ve /d \"pythonw \\\"%APPDATA%\\VLCProtocol\\handler.py\\\" \\\"%%1\\\"\" /f","","echo VLC protocol handler installed successfully.","pause"].join('\n');}_getLinuxSetupScript(){return["# Create handler script","mkdir -p ~/.local/bin","cat > ~/.local/bin/vlc-protocol << 'EOF'","#!/bin/bash","URL=\"$1\"","URL=\"${URL#vlc://}\"","URL=$(python3 -c \"import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))\" \"$URL\")","exec vlc \"$URL\" &","EOF","chmod +x ~/.local/bin/vlc-protocol","","# Create .desktop file","cat > ~/.local/share/applications/vlc-protocol.desktop << 'EOF'","[Desktop Entry]","Name=VLC Protocol Handler","Exec=bash -c '~/.local/bin/vlc-protocol %u'","Type=Application","NoDisplay=true","MimeType=x-scheme-handler/vlc;","EOF","","# Register the handler","xdg-mime default vlc-protocol.desktop x-scheme-handler/vlc","update-desktop-database ~/.local/share/applications/","","echo \"VLC protocol handler installed successfully.\""].join('\n');}_copyToClipboard(pText,pLabel){if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(pText).then(()=>{this.pict.providers['RetoldRemote-ToastNotification'].showToast(pLabel+' copied to clipboard');}).catch(()=>{this._fallbackCopy(pText,pLabel);});}else{this._fallbackCopy(pText,pLabel);}}_fallbackCopy(pText,pLabel){let tmpTextarea=document.createElement('textarea');tmpTextarea.value=pText;tmpTextarea.style.position='fixed';tmpTextarea.style.left='-9999px';document.body.appendChild(tmpTextarea);tmpTextarea.select();try{document.execCommand('copy');this.pict.providers['RetoldRemote-ToastNotification'].showToast(pLabel+' copied to clipboard');}catch(pErr){this.pict.providers['RetoldRemote-ToastNotification'].showToast('Failed to copy - please select and copy manually');}document.body.removeChild(tmpTextarea);}copyMacSetup(){this._copyToClipboard(this._getMacSetupScript(),'macOS setup script');}copyWindowsReg(){this._copyToClipboard(this._getWindowsRegFile(),'Registry file');}copyWindowsBatch(){this._copyToClipboard(this._getWindowsBatchScript(),'Batch script');}copyLinuxSetup(){this._copyToClipboard(this._getLinuxSetupScript(),'Linux setup script');}testProtocol(){let tmpIsWindows=/Windows/.test(navigator.userAgent);let tmpSampleURL='https://www.sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4';let tmpTestURL=tmpIsWindows?'vlc://'+tmpSampleURL:'vlc://'+encodeURIComponent(tmpSampleURL);let tmpLink=document.createElement('a');tmpLink.href=tmpTestURL;tmpLink.style.display='none';document.body.appendChild(tmpLink);tmpLink.click();document.body.removeChild(tmpLink);}}RetoldRemoteVLCSetupView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteVLCSetupView;},{"pict-view":76}],137:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-VideoExplorer",DefaultRenderable:"RetoldRemote-VideoExplorer",DefaultDestinationAddress:"#RetoldRemote-Viewer-Container",AutoRender:false,CSS:/*css*/`
13808
+ tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Test</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='Click below to test whether the vlc:// protocol handler is registered. VLC should open.';tmpHTML+='</div>';tmpHTML+='<button class="retold-remote-vlc-setup-btn" onclick="pict.views[\'RetoldRemote-VLCSetup\'].testProtocol()">Test VLC Protocol</button>';tmpHTML+='</div>';tmpContainer.innerHTML=tmpHTML;}_buildPlatformTab(pKey,pLabel,pActive){let tmpClass='retold-remote-vlc-setup-platform-tab';if(pKey===pActive){tmpClass+=' active';}return'<button class="'+tmpClass+'" onclick="pict.views[\'RetoldRemote-VLCSetup\'].switchPlatformTab(\''+pKey+'\')">'+pLabel+'</button>';}_getPlatformLabel(pKey){if(pKey==='macos')return'macOS';if(pKey==='windows')return'Windows';return'Linux';}_buildMacOSContent(pActive){let tmpClass='retold-remote-vlc-setup-platform'+(pActive==='macos'?' active':'');let tmpHTML='<div class="'+tmpClass+'" data-platform="macos">';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Setup (macOS)</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='VLC on macOS does not register a vlc:// protocol handler by default. ';tmpHTML+='An AppleScript app bundle is needed to bridge vlc:// links to VLC. ';tmpHTML+='Run the command below in Terminal to create and register the handler automatically.';tmpHTML+='</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Automatic Setup</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='Copy and paste this into Terminal:';tmpHTML+='</div>';let tmpScript=this._getMacSetupScript();tmpHTML+='<div class="retold-remote-vlc-setup-code">'+this.pict.providers['RetoldRemote-FormattingUtilities'].escapeHTML(tmpScript)+'</div>';tmpHTML+='<button class="retold-remote-vlc-setup-btn primary" onclick="pict.views[\'RetoldRemote-VLCSetup\'].copyMacSetup()">Copy to Clipboard</button>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">What This Does</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">1</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Creates an AppleScript at <code>/tmp/VLCProtocol.applescript</code> that handles vlc:// URLs</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">2</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Compiles it into an app bundle at <code>/Applications/VLCProtocol.app</code></div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">3</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Adds the vlc:// URL scheme to the app\'s Info.plist</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">4</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Registers the protocol handler with macOS Launch Services</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-note">Requires VLC installed at /Applications/VLC.app and Python 3 (included with macOS).</div>';tmpHTML+='</div>';tmpHTML+='</div>';return tmpHTML;}_buildWindowsContent(pActive){let tmpClass='retold-remote-vlc-setup-platform'+(pActive==='windows'?' active':'');let tmpHTML='<div class="'+tmpClass+'" data-platform="windows">';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Setup (Windows)</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='VLC on Windows registers the vlc:// protocol handler during installation. ';tmpHTML+='If it is not working, you can re-register it by saving and running the registry file below.';tmpHTML+='</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Option A: Reinstall VLC</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">1</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Reinstall VLC and ensure "Register VLC as handler for vlc:// protocol" is checked during installation.</div>';tmpHTML+='</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Option B: Registry File</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='Save this as <code>vlc-protocol.reg</code> and double-click to import. ';tmpHTML+='Adjust the VLC path if yours differs.';tmpHTML+='</div>';let tmpRegFile=this._getWindowsRegFile();tmpHTML+='<div class="retold-remote-vlc-setup-code">'+this.pict.providers['RetoldRemote-FormattingUtilities'].escapeHTML(tmpRegFile)+'</div>';tmpHTML+='<button class="retold-remote-vlc-setup-btn primary" onclick="pict.views[\'RetoldRemote-VLCSetup\'].copyWindowsReg()">Copy to Clipboard</button>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Option C: Batch Script</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='Alternatively, save this as <code>vlc-protocol-setup.bat</code> and run as Administrator. ';tmpHTML+='This creates a wrapper script that URL-decodes the vlc:// link before passing it to VLC.';tmpHTML+='</div>';let tmpBatchScript=this._getWindowsBatchScript();tmpHTML+='<div class="retold-remote-vlc-setup-code">'+this.pict.providers['RetoldRemote-FormattingUtilities'].escapeHTML(tmpBatchScript)+'</div>';tmpHTML+='<button class="retold-remote-vlc-setup-btn primary" onclick="pict.views[\'RetoldRemote-VLCSetup\'].copyWindowsBatch()">Copy to Clipboard</button>';tmpHTML+='</div>';tmpHTML+='</div>';return tmpHTML;}_buildLinuxContent(pActive){let tmpClass='retold-remote-vlc-setup-platform'+(pActive==='linux'?' active':'');let tmpHTML='<div class="'+tmpClass+'" data-platform="linux">';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Setup (Linux)</div>';tmpHTML+='<div class="retold-remote-vlc-setup-desc">';tmpHTML+='Register a vlc:// protocol handler using a .desktop file and xdg-mime. ';tmpHTML+='Run the command below in a terminal.';tmpHTML+='</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">Setup Command</div>';let tmpScript=this._getLinuxSetupScript();tmpHTML+='<div class="retold-remote-vlc-setup-code">'+this.pict.providers['RetoldRemote-FormattingUtilities'].escapeHTML(tmpScript)+'</div>';tmpHTML+='<button class="retold-remote-vlc-setup-btn primary" onclick="pict.views[\'RetoldRemote-VLCSetup\'].copyLinuxSetup()">Copy to Clipboard</button>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-section">';tmpHTML+='<div class="retold-remote-vlc-setup-section-title">What This Does</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">1</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Creates a handler script at <code>~/.local/bin/vlc-protocol</code> that URL-decodes and opens VLC</div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">2</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Creates a .desktop file at <code>~/.local/share/applications/vlc-protocol.desktop</code></div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step">';tmpHTML+='<div class="retold-remote-vlc-setup-step-num">3</div>';tmpHTML+='<div class="retold-remote-vlc-setup-step-content">Registers vlc:// as a URL scheme via <code>xdg-mime</code></div>';tmpHTML+='</div>';tmpHTML+='<div class="retold-remote-vlc-setup-note">Requires VLC and Python 3 installed.</div>';tmpHTML+='</div>';tmpHTML+='</div>';return tmpHTML;}_getMacSetupScript(){return["# Create the AppleScript handler","cat > /tmp/VLCProtocol.applescript << 'EOF'","on open location theURL","\tset theURL to text 7 thru -1 of theURL","\tset theURL to do shell script \"python3 -c 'import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))' \" & quoted form of theURL","\tdo shell script \"open -a VLC \" & quoted form of theURL","end open location","EOF","","# Compile into app bundle","osacompile -o /Applications/VLCProtocol.app /tmp/VLCProtocol.applescript","","# Add vlc:// URL scheme to Info.plist","/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes array\" \\"," /Applications/VLCProtocol.app/Contents/Info.plist 2>/dev/null","/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:0 dict\" \\"," /Applications/VLCProtocol.app/Contents/Info.plist 2>/dev/null","/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:0:CFBundleURLName string 'VLC Protocol'\" \\"," /Applications/VLCProtocol.app/Contents/Info.plist 2>/dev/null","/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:0:CFBundleURLSchemes array\" \\"," /Applications/VLCProtocol.app/Contents/Info.plist 2>/dev/null","/usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:0:CFBundleURLSchemes:0 string vlc\" \\"," /Applications/VLCProtocol.app/Contents/Info.plist 2>/dev/null","","# Register with Launch Services","/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister \\"," -f /Applications/VLCProtocol.app","","echo \"VLC protocol handler installed successfully.\""].join('\n');}_getWindowsRegFile(){return["Windows Registry Editor Version 5.00","","[HKEY_CLASSES_ROOT\\vlc]","@=\"URL:VLC Protocol\"","\"URL Protocol\"=\"\"","","[HKEY_CLASSES_ROOT\\vlc\\shell]","","[HKEY_CLASSES_ROOT\\vlc\\shell\\open]","","[HKEY_CLASSES_ROOT\\vlc\\shell\\open\\command]","@=\"\\\"C:\\\\Program Files\\\\VideoLAN\\\\VLC\\\\vlc.exe\\\" \\\"%1\\\"\""].join('\n');}_getWindowsBatchScript(){return["@echo off","REM VLC Protocol Handler Setup for Windows","REM Run this as Administrator","","REM Create the handler script","mkdir \"%APPDATA%\\VLCProtocol\" 2>nul","(","echo import sys, urllib.parse, subprocess","echo url = sys.argv[1] if len(sys.argv^) ^> 1 else ''","echo if url.startswith('vlc://'^): url = url[6:]","echo url = urllib.parse.unquote(url^)","echo subprocess.Popen(['C:\\\\Program Files\\\\VideoLAN\\\\VLC\\\\vlc.exe', url]^)",") > \"%APPDATA%\\VLCProtocol\\handler.py\"","","REM Register the protocol in the registry","reg add \"HKCU\\Software\\Classes\\vlc\" /ve /d \"URL:VLC Protocol\" /f","reg add \"HKCU\\Software\\Classes\\vlc\" /v \"URL Protocol\" /d \"\" /f","reg add \"HKCU\\Software\\Classes\\vlc\\shell\\open\\command\" /ve /d \"pythonw \\\"%APPDATA%\\VLCProtocol\\handler.py\\\" \\\"%%1\\\"\" /f","","echo VLC protocol handler installed successfully.","pause"].join('\n');}_getLinuxSetupScript(){return["# Create handler script","mkdir -p ~/.local/bin","cat > ~/.local/bin/vlc-protocol << 'EOF'","#!/bin/bash","URL=\"$1\"","URL=\"${URL#vlc://}\"","URL=$(python3 -c \"import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))\" \"$URL\")","exec vlc \"$URL\" &","EOF","chmod +x ~/.local/bin/vlc-protocol","","# Create .desktop file","cat > ~/.local/share/applications/vlc-protocol.desktop << 'EOF'","[Desktop Entry]","Name=VLC Protocol Handler","Exec=bash -c '~/.local/bin/vlc-protocol %u'","Type=Application","NoDisplay=true","MimeType=x-scheme-handler/vlc;","EOF","","# Register the handler","xdg-mime default vlc-protocol.desktop x-scheme-handler/vlc","update-desktop-database ~/.local/share/applications/","","echo \"VLC protocol handler installed successfully.\""].join('\n');}_copyToClipboard(pText,pLabel){if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(pText).then(()=>{this.pict.providers['RetoldRemote-ToastNotification'].showToast(pLabel+' copied to clipboard');}).catch(()=>{this._fallbackCopy(pText,pLabel);});}else{this._fallbackCopy(pText,pLabel);}}_fallbackCopy(pText,pLabel){let tmpTextarea=document.createElement('textarea');tmpTextarea.value=pText;tmpTextarea.style.position='fixed';tmpTextarea.style.left='-9999px';document.body.appendChild(tmpTextarea);tmpTextarea.select();try{document.execCommand('copy');this.pict.providers['RetoldRemote-ToastNotification'].showToast(pLabel+' copied to clipboard');}catch(pErr){this.pict.providers['RetoldRemote-ToastNotification'].showToast('Failed to copy - please select and copy manually');}document.body.removeChild(tmpTextarea);}copyMacSetup(){this._copyToClipboard(this._getMacSetupScript(),'macOS setup script');}copyWindowsReg(){this._copyToClipboard(this._getWindowsRegFile(),'Registry file');}copyWindowsBatch(){this._copyToClipboard(this._getWindowsBatchScript(),'Batch script');}copyLinuxSetup(){this._copyToClipboard(this._getLinuxSetupScript(),'Linux setup script');}testProtocol(){let tmpIsWindows=/Windows/.test(navigator.userAgent);let tmpSampleURL='https://www.sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4';let tmpTestURL=tmpIsWindows?'vlc://'+tmpSampleURL:'vlc://'+encodeURIComponent(tmpSampleURL);let tmpLink=document.createElement('a');tmpLink.href=tmpTestURL;tmpLink.style.display='none';document.body.appendChild(tmpLink);tmpLink.click();document.body.removeChild(tmpLink);}}RetoldRemoteVLCSetupView.default_configuration=_ViewConfiguration;module.exports=RetoldRemoteVLCSetupView;},{"pict-view":76}],138:[function(require,module,exports){const libPictView=require('pict-view');const _ViewConfiguration={ViewIdentifier:"RetoldRemote-VideoExplorer",DefaultRenderable:"RetoldRemote-VideoExplorer",DefaultDestinationAddress:"#RetoldRemote-Viewer-Container",AutoRender:false,CSS:/*css*/`
13441
13809
  .retold-remote-vex
13442
13810
  {
13443
13811
  display: flex;