flea-qml 0.0.0-stage → 0.2.0
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/LICENSE +22 -0
- package/README.md +511 -2
- package/THIRD-PARTY-NOTICES.md +29 -0
- package/demos/App.java +5 -0
- package/demos/Dockerfile +4 -0
- package/demos/Main.kt +3 -0
- package/demos/Program.cs +1 -0
- package/demos/README.md +12 -0
- package/demos/app.dart +3 -0
- package/demos/app.deb +0 -0
- package/demos/app.js +1 -0
- package/demos/backup.tar +0 -0
- package/demos/budget.xlsx +0 -0
- package/demos/build.sh +2 -0
- package/demos/bundle.zip +0 -0
- package/demos/clip.mp4 +0 -0
- package/demos/data.sqlite +0 -0
- package/demos/disk.iso +0 -0
- package/demos/engine.cpp +5 -0
- package/demos/firmware.bin +0 -0
- package/demos/flake.nix +4 -0
- package/demos/folder/inside.txt +1 -0
- package/demos/font.ttf +0 -0
- package/demos/index.html +5 -0
- package/demos/index.php +2 -0
- package/demos/init.lua +1 -0
- package/demos/letter.docx +0 -0
- package/demos/lib.rs +3 -0
- package/demos/main.c +6 -0
- package/demos/main.h +3 -0
- package/demos/math-and-diagrams.md +200 -0
- package/demos/notes.tar.gz +0 -0
- package/demos/notes.txt +3 -0
- package/demos/photo.png +0 -0
- package/demos/program +2 -0
- package/demos/report.pdf +32 -0
- package/demos/script.py +1 -0
- package/demos/server.go +7 -0
- package/demos/settings.json +4 -0
- package/demos/slides.pptx +0 -0
- package/demos/song.mp3 +0 -0
- package/demos/style.css +4 -0
- package/demos/tool.rb +1 -0
- package/demos/types.ts +2 -0
- package/docs/pele.md +23 -0
- package/docs/protocol.md +3420 -0
- package/docs/temml.md +63 -0
- package/index.js +107 -0
- package/package.json +34 -4
- package/src/archive.js +407 -0
- package/src/archiveops.js +728 -0
- package/src/backend.js +369 -0
- package/src/bulkrename.js +95 -0
- package/src/clip-host.js +76 -0
- package/src/clip.js +462 -0
- package/src/code.js +168 -0
- package/src/compare.js +74 -0
- package/src/create.js +128 -0
- package/src/dirsize.js +147 -0
- package/src/figure-svg.js +530 -0
- package/src/figure-thread.js +23 -0
- package/src/figure.js +132 -0
- package/src/find.js +55 -0
- package/src/flea.js +39 -0
- package/src/fsinfo.js +39 -0
- package/src/highlight.js +141 -0
- package/src/html.js +52 -0
- package/src/kinds.js +89 -0
- package/src/listing.js +130 -0
- package/src/markdown-html.js +317 -0
- package/src/mathml.js +186 -0
- package/src/menu.js +180 -0
- package/src/meta.js +135 -0
- package/src/office.js +810 -0
- package/src/order.js +100 -0
- package/src/peek.js +49 -0
- package/src/pele-wrapper.js +695 -0
- package/src/permissions.js +180 -0
- package/src/places.js +313 -0
- package/src/preview-language.js +10 -0
- package/src/terminal-server.js +95 -0
- package/src/terminal-shell.js +26 -0
- package/src/transfer.js +669 -0
- package/src/trash-record.js +41 -0
- package/src/trash.js +210 -0
- package/src/trashbrowse.js +327 -0
- package/src/uistate.js +393 -0
- package/src/uistore.js +168 -0
- package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
- package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
- package/src/vendor/LICENSES/MIT-katex.txt +21 -0
- package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
- package/src/vendor/LICENSES/MIT-pele.txt +40 -0
- package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
- package/src/vendor/LICENSES/MIT-temml.txt +21 -0
- package/src/vendor/pele.js +145 -0
- package/src/vendor/temml.mjs +14708 -0
- package/src/watch.js +98 -0
- package/src/wayland/client.js +109 -0
- package/src/wayland/protocol.js +55 -0
- package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
- package/src/wayland/protocols/wayland.xml +3248 -0
- package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
- package/src/wayland/resource-io.js +6 -0
- package/src/wayland/socket-discovery.js +26 -0
- package/src/wayland/transport-posix.js +120 -0
- package/src/wayland/transport-win32.js +11 -0
- package/src/wayland/transport.js +3 -0
- package/src/wayland/win32-resources.js +80 -0
- package/src/wayland/win32-wire.js +62 -0
- package/test/archive.test.js +80 -0
- package/test/bench-markdown-scroll.mjs +190 -0
- package/test/clip-host.test.js +113 -0
- package/test/code-preview.test.js +35 -0
- package/test/compare-ui-paths.test.js +24 -0
- package/test/compare.test.js +54 -0
- package/test/delete-trash.test.js +67 -0
- package/test/dirsize.test.js +138 -0
- package/test/file-ops.test.js +307 -0
- package/test/file-url.test.js +24 -0
- package/test/find-contents.test.js +161 -0
- package/test/find-input.test.js +66 -0
- package/test/fixtures/pele-parity.json +1006 -0
- package/test/highlight-launcher.test.js +35 -0
- package/test/html-preview.test.js +22 -0
- package/test/input.test.js +15 -0
- package/test/keymap.test.js +26 -0
- package/test/language-icons.test.js +36 -0
- package/test/launcher.test.js +51 -0
- package/test/manual-archive-here-ui.mjs +47 -0
- package/test/manual-code-scroll.mjs +28 -0
- package/test/manual-column-scroll.mjs +24 -0
- package/test/manual-compare-ui.mjs +20 -0
- package/test/manual-find-status.mjs +37 -0
- package/test/manual-folder-focus.mjs +63 -0
- package/test/manual-html-security.mjs +23 -0
- package/test/manual-html-ui.mjs +30 -0
- package/test/manual-syntax-preview.mjs +26 -0
- package/test/manual-terminal-lifecycle.mjs +42 -0
- package/test/manual-terminal-navigation.mjs +48 -0
- package/test/manual-terminal-ui.mjs +47 -0
- package/test/manual-trash-ui.mjs +86 -0
- package/test/markdown-diagrams.test.js +93 -0
- package/test/markdown-html.test.js +105 -0
- package/test/mathml.test.js +92 -0
- package/test/menu-transfer.test.js +57 -0
- package/test/office-preview.test.js +154 -0
- package/test/pele-parity.test.js +28 -0
- package/test/places.test.js +134 -0
- package/test/preview-keys.test.js +60 -0
- package/test/preview-language.test.js +22 -0
- package/test/status-filename.test.js +20 -0
- package/test/transfer-replace-merge.test.js +187 -0
- package/test/trash-address.test.js +23 -0
- package/test/trash-view.test.js +37 -0
- package/test/trashbrowse.test.js +135 -0
- package/ui/AboutFacts.qml +78 -0
- package/ui/ArchiveCards.qml +95 -0
- package/ui/ArchiveCompressDialog.qml +378 -0
- package/ui/ArchiveHereConfirm.qml +127 -0
- package/ui/ArchivePasswordDialog.qml +257 -0
- package/ui/Backend.qml +775 -0
- package/ui/BulkOldNames.qml +47 -0
- package/ui/BulkRenameDialog.qml +380 -0
- package/ui/CardFrame.qml +67 -0
- package/ui/CardScroll.qml +79 -0
- package/ui/CheckBox.qml +73 -0
- package/ui/ChromeBar.qml +360 -0
- package/ui/ChromeButton.qml +131 -0
- package/ui/ChromeModes.qml +43 -0
- package/ui/CodeLines.qml +256 -0
- package/ui/CodeRefusal.qml +52 -0
- package/ui/CollideConfirm.qml +147 -0
- package/ui/CollideHost.qml +167 -0
- package/ui/ColumnPane.qml +525 -0
- package/ui/ColumnRow.qml +380 -0
- package/ui/ColumnsArea.qml +594 -0
- package/ui/ColumnsLanding.qml +147 -0
- package/ui/CompareView.qml +321 -0
- package/ui/ContextMenu.qml +743 -0
- package/ui/ConvertDialog.qml +456 -0
- package/ui/CountedWorker.qml +7 -0
- package/ui/Crumb.qml +64 -0
- package/ui/CrumbDrop.qml +25 -0
- package/ui/CsvTable.qml +394 -0
- package/ui/CursorMark.qml +41 -0
- package/ui/DefaultClaim.qml +130 -0
- package/ui/DeviceLock.qml +47 -0
- package/ui/DeviceMounts.qml +540 -0
- package/ui/DialogButton.qml +150 -0
- package/ui/DialogField.qml +147 -0
- package/ui/DialogHeader.qml +31 -0
- package/ui/DialogScrim.qml +20 -0
- package/ui/DialogTitle.qml +37 -0
- package/ui/Divider.qml +9 -0
- package/ui/DropInto.qml +126 -0
- package/ui/DropTarget.qml +35 -0
- package/ui/DropboxMark.qml +60 -0
- package/ui/EmptyState.qml +150 -0
- package/ui/EscapeHint.qml +11 -0
- package/ui/FactsTable.qml +54 -0
- package/ui/FastScrollHandler.qml +476 -0
- package/ui/FatNamesConfirm.qml +157 -0
- package/ui/Favourites.qml +143 -0
- package/ui/FigureService.qml +120 -0
- package/ui/FileDrag.qml +267 -0
- package/ui/FilterStrip.qml +133 -0
- package/ui/FitMetrics.qml +22 -0
- package/ui/FlashDriveRows.qml +137 -0
- package/ui/FlashHost.qml +72 -0
- package/ui/FlashImageRow.qml +104 -0
- package/ui/FlashRunner.qml +119 -0
- package/ui/FlashStepRow.qml +172 -0
- package/ui/FlashStrip.qml +38 -0
- package/ui/FlashView.qml +397 -0
- package/ui/FleaMark.qml +88 -0
- package/ui/FlyoutFade.qml +23 -0
- package/ui/FontPane.qml +170 -0
- package/ui/Glass.qml +114 -0
- package/ui/GlassTagger.qml +59 -0
- package/ui/Glyph.qml +64 -0
- package/ui/GlyphSolid.qml +22 -0
- package/ui/GridArea.qml +664 -0
- package/ui/GridTile.qml +325 -0
- package/ui/GvfsBridge.qml +164 -0
- package/ui/Header.qml +433 -0
- package/ui/HoverTimers.qml +39 -0
- package/ui/HtmlClip.qml +30 -0
- package/ui/HtmlPane.qml +63 -0
- package/ui/HyprlandMark.qml +45 -0
- package/ui/Ipc.qml +1005 -0
- package/ui/IpcControls.qml +7 -0
- package/ui/IpcMenuState.qml +48 -0
- package/ui/IpcPreviewState.qml +185 -0
- package/ui/JumpPath.qml +51 -0
- package/ui/KeymapSheet.qml +561 -0
- package/ui/KeymapSheetResult.qml +89 -0
- package/ui/KindStack.qml +40 -0
- package/ui/LangMark.qml +51 -0
- package/ui/LangMarkLoader.qml +26 -0
- package/ui/List.qml +480 -0
- package/ui/LoadingState.qml +54 -0
- package/ui/LocalSend.qml +56 -0
- package/ui/LocalSendMark.qml +73 -0
- package/ui/MarkdownBlockView.qml +311 -0
- package/ui/MarkdownBlocks.qml +35 -0
- package/ui/MarkdownFigure.qml +254 -0
- package/ui/MarkdownImages.qml +72 -0
- package/ui/MarkdownList.qml +81 -0
- package/ui/MarkdownMathsText.qml +97 -0
- package/ui/MarkdownPane.qml +83 -0
- package/ui/MarkdownPictures.qml +41 -0
- package/ui/MarkdownQuote.qml +52 -0
- package/ui/MarkdownRemote.qml +82 -0
- package/ui/MarkdownSource.qml +155 -0
- package/ui/MarkdownTable.qml +222 -0
- package/ui/MarkdownTableScroll.qml +64 -0
- package/ui/MarkdownTableWheel.qml +126 -0
- package/ui/MarkdownText.qml +87 -0
- package/ui/MarkdownWorker.js +132 -0
- package/ui/MatchText.qml +99 -0
- package/ui/MediaSession.qml +38 -0
- package/ui/MediaSound.qml +26 -0
- package/ui/MediaStrip.qml +191 -0
- package/ui/MediaTrack.qml +36 -0
- package/ui/MediaVolume.qml +54 -0
- package/ui/MenuActionDialog.qml +396 -0
- package/ui/MenuEdgeFade.qml +24 -0
- package/ui/MenuHost.qml +227 -0
- package/ui/MenuRow.qml +351 -0
- package/ui/MountListing.qml +100 -0
- package/ui/NetworkDialog.qml +435 -0
- package/ui/NetworkForm.qml +426 -0
- package/ui/NetworkMounts.qml +913 -0
- package/ui/NetworkPlaces.qml +127 -0
- package/ui/OpenWithDialog.qml +613 -0
- package/ui/Opener.qml +95 -0
- package/ui/Pane.qml +1320 -0
- package/ui/PaneMenuActions.qml +527 -0
- package/ui/PanePath.qml +90 -0
- package/ui/PaneRail.qml +268 -0
- package/ui/PaneStates.qml +88 -0
- package/ui/PaneSwap.qml +339 -0
- package/ui/PaneWire.qml +601 -0
- package/ui/ParkedWait.qml +9 -0
- package/ui/PathEntry.qml +186 -0
- package/ui/PathJump.qml +400 -0
- package/ui/PdfViewer.qml +297 -0
- package/ui/PermissionsDialog.qml +658 -0
- package/ui/PermissionsHeadings.qml +31 -0
- package/ui/PhoneMounts.qml +67 -0
- package/ui/PickerAnswers.qml +75 -0
- package/ui/PickerBox.qml +26 -0
- package/ui/PickerChrome.qml +295 -0
- package/ui/PickerFilter.qml +97 -0
- package/ui/PickerGrid.qml +308 -0
- package/ui/PickerHeader.qml +28 -0
- package/ui/PickerLifecycle.qml +27 -0
- package/ui/PickerList.qml +218 -0
- package/ui/PickerListing.qml +149 -0
- package/ui/PickerPathBar.qml +127 -0
- package/ui/PickerPlaces.qml +189 -0
- package/ui/PickerRecent.qml +92 -0
- package/ui/PickerSave.qml +101 -0
- package/ui/PickerSelection.qml +155 -0
- package/ui/PickerWindow.qml +846 -0
- package/ui/PowerSectorsReader.qml +10 -0
- package/ui/PrebuildDriver.qml +146 -0
- package/ui/Preview.qml +1005 -0
- package/ui/PreviewAnimation.qml +24 -0
- package/ui/PreviewArchive.qml +91 -0
- package/ui/PreviewColumn.qml +553 -0
- package/ui/PreviewEdge.qml +63 -0
- package/ui/PreviewFacts.qml +30 -0
- package/ui/PreviewFactsLine.qml +34 -0
- package/ui/PreviewHtml.qml +233 -0
- package/ui/PreviewImage.qml +253 -0
- package/ui/PreviewImagePan.qml +13 -0
- package/ui/PreviewImageSharp.qml +32 -0
- package/ui/PreviewLines.qml +106 -0
- package/ui/PreviewMarkdown.qml +706 -0
- package/ui/PreviewMedia.qml +250 -0
- package/ui/PreviewPdf.qml +482 -0
- package/ui/PreviewScroll.qml +201 -0
- package/ui/PreviewSwap.qml +335 -0
- package/ui/PreviewText.qml +149 -0
- package/ui/ProtocolChip.qml +18 -0
- package/ui/QuickLookArchive.qml +41 -0
- package/ui/QuickLookBar.qml +103 -0
- package/ui/QuickLookPrepare.qml +355 -0
- package/ui/QuickLookSwap.qml +10 -0
- package/ui/QuickLookWarm.qml +65 -0
- package/ui/RailDrop.qml +155 -0
- package/ui/RailHeading.qml +19 -0
- package/ui/RailPlaces.qml +38 -0
- package/ui/RailTrashRow.qml +67 -0
- package/ui/RenameField.qml +353 -0
- package/ui/RendererRetry.qml +11 -0
- package/ui/ResizeHandle.qml +52 -0
- package/ui/Reveal.qml +54 -0
- package/ui/Row.qml +476 -0
- package/ui/RowDrag.qml +213 -0
- package/ui/RowDropTarget.qml +27 -0
- package/ui/RunCard.qml +286 -0
- package/ui/Scripts.qml +65 -0
- package/ui/SearchStrip.qml +232 -0
- package/ui/SelectionBand.qml +140 -0
- package/ui/SelectionPreview.qml +370 -0
- package/ui/SettingsFavourite.qml +122 -0
- package/ui/SettingsGroup.qml +96 -0
- package/ui/SettingsHint.qml +12 -0
- package/ui/SettingsMetrics.qml +29 -0
- package/ui/SettingsPane.qml +178 -0
- package/ui/SettingsPanel.qml +547 -0
- package/ui/SettingsRail.qml +128 -0
- package/ui/SettingsRow.qml +409 -0
- package/ui/SettingsRuler.qml +85 -0
- package/ui/SettingsSegment.qml +85 -0
- package/ui/ShareBrowser.qml +113 -0
- package/ui/ShareLink.qml +67 -0
- package/ui/ShelfPins.qml +101 -0
- package/ui/Sidebar.qml +728 -0
- package/ui/SidebarRow.qml +358 -0
- package/ui/Spinner.qml +60 -0
- package/ui/StableModel.qml +89 -0
- package/ui/StateMessage.qml +84 -0
- package/ui/StatusBar.qml +512 -0
- package/ui/StatusFileName.qml +27 -0
- package/ui/TabBar.qml +673 -0
- package/ui/TabDragGeometry.qml +60 -0
- package/ui/TagMenuMark.qml +52 -0
- package/ui/TagRailSection.qml +53 -0
- package/ui/TagSlot.qml +40 -0
- package/ui/TagState.qml +150 -0
- package/ui/TagSwatch.qml +28 -0
- package/ui/Taildrop.qml +86 -0
- package/ui/TailscaleMark.qml +50 -0
- package/ui/TerminalService.qml +69 -0
- package/ui/TerminalTab.qml +48 -0
- package/ui/TerminalTabs.qml +27 -0
- package/ui/Theme.qml +460 -0
- package/ui/ThemeColors.qml +43 -0
- package/ui/TransferCard.qml +239 -0
- package/ui/TrashConfirm.qml +129 -0
- package/ui/TrashDropHandler.qml +11 -0
- package/ui/TrashHost.qml +202 -0
- package/ui/TrashMonitor.qml +30 -0
- package/ui/TrashToolbar.qml +19 -0
- package/ui/TrashView.qml +492 -0
- package/ui/UnlockDialog.qml +450 -0
- package/ui/UnlockHost.qml +206 -0
- package/ui/UpdateCheck.qml +97 -0
- package/ui/UserDirs.qml +25 -0
- package/ui/ViewState.qml +565 -0
- package/ui/ViewportScrollBar.qml +195 -0
- package/ui/ViewportScrollBars.qml +25 -0
- package/ui/WebPreview.qml +33 -0
- package/ui/WebPreviewView.qml +26 -0
- package/ui/WindowBody.qml +829 -0
- package/ui/WindowDrag.qml +35 -0
- package/ui/boot/Commons/AudioNodes.qml +50 -0
- package/ui/boot/Commons/AudioNodesModel.js +96 -0
- package/ui/boot/Commons/Border.qml +243 -0
- package/ui/boot/Commons/BorderGeometry.js +373 -0
- package/ui/boot/Commons/Color.qml +258 -0
- package/ui/boot/Commons/I18n.qml +118 -0
- package/ui/boot/Commons/InputDevices.qml +112 -0
- package/ui/boot/Commons/InputMethodState.qml +38 -0
- package/ui/boot/Commons/IpcRegistry.qml +77 -0
- package/ui/boot/Commons/Numbers.js +19 -0
- package/ui/boot/Commons/Plural.js +91 -0
- package/ui/boot/Commons/ShellIpc.qml +12 -0
- package/ui/boot/Commons/Style.qml +561 -0
- package/ui/boot/Commons/Translations.qml +100 -0
- package/ui/boot/Commons/UntypedInput.qml +152 -0
- package/ui/boot/Commons/Util.qml +188 -0
- package/ui/boot/Commons/qmldir +13 -0
- package/ui/boot/LICENSE-omarchy +20 -0
- package/ui/boot/Ui/BackgroundMedia.qml +49 -0
- package/ui/boot/Ui/BarIconButton.qml +106 -0
- package/ui/boot/Ui/BarIconContent.qml +38 -0
- package/ui/boot/Ui/BarIndicator.qml +53 -0
- package/ui/boot/Ui/BarWidget.qml +50 -0
- package/ui/boot/Ui/BorderOverlay.qml +54 -0
- package/ui/boot/Ui/BorderSurface.qml +40 -0
- package/ui/boot/Ui/Button.qml +224 -0
- package/ui/boot/Ui/ButtonGroup.qml +131 -0
- package/ui/boot/Ui/ConfirmDialog.qml +134 -0
- package/ui/boot/Ui/CursorSurface.qml +42 -0
- package/ui/boot/Ui/Dropdown.qml +245 -0
- package/ui/boot/Ui/FilterInput.qml +26 -0
- package/ui/boot/Ui/IconContentBounds.qml +141 -0
- package/ui/boot/Ui/KeyboardPanel.qml +453 -0
- package/ui/boot/Ui/MultiSelect.qml +624 -0
- package/ui/boot/Ui/NumberField.qml +86 -0
- package/ui/boot/Ui/OpticalGlyph.qml +68 -0
- package/ui/boot/Ui/OverlayWindow.qml +102 -0
- package/ui/boot/Ui/Panel.qml +60 -0
- package/ui/boot/Ui/PanelActionButton.qml +105 -0
- package/ui/boot/Ui/PanelController.qml +16 -0
- package/ui/boot/Ui/PanelHero.qml +112 -0
- package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
- package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
- package/ui/boot/Ui/PanelSeparator.qml +19 -0
- package/ui/boot/Ui/PanelSlider.qml +156 -0
- package/ui/boot/Ui/PanelToolTip.qml +50 -0
- package/ui/boot/Ui/PluginBarApi.qml +89 -0
- package/ui/boot/Ui/PointerMoveGate.qml +54 -0
- package/ui/boot/Ui/PopupCard.qml +181 -0
- package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
- package/ui/boot/Ui/SearchableDropdown.qml +354 -0
- package/ui/boot/Ui/SizedImage.qml +125 -0
- package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
- package/ui/boot/Ui/TextField.qml +58 -0
- package/ui/boot/Ui/Toggle.qml +118 -0
- package/ui/boot/Ui/ToggleSwitch.qml +115 -0
- package/ui/boot/Ui/WidgetButton.qml +172 -0
- package/ui/boot/Ui/qmldir +41 -0
- package/ui/boot/fleatab.qml +50 -0
- package/ui/boot/picker.qml +39 -0
- package/ui/boot/shell.qml +131 -0
- package/ui/boot/tabtearoff.qml +51 -0
- package/ui/js/Anchor.js +379 -0
- package/ui/js/AnchorHold.js +162 -0
- package/ui/js/Archive.js +157 -0
- package/ui/js/ArchiveCard.js +44 -0
- package/ui/js/ArchiveOps.js +44 -0
- package/ui/js/BackReturn.js +118 -0
- package/ui/js/BulkRename.js +100 -0
- package/ui/js/Buttons.js +54 -0
- package/ui/js/ChromeKeys.js +116 -0
- package/ui/js/ClipMarks.js +73 -0
- package/ui/js/ClipSelection.js +67 -0
- package/ui/js/Clipboard.js +179 -0
- package/ui/js/Cloud.js +97 -0
- package/ui/js/CodeRuns.js +72 -0
- package/ui/js/Collide.js +212 -0
- package/ui/js/ColumnFit.js +28 -0
- package/ui/js/ColumnMenu.js +111 -0
- package/ui/js/Columns.js +298 -0
- package/ui/js/ColumnsCarry.js +103 -0
- package/ui/js/Compare.js +74 -0
- package/ui/js/Contrast.js +157 -0
- package/ui/js/ControlReader.js +42 -0
- package/ui/js/Convert.js +52 -0
- package/ui/js/CopyAs.js +52 -0
- package/ui/js/Crumbs.js +178 -0
- package/ui/js/Csv.js +231 -0
- package/ui/js/Density.js +44 -0
- package/ui/js/Devices.js +440 -0
- package/ui/js/DirSizes.js +180 -0
- package/ui/js/Drag.js +360 -0
- package/ui/js/DragOut.js +166 -0
- package/ui/js/DropDev.js +52 -0
- package/ui/js/Dropbox.js +41 -0
- package/ui/js/Eject.js +217 -0
- package/ui/js/Errors.js +188 -0
- package/ui/js/ExtThumbs.js +115 -0
- package/ui/js/Facts.js +402 -0
- package/ui/js/FigureDate.js +14 -0
- package/ui/js/Filter.js +285 -0
- package/ui/js/Find.js +46 -0
- package/ui/js/Flash.js +184 -0
- package/ui/js/FlashCard.js +79 -0
- package/ui/js/FlashEndings.js +125 -0
- package/ui/js/FlashPane.js +116 -0
- package/ui/js/FleaBin.js +12 -0
- package/ui/js/Focus.js +504 -0
- package/ui/js/FolderSorts.js +108 -0
- package/ui/js/FolderViews.js +44 -0
- package/ui/js/Format.js +314 -0
- package/ui/js/Fuzzy.js +141 -0
- package/ui/js/GlassTag.js +72 -0
- package/ui/js/Grid.js +33 -0
- package/ui/js/GridGeometry.js +90 -0
- package/ui/js/GridNames.js +153 -0
- package/ui/js/GvfsBridge.js +200 -0
- package/ui/js/HostClipboard.js +29 -0
- package/ui/js/Icons.js +218 -0
- package/ui/js/Input.js +50 -0
- package/ui/js/Jump.js +200 -0
- package/ui/js/KeyName.js +64 -0
- package/ui/js/Keymap.js +401 -0
- package/ui/js/Kinds.js +164 -0
- package/ui/js/LICENSES/ISC-lucide.txt +43 -0
- package/ui/js/LangMarkPaths.js +47 -0
- package/ui/js/LangMarks.js +120 -0
- package/ui/js/Lists.js +11 -0
- package/ui/js/LocalSend.js +39 -0
- package/ui/js/LockedMenu.js +63 -0
- package/ui/js/MakeDefault.js +186 -0
- package/ui/js/MarkBox.js +7 -0
- package/ui/js/Markdown.js +119 -0
- package/ui/js/MarkdownLists.js +86 -0
- package/ui/js/MarkdownMaths.js +58 -0
- package/ui/js/MarkdownPictures.js +32 -0
- package/ui/js/MarkdownPrepared.js +139 -0
- package/ui/js/MarkdownTableFit.js +34 -0
- package/ui/js/Marks.js +148 -0
- package/ui/js/Marquee.js +96 -0
- package/ui/js/Match.js +93 -0
- package/ui/js/Material.js +109 -0
- package/ui/js/MdBlocks.js +437 -0
- package/ui/js/MdBreak.js +71 -0
- package/ui/js/MdChunks.js +70 -0
- package/ui/js/MdContainer.js +137 -0
- package/ui/js/MdDocument.js +337 -0
- package/ui/js/MdEmph.js +97 -0
- package/ui/js/MdEntity.js +108 -0
- package/ui/js/MdEntityTable.js +223 -0
- package/ui/js/MdEscape.js +59 -0
- package/ui/js/MdFront.js +37 -0
- package/ui/js/MdHold.js +32 -0
- package/ui/js/MdHtml.js +307 -0
- package/ui/js/MdHtmlBlock.js +290 -0
- package/ui/js/MdHtmlHeading.js +53 -0
- package/ui/js/MdHtmlImage.js +179 -0
- package/ui/js/MdInline.js +154 -0
- package/ui/js/MdItems.js +212 -0
- package/ui/js/MdLeaf.js +309 -0
- package/ui/js/MdLink.js +196 -0
- package/ui/js/MdMath.js +67 -0
- package/ui/js/MdParagraphs.js +138 -0
- package/ui/js/MdRefs.js +232 -0
- package/ui/js/MdResolve.js +226 -0
- package/ui/js/MdRun.js +300 -0
- package/ui/js/MdUrl.js +226 -0
- package/ui/js/Menu.js +514 -0
- package/ui/js/MenuContext.js +85 -0
- package/ui/js/MenuFit.js +13 -0
- package/ui/js/MenuRefresh.js +74 -0
- package/ui/js/MenuWheel.js +35 -0
- package/ui/js/Messages.js +186 -0
- package/ui/js/Motion.js +16 -0
- package/ui/js/Mounts.js +320 -0
- package/ui/js/MouseNav.js +13 -0
- package/ui/js/Nav.js +329 -0
- package/ui/js/NetFs.js +26 -0
- package/ui/js/OpenWith.js +83 -0
- package/ui/js/Ops.js +585 -0
- package/ui/js/Palette.js +33 -0
- package/ui/js/PathBar.js +260 -0
- package/ui/js/Permissions.js +179 -0
- package/ui/js/Phones.js +112 -0
- package/ui/js/Picker.js +353 -0
- package/ui/js/PlaceMenu.js +96 -0
- package/ui/js/Places.js +265 -0
- package/ui/js/PreviewAsk.js +21 -0
- package/ui/js/PreviewKeys.js +155 -0
- package/ui/js/PreviewSettle.js +29 -0
- package/ui/js/PreviewSwap.js +101 -0
- package/ui/js/PropertyFacts.js +144 -0
- package/ui/js/Protocols.js +296 -0
- package/ui/js/QuickLookKinds.js +27 -0
- package/ui/js/QuickLookRect.js +24 -0
- package/ui/js/RailDrop.js +51 -0
- package/ui/js/RailKeys.js +87 -0
- package/ui/js/RailMenu.js +133 -0
- package/ui/js/Recent.js +135 -0
- package/ui/js/RecentMode.js +156 -0
- package/ui/js/Reload.js +60 -0
- package/ui/js/Renderer.js +9 -0
- package/ui/js/RunFile.js +143 -0
- package/ui/js/Scripts.js +28 -0
- package/ui/js/Scroll.js +304 -0
- package/ui/js/ScrollOff.js +69 -0
- package/ui/js/Search.js +478 -0
- package/ui/js/Selection.js +97 -0
- package/ui/js/Settings.js +476 -0
- package/ui/js/SettingsAbout.js +97 -0
- package/ui/js/SettingsShelf.js +52 -0
- package/ui/js/SheetKeys.js +42 -0
- package/ui/js/SheetQuery.js +281 -0
- package/ui/js/ShelfPile.js +27 -0
- package/ui/js/SlowClick.js +53 -0
- package/ui/js/SlowOp.js +6 -0
- package/ui/js/Sort.js +134 -0
- package/ui/js/Startup.js +63 -0
- package/ui/js/StateWords.js +17 -0
- package/ui/js/Status.js +238 -0
- package/ui/js/Swap.js +166 -0
- package/ui/js/TabMove.js +39 -0
- package/ui/js/Tabs.js +751 -0
- package/ui/js/Tags.js +134 -0
- package/ui/js/Taildrop.js +128 -0
- package/ui/js/Tap.js +180 -0
- package/ui/js/TextSize.js +107 -0
- package/ui/js/Thumbs.js +158 -0
- package/ui/js/Transfer.js +172 -0
- package/ui/js/Trash.js +84 -0
- package/ui/js/TrashDates.js +47 -0
- package/ui/js/TrashDrop.js +64 -0
- package/ui/js/UiState.js +438 -0
- package/ui/js/Unlock.js +152 -0
- package/ui/js/Update.js +130 -0
- package/ui/js/UserDirs.js +56 -0
- package/ui/qmldir +230 -0
package/ui/js/Collide.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
.import "Format.js" as Format
|
|
3
|
+
.import "Ops.js" as Ops
|
|
4
|
+
.import "Status.js" as Status
|
|
5
|
+
.import "Swap.js" as Swap
|
|
6
|
+
|
|
7
|
+
// The question a paste or a drop asks before it lands on names that exist, as decisions ui/CollideHost.qml and ui/CollideConfirm.qml wire.
|
|
8
|
+
|
|
9
|
+
// Whole sentences with "%1" for a value, filled by Format.fill so each translates as one; one per count, because the verb changes with it.
|
|
10
|
+
var WORDS = {
|
|
11
|
+
existsOne: "%1 already exists in %2",
|
|
12
|
+
existsMany: "%1 items already exist in %2"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Left to right, the order h, l and Tab walk.
|
|
16
|
+
var BUTTONS = ["cancel", "skip", "keep", "merge", "replace"]
|
|
17
|
+
var LABELS = { cancel: "Cancel", skip: "Skip", keep: "Keep both", merge: "Merge", replace: "Replace" }
|
|
18
|
+
// Where the card opens, and so what a reflexive Enter takes: the one choice that changes nothing already there.
|
|
19
|
+
var START = "keep"
|
|
20
|
+
var EXPLAIN = "Replaced items go to Trash, and Undo restores them."
|
|
21
|
+
// What a transfer carries when nothing collided: any name that appears after the question is refused.
|
|
22
|
+
var NONE = "refuse"
|
|
23
|
+
var WAITING = "A transfer is already waiting on its question; try again once it is answered."
|
|
24
|
+
|
|
25
|
+
// One card geometry for CollideConfirm and FatNamesConfirm, so the two cards keep one size.
|
|
26
|
+
var CARD_REFERENCE_BODY = 13
|
|
27
|
+
var CARD_PAD = 16
|
|
28
|
+
var CARD_CONTENT_BASE = 368
|
|
29
|
+
function cardReferenceScale(bodySmall) { return bodySmall / CARD_REFERENCE_BODY }
|
|
30
|
+
function cardPadding(scale) { return Math.round(CARD_PAD * scale) }
|
|
31
|
+
function cardContentWidth(scale, ratio, buttonsWidth) {
|
|
32
|
+
return Math.max(Math.round(CARD_CONTENT_BASE * scale * ratio), buttonsWidth)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// The folder's own name, which is what the title says; the root has no leaf, so it says itself.
|
|
36
|
+
function folderName(dest) {
|
|
37
|
+
var path = String(dest || "")
|
|
38
|
+
var cut = path.lastIndexOf("/")
|
|
39
|
+
var leaf = cut >= 0 ? path.substring(cut + 1) : path
|
|
40
|
+
return leaf.length > 0 ? leaf : "/"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// "screenshot.png already exists in Pictures" for one, "3 items already exist in Downloads" for several.
|
|
44
|
+
function title(names, total, dest) {
|
|
45
|
+
if (total === 1 && names.length > 0)
|
|
46
|
+
return Format.fill(WORDS.existsOne, names[0].n, folderName(dest))
|
|
47
|
+
return Format.fill(WORDS.existsMany, Format.count(total), folderName(dest))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// The row under the list, empty when every collision is already on it.
|
|
51
|
+
function more(total, shown) {
|
|
52
|
+
return total > shown ? "and " + Format.count(total - shown) + " more" : ""
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Only the buttons the card shows take the ring; a hidden Merge never holds it.
|
|
56
|
+
function shownButtons(showMerge) {
|
|
57
|
+
return showMerge === true ? BUTTONS : BUTTONS.filter(function (b) { return b !== "merge" })
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// h and l stop at the ends like TrashConfirm's pair; Tab and Backtab come round. A focus not in order starts from start.
|
|
61
|
+
function walk(order, focus, key, modifiers, start) {
|
|
62
|
+
var at = order.indexOf(focus)
|
|
63
|
+
if (at < 0)
|
|
64
|
+
at = Math.max(0, order.indexOf(start))
|
|
65
|
+
var last = order.length - 1
|
|
66
|
+
if (key === Qt.Key_H || key === Qt.Key_Left)
|
|
67
|
+
return order[Math.max(0, at - 1)]
|
|
68
|
+
if (key === Qt.Key_L || key === Qt.Key_Right)
|
|
69
|
+
return order[Math.min(last, at + 1)]
|
|
70
|
+
// Shift+Tab reaches a Keys handler as Backtab or as Tab with Shift held, depending on the input path.
|
|
71
|
+
if (key === Qt.Key_Backtab || key === Qt.Key_Tab && (modifiers & Qt.ShiftModifier))
|
|
72
|
+
return order[(at + last) % order.length]
|
|
73
|
+
if (key === Qt.Key_Tab)
|
|
74
|
+
return order[(at + 1) % order.length]
|
|
75
|
+
return order[at]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function moved(focus, key, showMerge, modifiers) {
|
|
79
|
+
return walk(shownButtons(showMerge), focus, key, modifiers, START)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function activates(key) {
|
|
83
|
+
return key === Qt.Key_Return || key === Qt.Key_Enter || key === Qt.Key_Space
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// The transfer the card holds, its rows stamped in the numbering they were read in; a menu's is resolved from the menu's own capture.
|
|
87
|
+
function waiting(request, held) {
|
|
88
|
+
return request.menuId ? request : Swap.named(request, held)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// One question at a time, open or still in flight: a second is refused out loud rather than replacing the first.
|
|
92
|
+
function refusal(opened, pending) {
|
|
93
|
+
return opened || pending !== null ? WAITING : ""
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// A refused question ends the wait the same way an answered one does: the card never opens, so nothing stays waiting.
|
|
97
|
+
function droppedPending(where, input) {
|
|
98
|
+
return where === "stale" && (input === "collisions" || input === "mergecollisions")
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// The question names the same sources the transfer will, in the backend's order: a shelf drag's paths, a menu's selection, paths, rows.
|
|
102
|
+
function question(request, probe, id) {
|
|
103
|
+
var asked = { c: "collisions", id: id, dest: request.dest }
|
|
104
|
+
if (request.fat)
|
|
105
|
+
asked.fat = request.fat
|
|
106
|
+
if (probe && probe.length > 0)
|
|
107
|
+
asked.paths = probe
|
|
108
|
+
else if (request.menuId)
|
|
109
|
+
asked.menuId = request.menuId
|
|
110
|
+
else if (request.paths && request.paths.length > 0)
|
|
111
|
+
asked.paths = request.paths
|
|
112
|
+
else
|
|
113
|
+
asked.rows = request.rows || []
|
|
114
|
+
// Rows are asked about in the numbering the transfer will name, ui/js/Swap.js named().
|
|
115
|
+
if (asked.rows && request.listing !== undefined)
|
|
116
|
+
asked.listing = request.listing
|
|
117
|
+
return asked
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// The waiting transfer with the answer on it; the id is what lets the backend cover only the names it listed.
|
|
121
|
+
function transfer(request, choice, id) {
|
|
122
|
+
return Object.assign({}, request, { collide: choice, collideId: id })
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Paste as links answers on the waiting request like a transfer; rows ride along only when named, so paths-only pastes skip listing checks.
|
|
126
|
+
function link(request, choice, id) {
|
|
127
|
+
var out = { c: "link", op: request.op, paths: request.paths || [],
|
|
128
|
+
dest: request.dest, collide: choice, collideId: id }
|
|
129
|
+
if (request.fat)
|
|
130
|
+
out.fat = request.fat
|
|
131
|
+
if (request.rows && request.rows.length > 0) out.rows = request.rows
|
|
132
|
+
if (request.listing !== undefined) out.listing = request.listing
|
|
133
|
+
return out
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// After Merge, one walk of the sources against the destination, before anything is written.
|
|
137
|
+
function mergeQuestion(request, probe, id) {
|
|
138
|
+
var asked = { c: "mergecollisions", id: id, dest: request.dest }
|
|
139
|
+
if (probe && probe.length > 0)
|
|
140
|
+
asked.paths = probe
|
|
141
|
+
else if (request.menuId)
|
|
142
|
+
asked.menuId = request.menuId
|
|
143
|
+
else if (request.paths && request.paths.length > 0)
|
|
144
|
+
asked.paths = request.paths
|
|
145
|
+
else
|
|
146
|
+
asked.rows = request.rows || []
|
|
147
|
+
if (asked.rows && request.listing !== undefined)
|
|
148
|
+
asked.listing = request.listing
|
|
149
|
+
return asked
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// The merge transfer with the second card's answer on it; the id names the walk it answers.
|
|
153
|
+
function mergeTransfer(request, inner, id) {
|
|
154
|
+
return Object.assign({}, request, { collide: "merge", collideId: id, inner: inner })
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// The second card names the folder it merges into: the one merging folder when it was the only
|
|
158
|
+
// name the first card counted, else the destination, which every other name it lists lands in.
|
|
159
|
+
// Sample input: a first card of trip/ alone gives ".../trip"; trip/ beside a.txt gives the destination.
|
|
160
|
+
function mergeDest(request, outerNames, outerTotal) {
|
|
161
|
+
var folders = (outerNames || []).filter(function (n) { return n.d === true }).map(function (n) { return n.n })
|
|
162
|
+
if (folders.length === 1 && (outerTotal === undefined || outerTotal === 1))
|
|
163
|
+
return String(request.dest).replace(/\/$/, "") + "/" + folders[0]
|
|
164
|
+
return request.dest
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// The board's merged line as whole sentences, one per count, joined once; the undo hint stays its suffix.
|
|
168
|
+
var MERGED_ONE = "Merged 1 item into %1"
|
|
169
|
+
var MERGED_MANY = "Merged %1 items into %2"
|
|
170
|
+
var MERGED_KEPT = "%1 kept both"
|
|
171
|
+
var MERGED_FAILED = "%1 failed"
|
|
172
|
+
var MERGED_SKIPPED = "%1 skipped"
|
|
173
|
+
function merged(count, keptBoth, leaf, failed, skipped, cancelled, note) {
|
|
174
|
+
var segments = [count === 1 ? MERGED_ONE.replace("%1", leaf) : MERGED_MANY.replace("%1", Format.count(count)).replace("%2", leaf)]
|
|
175
|
+
if (keptBoth > 0) segments.push(MERGED_KEPT.replace("%1", Format.count(keptBoth)))
|
|
176
|
+
if (failed > 0) segments.push(MERGED_FAILED.replace("%1", Format.count(failed)))
|
|
177
|
+
if (skipped > 0) segments.push(MERGED_SKIPPED.replace("%1", Format.count(skipped)))
|
|
178
|
+
if (cancelled) segments.push("cancelled")
|
|
179
|
+
if (count > 0 && String(note || "").length > 0) segments.push(note)
|
|
180
|
+
var line = segments.join(" · ")
|
|
181
|
+
return line + (count > 0 ? Status.undoHint() : "")
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// The done line off the transferdone line itself, so a refused merge never mislabels the next copy.
|
|
185
|
+
function doneLine(t, r) {
|
|
186
|
+
if (r.into && r.into.length > 0)
|
|
187
|
+
return merged(r.merged || 0, r.keptBoth || 0, r.into, r.failed, r.skipped, r.cancelled, r.note)
|
|
188
|
+
return Ops.transferDone(t, r.ok, r.failed, r.skipped, r.cancelled, r.durable, r.note)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Drops callout 3, the FAT names card: every string is one whole sentence with placeholders for its values.
|
|
192
|
+
var FAT_DEFAULT = "rename"
|
|
193
|
+
var FAT_BUTTONS = { cancel: "Cancel", skip: "Skip them", rename: "Rename and copy" }
|
|
194
|
+
var FAT_TITLE_ONE = "1 name cannot exist on %1 (%2)"
|
|
195
|
+
var FAT_TITLE_MANY = "%1 names cannot exist on %2 (%3)"
|
|
196
|
+
var FAT_NOTE = "%1 refuses : ? * \" < > | and trailing dots or spaces."
|
|
197
|
+
// The mount table's own word as the card spells it; vfat could be any FAT width, so it claims none.
|
|
198
|
+
var FAT_FILESYSTEMS = { exfat: "exFAT", vfat: "FAT", fat: "FAT", msdos: "FAT", fat12: "FAT12", fat16: "FAT16", fat32: "FAT32", ntfs: "NTFS", ntfs3: "NTFS" }
|
|
199
|
+
function filesystemLabel(fstype) {
|
|
200
|
+
return FAT_FILESYSTEMS[String(fstype).toLowerCase()] || String(fstype)
|
|
201
|
+
}
|
|
202
|
+
// One pass over the placeholders, so a value that holds a placeholder or a dollar sign is never read twice.
|
|
203
|
+
function fill(template, values) {
|
|
204
|
+
return template.replace(/%(\d)/g, function (whole, n) { return values[n - 1] })
|
|
205
|
+
}
|
|
206
|
+
function cardTitle(total, volume, fstype) {
|
|
207
|
+
var label = filesystemLabel(fstype)
|
|
208
|
+
return total === 1 ? fill(FAT_TITLE_ONE, [volume, label]) : fill(FAT_TITLE_MANY, [Format.count(total), volume, label])
|
|
209
|
+
}
|
|
210
|
+
function cardNote(fstype) {
|
|
211
|
+
return fill(FAT_NOTE, [filesystemLabel(fstype)])
|
|
212
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
.import "DirSizes.js" as DirSizes
|
|
3
|
+
.import "Format.js" as Format
|
|
4
|
+
|
|
5
|
+
// The strings an autofit measures, the same ones ui/Row.qml draws.
|
|
6
|
+
// Sample input: ("size", {p: 33188, d: false, s: 18000}) answers "18.0 kB".
|
|
7
|
+
var FIT_KEYS = ["mode", "size", "date", "kind"]
|
|
8
|
+
|
|
9
|
+
function cellText(key, row, kindNames, dirSize) {
|
|
10
|
+
if (key === "mode")
|
|
11
|
+
return Format.permissions(row.p)
|
|
12
|
+
if (key === "size") {
|
|
13
|
+
if (Format.isSymlink(row.p))
|
|
14
|
+
return "link"
|
|
15
|
+
if (!row.d)
|
|
16
|
+
return Format.size(row.s)
|
|
17
|
+
return DirSizes.folderText(dirSize, row)
|
|
18
|
+
}
|
|
19
|
+
if (key === "date")
|
|
20
|
+
return row.m === null ? "--" : Format.date(row.m)
|
|
21
|
+
var text = (kindNames || [])[row.k]
|
|
22
|
+
return text !== undefined ? text : ""
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// The held index behind one held row, for the dirsize the row would draw.
|
|
26
|
+
function dirSizeFor(state, held, at) {
|
|
27
|
+
return DirSizes.sizeFor(state, held + at)
|
|
28
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// Neighbour-column background menus: a peek's empty space navigates to its DRAWN directory (parent/ancestor or shownChildPath, never pending childPath) and opens the background menu once its rows land.
|
|
4
|
+
|
|
5
|
+
// A trailing slash trimmed except at the root itself.
|
|
6
|
+
// Sample input: trimSlash("/home/gm/") is "/home/gm".
|
|
7
|
+
function trimSlash(path) {
|
|
8
|
+
var text = String(path)
|
|
9
|
+
return text.length > 1 && text.charAt(text.length - 1) === "/" ? text.substring(0, text.length - 1) : text
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// True when two paths name the same directory, trailing slash aside.
|
|
13
|
+
// Sample input: samePath("/a/", "/a") is true.
|
|
14
|
+
function samePath(a, b) {
|
|
15
|
+
return trimSlash(a) === trimSlash(b)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// "" when a background intent may arm, else the busy reason: rejects before any intent is stored, so a refused open never leaves one behind.
|
|
19
|
+
// Sample input: canArm({listInFlight: true}) is "loading".
|
|
20
|
+
function canArm(pane) {
|
|
21
|
+
if (!pane)
|
|
22
|
+
return "no pane"
|
|
23
|
+
if (pane.listInFlight === true)
|
|
24
|
+
return "loading"
|
|
25
|
+
if (pane.trash && (pane.trash.opened === true || pane.trash.confirming === true))
|
|
26
|
+
return "trash"
|
|
27
|
+
if (pane.searchMode && pane.searchMode.length > 0)
|
|
28
|
+
return "search"
|
|
29
|
+
if (pane.collide && (pane.collide.opened === true || pane.collide.pending !== null))
|
|
30
|
+
return "collide"
|
|
31
|
+
if (pane.menuVisible === true)
|
|
32
|
+
return "menu"
|
|
33
|
+
if (pane.menuActions && pane.menuActions.opened === true)
|
|
34
|
+
return "menu"
|
|
35
|
+
if (pane.renamingIndex >= 0 || pane.renamePending === true)
|
|
36
|
+
return "rename"
|
|
37
|
+
if (pane.filterTyping === true)
|
|
38
|
+
return "filter"
|
|
39
|
+
if (pane.selectionBand !== null && pane.selectionBand !== undefined)
|
|
40
|
+
return "band"
|
|
41
|
+
return ""
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// True when the target is already shown: open the menu where it stands, no navigation.
|
|
45
|
+
// Sample input: directOpen("/a", "/a/") is true.
|
|
46
|
+
function directOpen(target, panePath) {
|
|
47
|
+
return target.length > 0 && samePath(target, panePath)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// True when landed rows may open the deferred menu: the pending target names this listing and it succeeded; empty counts because an empty directory is where the menu matters most, while locked, error and loading drop the intent.
|
|
51
|
+
// Sample input: shouldOpen("/a", "/a", "ready") is true.
|
|
52
|
+
function shouldOpen(panePath, pending, listingState) {
|
|
53
|
+
if (!pending || pending.length === 0)
|
|
54
|
+
return false
|
|
55
|
+
if (!samePath(panePath, pending))
|
|
56
|
+
return false
|
|
57
|
+
return listingState === "ready" || listingState === "empty"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// A failed listing drops the deferred menu, so no later rows open it.
|
|
61
|
+
function clearPendingBackground(pane) {
|
|
62
|
+
if (!pane)
|
|
63
|
+
return
|
|
64
|
+
pane.pendingBackground = ""
|
|
65
|
+
pane.pendingBackgroundAt = null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// The deferred neighbour background, consumed either way so later rows never open it: opens only a successful listing of the drawn target, at the stored point.
|
|
69
|
+
function applyPendingBackground(pane) {
|
|
70
|
+
if (!pane || !pane.pendingBackground || pane.pendingBackground.length === 0)
|
|
71
|
+
return
|
|
72
|
+
var target = pane.pendingBackground
|
|
73
|
+
var at = pane.pendingBackgroundAt
|
|
74
|
+
pane.pendingBackground = ""
|
|
75
|
+
pane.pendingBackgroundAt = null
|
|
76
|
+
if (!shouldOpen(pane.path, target, pane.listingState))
|
|
77
|
+
return
|
|
78
|
+
if (pane.searchMode && pane.searchMode.length > 0)
|
|
79
|
+
return
|
|
80
|
+
if (pane.trash && pane.trash.opened)
|
|
81
|
+
return
|
|
82
|
+
if (at === null || at === undefined)
|
|
83
|
+
return
|
|
84
|
+
pane.openBackgroundMenu(at)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Routes one neighbour background for the columns view: busy refuses before any intent is stored, the shown folder opens its menu where it stands, and any other target navigates with the menu waiting on its rows. Answers opened, navigating, ignored or refused:<reason>.
|
|
88
|
+
// Sample input: routeBackground({path: "/a"}, "/a", {x: 1}, {openBackground: function () {}}) is "opened".
|
|
89
|
+
function routeBackground(pane, base, scenePoint, menu) {
|
|
90
|
+
if (!pane || !base || base.length === 0 || !scenePoint)
|
|
91
|
+
return "ignored"
|
|
92
|
+
var busy = canArm(pane)
|
|
93
|
+
if (busy.length > 0) {
|
|
94
|
+
if (busy === "loading")
|
|
95
|
+
pane.message("A directory is already loading.", false)
|
|
96
|
+
return "refused:" + busy
|
|
97
|
+
}
|
|
98
|
+
if (directOpen(base, pane.path)) {
|
|
99
|
+
menu.openBackground(scenePoint)
|
|
100
|
+
return "opened"
|
|
101
|
+
}
|
|
102
|
+
pane.pendingBackground = base
|
|
103
|
+
pane.pendingBackgroundAt = scenePoint
|
|
104
|
+
pane.open(base)
|
|
105
|
+
if (!pane.listInFlight) {
|
|
106
|
+
pane.pendingBackground = ""
|
|
107
|
+
pane.pendingBackgroundAt = null
|
|
108
|
+
return "refused:not-started"
|
|
109
|
+
}
|
|
110
|
+
return "navigating"
|
|
111
|
+
}
|
package/ui/js/Columns.js
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// Which columns a list row of a given width draws. The name is the one column a file manager
|
|
4
|
+
// cannot do without, so it is the one that never loses: each metadata column drops instead, at
|
|
5
|
+
// the width where keeping it would push the name under its floor. ui/Header.qml and ui/Row.qml
|
|
6
|
+
// both resolve their set here, from the same width, so the header can never head a column the
|
|
7
|
+
// rows below it are not drawing.
|
|
8
|
+
|
|
9
|
+
// The optional columns, widest first, which is the order they drop in. Kind goes first: the row
|
|
10
|
+
// already marks its kind with a glyph and most names carry the extension, so it is the most
|
|
11
|
+
// redundant column as well as the widest. Mode goes last, because it is the permanent column.
|
|
12
|
+
var DROP_ORDER = ["kind", "date", "size", "mode"]
|
|
13
|
+
|
|
14
|
+
// The row width each optional column needs before it is drawn, keyed by column. t carries the
|
|
15
|
+
// tokens ui/Theme.qml resolved: rowPaddingX, gap, iconSize, nameMin, and one width per column.
|
|
16
|
+
// A floor includes every column that outlives it, because they drop in order and a wider column
|
|
17
|
+
// never survives a narrower one, which is what makes the four floors nest.
|
|
18
|
+
function floors(t) {
|
|
19
|
+
// The name's own slot at its floor: the row padding either side, the mark and the gap after it.
|
|
20
|
+
var running = t.rowPaddingX + t.iconSize + t.gap + t.nameMin + t.rowPaddingX
|
|
21
|
+
var out = {}
|
|
22
|
+
for (var i = DROP_ORDER.length - 1; i >= 0; i--) {
|
|
23
|
+
var key = DROP_ORDER[i]
|
|
24
|
+
running += t[key] + t.gap
|
|
25
|
+
out[key] = running
|
|
26
|
+
}
|
|
27
|
+
return out
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// One boolean per optional column, for a row of this width. hidden is the user's own set (keys
|
|
31
|
+
// "mode"/"size"/"date"/"kind", from qs module ViewState), subtracted from what the width
|
|
32
|
+
// affords: a hidden column never draws, and width still wins over a column the user wants back,
|
|
33
|
+
// so the name cannot be crowded out by a column the pane is too narrow to carry.
|
|
34
|
+
function set(width, t, hidden) {
|
|
35
|
+
var f = floors(t)
|
|
36
|
+
var h = {}
|
|
37
|
+
var list = hidden || []
|
|
38
|
+
for (var i = 0; i < list.length; i++) h[list[i]] = true
|
|
39
|
+
return {
|
|
40
|
+
location: false,
|
|
41
|
+
mode: width >= f.mode && !h["mode"],
|
|
42
|
+
size: width >= f.size && !h["size"],
|
|
43
|
+
date: width >= f.date && !h["date"],
|
|
44
|
+
kind: width >= f.kind && !h["kind"]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// DualPane protects its name floor without reserving absent Mode and Kind columns.
|
|
49
|
+
function dualSet(width, t, hidden) {
|
|
50
|
+
var base = 2 * t.rowPaddingX + t.iconSize + t.gap + t.nameMin
|
|
51
|
+
var showSize = (hidden || []).indexOf("size") < 0 && width >= base + t.size
|
|
52
|
+
var showDate = (hidden || []).indexOf("date") < 0
|
|
53
|
+
&& width >= base + (showSize ? t.size : 0) + t.date
|
|
54
|
+
return {mode: false, kind: false, location: false, size: showSize, date: showDate}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Recent protects its pane's name floor and reserves every non-hidden metadata width for Location.
|
|
58
|
+
function recentSet(width, t, hidden, dual) {
|
|
59
|
+
var base = 2 * t.rowPaddingX + t.iconSize + t.gap + t.nameMin
|
|
60
|
+
var metadataGap = dual ? 0 : t.gap
|
|
61
|
+
var h = hidden || []
|
|
62
|
+
var showSize = h.indexOf("size") < 0 && width >= base + t.size + metadataGap
|
|
63
|
+
var sizeSlot = showSize ? t.size + metadataGap : 0
|
|
64
|
+
var showDate = h.indexOf("date") < 0 && width >= base + sizeSlot + t.date + metadataGap
|
|
65
|
+
var locationFloor = base + (h.indexOf("size") < 0 ? t.size + metadataGap : 0)
|
|
66
|
+
+ (h.indexOf("date") < 0 ? t.date + metadataGap : 0) + t.location + t.gap
|
|
67
|
+
return {mode: false, kind: false,
|
|
68
|
+
size: showSize,
|
|
69
|
+
date: showDate,
|
|
70
|
+
location: width >= locationFloor}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// A peeked reply is keyed by what ordered it, so a stale ancestor column never survives the hidden-last toggle: path plus hidden plus hiddenLast.
|
|
74
|
+
// Sample input: peekKey("/a", true, true) is "/a\n11".
|
|
75
|
+
function peekKey(path, hidden, hiddenLast) {
|
|
76
|
+
return String(path) + "\n" + (hidden === true ? "1" : "0") + (hiddenLast === true ? "1" : "0")
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// The folder's own remembered order a column asks under and its reply echoes: "" for name order, else the key and 1 when descending.
|
|
80
|
+
// Sample input: orderTag("size", true) is "size1", orderTag("", false) is "".
|
|
81
|
+
function orderTag(by, desc) {
|
|
82
|
+
return by ? String(by) + (desc === true ? "1" : "0") : ""
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// The row count and the folder order join the key only for an outstanding ask, so a resize or a re-sort never orphans a stored column.
|
|
86
|
+
// Sample input: sentKey("/a\n00", 35) is "/a\n00\n35", and sentKey("/a\n00", 35, "size1") is "/a\n00\n35\nsize1".
|
|
87
|
+
function sentKey(key, first, order) {
|
|
88
|
+
return String(key) + "\n" + Math.floor(Number(first)) + (order ? "\n" + String(order) : "")
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// An ask this view made and still awaits, counted per sentKey (path, flags, row count, order), so another client's reply never lands in its column and a column re-asked in flight lands both replies.
|
|
92
|
+
// Sample input: trackAsk(trackAsk({}, "/a\n10\n35"), "/a\n10\n35") holds that key twice.
|
|
93
|
+
function trackAsk(pending, key) {
|
|
94
|
+
var next = {}
|
|
95
|
+
var src = pending || {}
|
|
96
|
+
for (var k in src) next[k] = src[k]
|
|
97
|
+
next[String(key)] = (next[String(key)] || 0) + 1
|
|
98
|
+
return next
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// True only for a reply this view asked for; anything else is another client's.
|
|
102
|
+
// Sample input: hasAsk(trackAsk({}, "/a\n10"), "/a\n10") is true.
|
|
103
|
+
function hasAsk(pending, key) {
|
|
104
|
+
return ((pending || {})[String(key)] || 0) > 0
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// One ask answered or superseded; a new listing drops them all.
|
|
108
|
+
// Sample input: dropAsk(trackAsk({}, "/a\n10"), "/a\n10") holds nothing, and dropAsk of a key asked twice holds it once.
|
|
109
|
+
function dropAsk(pending, key) {
|
|
110
|
+
var next = {}
|
|
111
|
+
var want = String(key)
|
|
112
|
+
var src = pending || {}
|
|
113
|
+
for (var k in src) {
|
|
114
|
+
var left = k === want ? src[k] - 1 : src[k]
|
|
115
|
+
if (left > 0) next[k] = left
|
|
116
|
+
}
|
|
117
|
+
return next
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// The columns view's count follows the window width, capped by Settings View's limit.
|
|
121
|
+
// Sample input: (899, 5) answers 2.
|
|
122
|
+
var COUNT_4_AT = 1700
|
|
123
|
+
var COUNT_5_AT = 2300
|
|
124
|
+
var COUNT_NARROW_AT = 900
|
|
125
|
+
var COUNT_MIN = 2
|
|
126
|
+
var COUNT_MAX = 5
|
|
127
|
+
// The shipped View limit: a default install holds 3 columns from 900 px up.
|
|
128
|
+
var COUNT_DEFAULT = 3
|
|
129
|
+
|
|
130
|
+
// A stored number clamps to 2 to 5, anything else reads as the shipped default.
|
|
131
|
+
function cappedLimit(limit) {
|
|
132
|
+
if (typeof limit !== "number")
|
|
133
|
+
return COUNT_DEFAULT
|
|
134
|
+
var n = Math.floor(limit)
|
|
135
|
+
if (!(n >= COUNT_MIN) && !(n <= COUNT_MAX))
|
|
136
|
+
return COUNT_DEFAULT
|
|
137
|
+
if (n < COUNT_MIN)
|
|
138
|
+
return COUNT_MIN
|
|
139
|
+
if (n > COUNT_MAX)
|
|
140
|
+
return COUNT_MAX
|
|
141
|
+
return n
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// One integer for a window of this width; resizing re-lays columns without re-reading.
|
|
145
|
+
function columnCountForWidth(width, limit) {
|
|
146
|
+
var count = width < COUNT_NARROW_AT ? 2 : width < COUNT_4_AT ? 3
|
|
147
|
+
: width < COUNT_5_AT ? 4 : 5
|
|
148
|
+
var cap = cappedLimit(limit)
|
|
149
|
+
if (count > cap)
|
|
150
|
+
count = cap
|
|
151
|
+
if (count < COUNT_MIN)
|
|
152
|
+
count = COUNT_MIN
|
|
153
|
+
return count
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Extra columns are ancestors, read with the same viewport-scoped peek as the parent today.
|
|
157
|
+
function ancestorsForCount(count) {
|
|
158
|
+
var n = Math.floor(Number(count))
|
|
159
|
+
if (!(n >= COUNT_MIN))
|
|
160
|
+
return 0
|
|
161
|
+
return Math.min(n, COUNT_MAX) - 2
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// The parent one step up, with a trailing slash trimmed except at the root itself.
|
|
165
|
+
// Sample input: ancestorParent("/home/") is "/".
|
|
166
|
+
function ancestorParent(path) {
|
|
167
|
+
var text = String(path)
|
|
168
|
+
if (text.length > 1 && text.charAt(text.length - 1) === "/")
|
|
169
|
+
text = text.substring(0, text.length - 1)
|
|
170
|
+
var cut = text.lastIndexOf("/")
|
|
171
|
+
return cut <= 0 ? "/" : text.substring(0, cut)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// The nearest distinct ancestors of a path, oldest first, stopping where the climb stops.
|
|
175
|
+
// Sample input: ancestors("/home/gm", 3) is ["/", "/home"].
|
|
176
|
+
function ancestors(path, count) {
|
|
177
|
+
var n = Math.floor(Number(count))
|
|
178
|
+
if (!(n >= 1))
|
|
179
|
+
return []
|
|
180
|
+
var text = String(path)
|
|
181
|
+
if (text.length === 0)
|
|
182
|
+
return []
|
|
183
|
+
if (text.length > 1 && text.charAt(text.length - 1) === "/")
|
|
184
|
+
text = text.substring(0, text.length - 1)
|
|
185
|
+
var near = []
|
|
186
|
+
var cur = text
|
|
187
|
+
for (var i = 0; i < n; i++) {
|
|
188
|
+
var p = ancestorParent(cur)
|
|
189
|
+
if (p === cur || near.indexOf(p) >= 0)
|
|
190
|
+
break
|
|
191
|
+
near.push(p)
|
|
192
|
+
cur = p
|
|
193
|
+
}
|
|
194
|
+
return near.reverse()
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// True while an ancestor column of this depth names a directory of its own.
|
|
198
|
+
// Sample input: ancestorShown("/home", 2) is false.
|
|
199
|
+
function ancestorShown(path, depth) {
|
|
200
|
+
var d = Math.floor(Number(depth))
|
|
201
|
+
if (!(d >= 1))
|
|
202
|
+
return false
|
|
203
|
+
return ancestors(path, d).length >= d
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Sample input: neighbourAsks("/home/gm", 1200, 5) is ["/home"], the shown ancestors oldest first.
|
|
207
|
+
function neighbourAsks(path, width, limit) {
|
|
208
|
+
var want = ancestorsForCount(columnCountForWidth(Number(width), limit))
|
|
209
|
+
if (!(want >= 1))
|
|
210
|
+
return []
|
|
211
|
+
return ancestors(path, want)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Sample input: keepAsks({ drawn: ["/a"] }, ["/a"], "/a/b") answers [{path "/a", again false}, {path "/a/b", again true}] and leaves drawn ["/a", "/a/b"]; again names a column not drawn last refresh.
|
|
215
|
+
function keepAsks(keep, asks, child) {
|
|
216
|
+
var shown = child.length > 0 && asks.indexOf(child) < 0 ? asks.concat([child]) : asks.slice()
|
|
217
|
+
var plan = shown.map(function (path) { return { path: path, again: keep.drawn.indexOf(path) < 0 } })
|
|
218
|
+
keep.drawn = shown
|
|
219
|
+
return plan
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ui.json carries whatever a hand edit wrote, so only a finite number is a stored width; anything else keeps the measured one.
|
|
223
|
+
// Sample input: storedNumber("120") is NaN, storedNumber(120.6) is 121.
|
|
224
|
+
function storedNumber(raw) {
|
|
225
|
+
if (typeof raw !== "number" || !isFinite(raw) || raw < 0)
|
|
226
|
+
return NaN
|
|
227
|
+
return Math.round(raw)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ListColumns040 board: a dragged edge clamps to the rails, and a double click fits the
|
|
231
|
+
// widest value the window holds, never a directory-wide scan. Sample input: 9999 clamps.
|
|
232
|
+
var MIN_LIST_WIDTH = 48
|
|
233
|
+
var MAX_LIST_WIDTH = 480
|
|
234
|
+
|
|
235
|
+
// One whole pixel inside the rails, whatever the drag handed in.
|
|
236
|
+
function clampListWidth(px) {
|
|
237
|
+
var n = Math.round(Number(px))
|
|
238
|
+
if (!(n >= 0))
|
|
239
|
+
return MIN_LIST_WIDTH
|
|
240
|
+
if (n < MIN_LIST_WIDTH)
|
|
241
|
+
return MIN_LIST_WIDTH
|
|
242
|
+
if (n > MAX_LIST_WIDTH)
|
|
243
|
+
return MAX_LIST_WIDTH
|
|
244
|
+
return n
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// The widest held cell, clamped; an empty window keeps the column it has, so a fit can narrow as well as widen.
|
|
248
|
+
function autofitWidth(widths, fallback) {
|
|
249
|
+
var cells = widths || []
|
|
250
|
+
if (cells.length === 0)
|
|
251
|
+
return clampListWidth(fallback)
|
|
252
|
+
var best = MIN_LIST_WIDTH
|
|
253
|
+
for (var i = 0; i < cells.length; i++) {
|
|
254
|
+
var w = Math.round(Number(cells[i]))
|
|
255
|
+
if (w >= 0 && w > best)
|
|
256
|
+
best = w
|
|
257
|
+
}
|
|
258
|
+
return clampListWidth(best)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function names(s) {
|
|
262
|
+
var out = ["name"]
|
|
263
|
+
if (s.location) out.push("location")
|
|
264
|
+
for (var i = DROP_ORDER.length - 1; i >= 0; i--) {
|
|
265
|
+
var key = DROP_ORDER[i]
|
|
266
|
+
if (s[key])
|
|
267
|
+
out.push(key)
|
|
268
|
+
}
|
|
269
|
+
return out.join(",")
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// An unanswered folder keeps the old column by data, never by picture.
|
|
273
|
+
// Sample input: folderDataHold(true, false) is true.
|
|
274
|
+
function folderDataHold(cursorIsDir, answered) {
|
|
275
|
+
return cursorIsDir === true && answered !== true
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// A file load needs a real file row: null never loads and a folder waits by data.
|
|
279
|
+
// Sample input: isFileRow({d: false}) is true.
|
|
280
|
+
function isFileRow(row) {
|
|
281
|
+
return row !== null && row !== undefined && row.d !== true
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// A landed peek shows the cursor folder while it is still the one waiting.
|
|
285
|
+
// Sample input: showFolderOnPeek("/a", "/b", true) is true.
|
|
286
|
+
function showFolderOnPeek(childPath, shownChildPath, answered) {
|
|
287
|
+
return answered === true && childPath.length > 0 && childPath !== shownChildPath
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// A data-held empty folder lands settled, the whole frame the picture hold revealed.
|
|
291
|
+
// Sample input: shouldSettleHero(true, "/a", "/a", false, 0) is true.
|
|
292
|
+
function shouldSettleHero(cursorIsDir, path, childPath, readFailed, rowCount) {
|
|
293
|
+
if (cursorIsDir !== true || readFailed === true)
|
|
294
|
+
return false
|
|
295
|
+
if (String(path) !== String(childPath))
|
|
296
|
+
return false
|
|
297
|
+
return Math.floor(Number(rowCount)) === 0
|
|
298
|
+
}
|