retold-content-system 1.0.12 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -68
- package/package.json +3 -3
- package/source/cli/ContentSystem-Server-Setup.js +7 -3
- package/web-application/js/pict.min.js +2 -2
- package/web-application/retold-content-system.compatible.js +50 -7
- package/web-application/retold-content-system.compatible.js.map +1 -1
- package/web-application/retold-content-system.compatible.min.js +5 -5
- package/web-application/retold-content-system.compatible.min.js.map +1 -1
- package/web-application/retold-content-system.js +49 -6
- package/web-application/retold-content-system.js.map +1 -1
- package/web-application/retold-content-system.min.js +1 -1
- package/web-application/retold-content-system.min.js.map +1 -1
|
@@ -2781,18 +2781,45 @@ var tmpCached=tmpBrowseProvider.getChildFolders(pPath);if(!tmpCached){if(typeof
|
|
|
2781
2781
|
* Get the current location from state.
|
|
2782
2782
|
*
|
|
2783
2783
|
* @returns {string} The current location path
|
|
2784
|
-
*/},{key:"getCurrentLocation",value:function getCurrentLocation(){var tmpStateAddresses=this.options.StateAddresses||{};var tmpAddress=tmpStateAddresses.CurrentLocation||'AppData.PictFileBrowser.CurrentLocation';return this.pict.manifest.getValueByHash({AppData:this.pict.AppData,Pict:this.pict},tmpAddress)||'';}}]);}(libPictView);module.exports=PictViewFileBrowserBrowseTree;module.exports.default_configuration=_ViewConfiguration;},{"pict-view":88}],72:[function(require,module,exports){var libPictView=require('pict-view')
|
|
2784
|
+
*/},{key:"getCurrentLocation",value:function getCurrentLocation(){var tmpStateAddresses=this.options.StateAddresses||{};var tmpAddress=tmpStateAddresses.CurrentLocation||'AppData.PictFileBrowser.CurrentLocation';return this.pict.manifest.getValueByHash({AppData:this.pict.AppData,Pict:this.pict},tmpAddress)||'';}}]);}(libPictView);module.exports=PictViewFileBrowserBrowseTree;module.exports.default_configuration=_ViewConfiguration;},{"pict-view":88}],72:[function(require,module,exports){var libPictView=require('pict-view');// Chunked rendering constants — for folders with very large file counts
|
|
2785
|
+
// we render rows in chunks via requestAnimationFrame so the main thread
|
|
2786
|
+
// stays responsive instead of freezing on one massive assignContent call.
|
|
2787
|
+
var _CHUNKED_RENDER_THRESHOLD=500;var _CHUNK_FIRST_SIZE=200;var _CHUNK_SUBSEQUENT_SIZE=400;var _ViewConfiguration={"ViewIdentifier":"Pict-FileBrowser-ListDetail","DefaultRenderable":"ListDetail-Container","DefaultDestinationAddress":"#Pict-FileBrowser-ListPane","AutoRender":false,"Templates":[{"Hash":"FileBrowser-ListDetail-Container-Template","Template":/*html*/"\n<div class=\"pict-fb-detail\" id=\"Pict-FileBrowser-DetailList\">\n\t<div class=\"pict-fb-breadcrumb\" id=\"Pict-FileBrowser-Breadcrumb\"></div>\n\t<div class=\"pict-fb-detail-header\">\n\t\t<div class=\"pict-fb-detail-header-cell pict-fb-detail-col-name\" onclick=\"pict.views['{~D:Record.ViewHash~}'].sortBy('Name')\">Name</div>\n\t\t<div class=\"pict-fb-detail-header-cell pict-fb-detail-col-size\" onclick=\"pict.views['{~D:Record.ViewHash~}'].sortBy('Size')\">Size</div>\n\t\t<div class=\"pict-fb-detail-header-cell pict-fb-detail-col-modified\" onclick=\"pict.views['{~D:Record.ViewHash~}'].sortBy('Modified')\">Modified</div>\n\t</div>\n\t<div id=\"Pict-FileBrowser-DetailRows\"></div>\n</div>\n"},{"Hash":"FileBrowser-ListDetail-Row-Template","Template":/*html*/"\n<div class=\"pict-fb-detail-row{~D:Record.SelectedClass~}\" data-index=\"{~D:Record.Index~}\" onclick=\"{~D:Record.ClickHandler~}\" ondblclick=\"{~D:Record.DblClickHandler~}\">\n\t<span class=\"pict-fb-detail-icon\">{~D:Record.Icon~}</span>\n\t<span class=\"pict-fb-detail-name\">{~D:Record.Name~}</span>\n\t<span class=\"pict-fb-detail-size\">{~D:Record.SizeFormatted~}</span>\n\t<span class=\"pict-fb-detail-modified\">{~D:Record.ModifiedFormatted~}</span>\n</div>\n"},{"Hash":"FileBrowser-ListDetail-Empty-Template","Template":/*html*/"<div class=\"pict-fb-empty\">{~D:Record.Message~}</div>"},{"Hash":"FileBrowser-Breadcrumb-Segment-Template","Template":/*html*/"<span class=\"pict-fb-breadcrumb-segment\" onclick=\"{~D:Record.ClickHandler~}\">{~D:Record.Label~}</span>"},{"Hash":"FileBrowser-Breadcrumb-Separator-Template","Template":/*html*/"<span class=\"pict-fb-breadcrumb-separator\">/</span>"},{"Hash":"FileBrowser-Breadcrumb-Current-Template","Template":/*html*/"<span class=\"pict-fb-breadcrumb-current\">{~D:Record.Label~}</span>"}],"Renderables":[{"RenderableHash":"ListDetail-Container","TemplateHash":"FileBrowser-ListDetail-Container-Template","DestinationAddress":"#Pict-FileBrowser-ListPane","RenderMethod":"replace"}]};/**
|
|
2785
2788
|
* Listing view that shows files in a detailed table with columns for
|
|
2786
2789
|
* name, size, and modified date.
|
|
2787
2790
|
*
|
|
2788
2791
|
* Supports sorting by column header click and single-click selection
|
|
2789
2792
|
* with double-click to open folders.
|
|
2790
|
-
*/var PictViewFileBrowserListDetail=/*#__PURE__*/function(_libPictView9){function PictViewFileBrowserListDetail(pFable,pOptions,pServiceHash){var _this44;_classCallCheck(this,PictViewFileBrowserListDetail);var tmpOptions=Object.assign({},_ViewConfiguration,pOptions);_this44=_callSuper(this,PictViewFileBrowserListDetail,[pFable,tmpOptions,pServiceHash]);_this44._cachedFileList=[]
|
|
2793
|
+
*/var PictViewFileBrowserListDetail=/*#__PURE__*/function(_libPictView9){function PictViewFileBrowserListDetail(pFable,pOptions,pServiceHash){var _this44;_classCallCheck(this,PictViewFileBrowserListDetail);var tmpOptions=Object.assign({},_ViewConfiguration,pOptions);_this44=_callSuper(this,PictViewFileBrowserListDetail,[pFable,tmpOptions,pServiceHash]);_this44._cachedFileList=[];// Chunked render state
|
|
2794
|
+
_this44._activeRebuildFrame=null;_this44._activeRebuildToken=0;return _this44;}/**
|
|
2795
|
+
* Cancel any in-flight chunked rebuild so it does not overlap with a
|
|
2796
|
+
* fresh navigation.
|
|
2797
|
+
*/_inherits(PictViewFileBrowserListDetail,_libPictView9);return _createClass(PictViewFileBrowserListDetail,[{key:"_cancelActiveRebuild",value:function _cancelActiveRebuild(){if(this._activeRebuildFrame!==null&&typeof cancelAnimationFrame==='function'){cancelAnimationFrame(this._activeRebuildFrame);this._activeRebuildFrame=null;}this._activeRebuildToken++;}/**
|
|
2791
2798
|
* After rendering the container shell, populate the rows.
|
|
2792
|
-
*/
|
|
2799
|
+
*/},{key:"onAfterRender",value:function onAfterRender(pRenderable){// Render the container with the view hash
|
|
2793
2800
|
var tmpContainerHTML=this.pict.parseTemplateByHash('FileBrowser-ListDetail-Container-Template',{ViewHash:this.Hash});this.pict.ContentAssignment.assignContent('#Pict-FileBrowser-ListPane',tmpContainerHTML);this.rebuildList();this.rebuildBreadcrumb();this.pict.CSSMap.injectCSS();return _superPropGet(PictViewFileBrowserListDetail,"onAfterRender",this,3)([pRenderable]);}/**
|
|
2794
2801
|
* Rebuild the file list rows.
|
|
2795
|
-
|
|
2802
|
+
*
|
|
2803
|
+
* For folders with more than _CHUNKED_RENDER_THRESHOLD items, the render
|
|
2804
|
+
* is split into chunks scheduled via requestAnimationFrame so the main
|
|
2805
|
+
* thread stays responsive. Smaller folders use the synchronous fast path.
|
|
2806
|
+
*/},{key:"rebuildList",value:function rebuildList(){// Cancel any in-flight chunked rebuild from a previous folder
|
|
2807
|
+
this._cancelActiveRebuild();var tmpListProvider=this.pict.providers['Pict-FileBrowser-List'];if(!tmpListProvider){return;}var tmpFileList=tmpListProvider.getSortedFileList();this._cachedFileList=tmpFileList;var tmpSelectedFile=tmpListProvider.getSelectedFile();if(tmpFileList.length===0){var tmpEmptyHTML=this.pict.parseTemplateByHash('FileBrowser-ListDetail-Empty-Template',{Message:'This folder is empty'});this.pict.ContentAssignment.assignContent('#Pict-FileBrowser-DetailRows',tmpEmptyHTML);return;}// SMALL FOLDER FAST PATH — keep the existing synchronous behavior
|
|
2808
|
+
// for normal-sized folders so there's no perceptible change.
|
|
2809
|
+
if(tmpFileList.length<=_CHUNKED_RENDER_THRESHOLD){var tmpHTML='';for(var i=0;i<tmpFileList.length;i++){tmpHTML+=this._buildRowHTML(tmpFileList[i],i,tmpSelectedFile);}this.pict.ContentAssignment.assignContent('#Pict-FileBrowser-DetailRows',tmpHTML);return;}// LARGE FOLDER CHUNKED PATH — paint a loading row immediately, then
|
|
2810
|
+
// fill rows in chunks via requestAnimationFrame.
|
|
2811
|
+
var tmpLoadingHTML='<div class="retold-remote-filebrowser-loading-row">'+'Loading '+tmpFileList.length.toLocaleString()+" items\u2026"+'</div>';this.pict.ContentAssignment.assignContent('#Pict-FileBrowser-DetailRows',tmpLoadingHTML);this._rebuildListChunked(tmpFileList,tmpSelectedFile);}/**
|
|
2812
|
+
* Build the HTML for a single row. Extracted so both the fast path
|
|
2813
|
+
* and the chunked path can share it.
|
|
2814
|
+
*/},{key:"_buildRowHTML",value:function _buildRowHTML(pEntry,pIndex,pSelectedFile){var tmpListProvider=this.pict.providers['Pict-FileBrowser-List'];var tmpIsSelected=pSelectedFile&&pSelectedFile.Name===pEntry.Name&&pSelectedFile.Path===pEntry.Path;var tmpRecord={Index:pIndex,Name:pEntry.Name,Icon:tmpListProvider.getEntryIcon(pEntry),SizeFormatted:pEntry.Type==='folder'?'--':tmpListProvider.formatFileSize(pEntry.Size),ModifiedFormatted:tmpListProvider.formatDate(pEntry.Modified),SelectedClass:tmpIsSelected?' selected':'',ClickHandler:"pict.views['"+this.Hash+"'].selectEntry("+pIndex+")",DblClickHandler:"pict.views['"+this.Hash+"'].openEntry("+pIndex+")"};return this.pict.parseTemplateByHash('FileBrowser-ListDetail-Row-Template',tmpRecord);}/**
|
|
2815
|
+
* Render the file list into chunks via requestAnimationFrame.
|
|
2816
|
+
* After the first chunk replaces the loading row, each subsequent
|
|
2817
|
+
* chunk is appended to the rows container.
|
|
2818
|
+
*/},{key:"_rebuildListChunked",value:function _rebuildListChunked(pFileList,pSelectedFile){var tmpSelf=this;var tmpToken=++this._activeRebuildToken;var tmpTotal=pFileList.length;var tmpOffset=0;var _renderNextChunk2=function _renderNextChunk(){if(tmpToken!==tmpSelf._activeRebuildToken){return;}var tmpRowsContainer=document.getElementById('Pict-FileBrowser-DetailRows');if(!tmpRowsContainer){return;}var tmpChunkSize=tmpOffset===0?_CHUNK_FIRST_SIZE:_CHUNK_SUBSEQUENT_SIZE;var tmpEnd=Math.min(tmpOffset+tmpChunkSize,tmpTotal);var tmpChunkHTML='';for(var i=tmpOffset;i<tmpEnd;i++){tmpChunkHTML+=tmpSelf._buildRowHTML(pFileList[i],i,pSelectedFile);}if(tmpOffset===0){// Replace the loading row on the first chunk
|
|
2819
|
+
tmpRowsContainer.innerHTML=tmpChunkHTML;}else{// Append subsequent chunks
|
|
2820
|
+
tmpRowsContainer.insertAdjacentHTML('beforeend',tmpChunkHTML);}tmpOffset=tmpEnd;if(tmpOffset<tmpTotal){tmpSelf._activeRebuildFrame=requestAnimationFrame(_renderNextChunk2);}else{tmpSelf._activeRebuildFrame=null;}};if(typeof requestAnimationFrame==='function'){this._activeRebuildFrame=requestAnimationFrame(_renderNextChunk2);}else{// No rAF (shouldn't happen in a browser, but be safe) — fall back
|
|
2821
|
+
// to synchronous render
|
|
2822
|
+
_renderNextChunk2();while(tmpOffset<tmpTotal){_renderNextChunk2();}}}/**
|
|
2796
2823
|
* Rebuild the breadcrumb navigation bar.
|
|
2797
2824
|
*/},{key:"rebuildBreadcrumb",value:function rebuildBreadcrumb(){var tmpCurrentLocation=this.getCurrentLocation();var tmpHTML='';// Root segment — use SVG home icon if provider is available
|
|
2798
2825
|
var tmpIconProvider=this.pict.providers['Pict-FileBrowser-Icons'];var tmpHomeLabel=tmpIconProvider?tmpIconProvider.getIcon('home',16):"\uD83C\uDFE0";tmpHTML+=this.pict.parseTemplateByHash('FileBrowser-Breadcrumb-Segment-Template',{Label:tmpHomeLabel,ClickHandler:"pict.views['"+this.Hash+"'].navigateToPath('')"});if(tmpCurrentLocation){var tmpParts=tmpCurrentLocation.split('/');var tmpAccumulatedPath='';for(var i=0;i<tmpParts.length;i++){tmpAccumulatedPath=tmpAccumulatedPath?tmpAccumulatedPath+'/'+tmpParts[i]:tmpParts[i];tmpHTML+=this.pict.parseTemplateByHash('FileBrowser-Breadcrumb-Separator-Template',{});if(i===tmpParts.length-1){// Last segment — not clickable
|
|
@@ -3770,14 +3797,30 @@ this.pict.ContentAssignment.projectContent(pRenderable.RenderMethod,pRenderable.
|
|
|
3770
3797
|
*
|
|
3771
3798
|
* @param {Renderable} pRenderable - The renderable that was rendered.
|
|
3772
3799
|
*/},{key:"onAfterRender",value:function onAfterRender(pRenderable){if(this.pict.LogNoisiness>3){this.log.trace("PictView [".concat(this.UUID,"]::[").concat(this.Hash,"] ").concat(this.options.ViewIdentifier," onAfterRender:"));}if(pRenderable&&pRenderable.RootRenderableViewHash===this.Hash){var tmpTransactionQueue=this.pict.TransactionTracking.clearTransactionQueue(pRenderable.TransactionHash)||[];var _iterator2=_createForOfIteratorHelper(tmpTransactionQueue),_step2;try{for(_iterator2.s();!(_step2=_iterator2.n()).done;){var tmpEvent=_step2.value;var tmpView=this.pict.views[tmpEvent.Data.ViewHash];if(!tmpView){this.log.error("PictView [".concat(this.UUID,"]::[").concat(this.Hash,"] ").concat(this.options.ViewIdentifier," onAfterRender: Could not find view for transaction hash ").concat(pRenderable.TransactionHash," and ViewHash ").concat(tmpEvent.Data.ViewHash,"."));continue;}tmpView.onAfterProject();// Execute the developer-overridable post-render behavior
|
|
3773
|
-
tmpView.onAfterRender(tmpEvent.Data.Renderable);}
|
|
3800
|
+
tmpView.onAfterRender(tmpEvent.Data.Renderable);}// Queue is drained and nested child renders have each cleaned up
|
|
3801
|
+
// their own transactions; remove this root render's entry from
|
|
3802
|
+
// the tracking map so it does not leak.
|
|
3803
|
+
}catch(err){_iterator2.e(err);}finally{_iterator2.f();}this.pict.TransactionTracking.unregisterTransaction(pRenderable.TransactionHash);}return true;}/**
|
|
3774
3804
|
* Lifecycle hook that triggers after the view is rendered (async flow).
|
|
3775
3805
|
*
|
|
3776
3806
|
* @param {ErrorCallback} fCallback - The callback to call when the async operation is complete.
|
|
3777
3807
|
* @param {Renderable} pRenderable - The renderable that was rendered.
|
|
3778
|
-
*/},{key:"onAfterRenderAsync",value:function onAfterRenderAsync(fCallback,pRenderable){var _this53=this
|
|
3808
|
+
*/},{key:"onAfterRenderAsync",value:function onAfterRenderAsync(fCallback,pRenderable){var _this53=this;// NOTE: this.onAfterRender(pRenderable) will itself clear the
|
|
3809
|
+
// transaction queue and unregister the transaction if this view is
|
|
3810
|
+
// the root renderable - see onAfterRender above. So by the time the
|
|
3811
|
+
// loop below runs, the queue is already empty and there is nothing
|
|
3812
|
+
// to drain. Keeping the async queue walk here defensively in case
|
|
3813
|
+
// future subclasses override onAfterRender in ways that skip the
|
|
3814
|
+
// drain, but the common path is now "sync drain, async no-op".
|
|
3815
|
+
this.onAfterRender(pRenderable);var tmpAnticipate=this.fable.newAnticipate();var tmpIsRootRenderable=pRenderable&&pRenderable.RootRenderableViewHash===this.Hash;if(tmpIsRootRenderable){var queue=this.pict.TransactionTracking.clearTransactionQueue(pRenderable.TransactionHash)||[];var _iterator3=_createForOfIteratorHelper(queue),_step3;try{var _loop2=function _loop2(){var event=_step3.value;/** @type {PictView} */var tmpView=_this53.pict.views[event.Data.ViewHash];if(!tmpView){_this53.log.error("PictView [".concat(_this53.UUID,"]::[").concat(_this53.Hash,"] ").concat(_this53.options.ViewIdentifier," onAfterRenderAsync: Could not find view for transaction hash ").concat(pRenderable.TransactionHash," and ViewHash ").concat(event.Data.ViewHash,"."));return 1;// continue
|
|
3779
3816
|
}tmpAnticipate.anticipate(tmpView.onAfterProjectAsync.bind(tmpView));tmpAnticipate.anticipate(function(fNext){tmpView.onAfterRenderAsync(fNext,event.Data.Renderable);});// Execute the developer-overridable post-render behavior
|
|
3780
|
-
};for(_iterator3.s();!(_step3=_iterator3.n()).done;){if(_loop2())continue;}}catch(err){_iterator3.e(err);}finally{_iterator3.f();}}return tmpAnticipate.wait(
|
|
3817
|
+
};for(_iterator3.s();!(_step3=_iterator3.n()).done;){if(_loop2())continue;}}catch(err){_iterator3.e(err);}finally{_iterator3.f();}}return tmpAnticipate.wait(function(pError){// Nested virtual-assignment children have now settled their own
|
|
3818
|
+
// onAfterRenderAsync chains (and unregistered their own
|
|
3819
|
+
// transactions along the way). Ensure this root render's entry
|
|
3820
|
+
// is also gone - unregisterTransaction is a no-op if the sync
|
|
3821
|
+
// onAfterRender above already removed it, so this is safe to
|
|
3822
|
+
// call unconditionally on the root path.
|
|
3823
|
+
if(tmpIsRootRenderable&&pRenderable&&pRenderable.TransactionHash){_this53.pict.TransactionTracking.unregisterTransaction(pRenderable.TransactionHash);}return fCallback(pError);});}/**
|
|
3781
3824
|
* Lifecycle hook that triggers after the view is projected into the DOM.
|
|
3782
3825
|
*
|
|
3783
3826
|
* @param {Renderable} pRenderable - The renderable that was projected.
|