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
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
.import "Input.js" as Input
|
|
3
|
+
|
|
4
|
+
// The keymap sheet's key decisions; imports no QML, so tests drive it.
|
|
5
|
+
|
|
6
|
+
// Sample input: isBareModifier(Qt.Key_Shift) is true, isBareModifier(Qt.Key_A) is false.
|
|
7
|
+
// A bare modifier carries no text, so without this the sheet would close under a shifted letter.
|
|
8
|
+
function isBareModifier(key) {
|
|
9
|
+
return key === Qt.Key_Shift || key === Qt.Key_Control || key === Qt.Key_Alt
|
|
10
|
+
|| key === Qt.Key_AltGr || key === Qt.Key_Meta || key === Qt.Key_CapsLock
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Sample input: sheetKey("co", Qt.Key_Shift, "") is "ignore".
|
|
14
|
+
// The one decision the sheet's Keys.onPressed runs, so the handler owns no key meaning of its own.
|
|
15
|
+
function sheetKey(query, key, text) {
|
|
16
|
+
if (key === Qt.Key_Escape)
|
|
17
|
+
return "close"
|
|
18
|
+
if (String(query).length > 0) {
|
|
19
|
+
if (key === Qt.Key_Up)
|
|
20
|
+
return "up"
|
|
21
|
+
if (key === Qt.Key_Down)
|
|
22
|
+
return "down"
|
|
23
|
+
if (key === Qt.Key_Return || key === Qt.Key_Enter)
|
|
24
|
+
return "activate"
|
|
25
|
+
}
|
|
26
|
+
if (key === Qt.Key_Backspace)
|
|
27
|
+
return String(query).length > 0 ? "backspace" : "close"
|
|
28
|
+
if (Input.isPrintable(text))
|
|
29
|
+
return "type"
|
|
30
|
+
// Delete edits nothing forward, so it is ignored rather than typed or closed on.
|
|
31
|
+
if (key === Qt.Key_Delete || isBareModifier(key))
|
|
32
|
+
return "ignore"
|
|
33
|
+
return "close"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Sample input: stepCursor(0, -1, 3) is 2, stepCursor(2, 1, 3) is 0.
|
|
37
|
+
// The cursor wraps at both ends; with no rows it parks at the first.
|
|
38
|
+
function stepCursor(cursor, delta, count) {
|
|
39
|
+
if (!(count > 0))
|
|
40
|
+
return 0
|
|
41
|
+
return (((cursor + delta) % count) + count) % count
|
|
42
|
+
}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
.import "Format.js" as Format
|
|
3
|
+
.import "Recent.js" as Recent
|
|
4
|
+
.import "Swap.js" as Swap
|
|
5
|
+
.import "Places.js" as Places
|
|
6
|
+
.import "Focus.js" as Focus
|
|
7
|
+
|
|
8
|
+
// The sheet's four-section query filter; imports no QML, so tests drive it.
|
|
9
|
+
|
|
10
|
+
var RESULT_LIMIT = 50
|
|
11
|
+
|
|
12
|
+
// The one non-listing context a sheet row can carry, named as the UI names that surface; the others have no name on screen.
|
|
13
|
+
var CONTEXT_NAMES = { media: "Preview" }
|
|
14
|
+
|
|
15
|
+
// Sample input: whereForContext("media") is "Preview", whereForContext("listing") is "".
|
|
16
|
+
// A key that works in one place only says where, in that place's name; a context the UI never names says nothing.
|
|
17
|
+
function whereForContext(context) {
|
|
18
|
+
var text = String(context || "")
|
|
19
|
+
if (text.indexOf(",") >= 0 || !Object.prototype.hasOwnProperty.call(CONTEXT_NAMES, text)) {
|
|
20
|
+
return ""
|
|
21
|
+
}
|
|
22
|
+
return CONTEXT_NAMES[text]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Section 0 from the generated sheet; the caller hands in sheetFor rows.
|
|
26
|
+
function actionCandidates(sheetRows) {
|
|
27
|
+
var out = []
|
|
28
|
+
var rows = sheetRows || []
|
|
29
|
+
for (var i = 0; i < rows.length; i++) {
|
|
30
|
+
out.push({ label: String(rows[i].label || ""), keys: String(rows[i].keys || ""),
|
|
31
|
+
section: 0, where: whereForContext(rows[i].context),
|
|
32
|
+
action: String(rows[i].action || ""), disabled: false, danger: false })
|
|
33
|
+
}
|
|
34
|
+
return out
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Section 1 from the menu's own model, hidden rows included; disabled rows never run.
|
|
38
|
+
function menuCandidates(entries, hintFor) {
|
|
39
|
+
var out = []
|
|
40
|
+
var rows = entries || []
|
|
41
|
+
var hint = typeof hintFor === "function" ? hintFor : function () { return "" }
|
|
42
|
+
for (var i = 0; i < rows.length; i++) {
|
|
43
|
+
var entry = rows[i]
|
|
44
|
+
if (!entry || entry.separator === true) {
|
|
45
|
+
continue
|
|
46
|
+
}
|
|
47
|
+
var action = String(entry.action || entry.id || "")
|
|
48
|
+
out.push({ label: String(entry.label || ""), keys: String(hint(action) || ""),
|
|
49
|
+
section: 1, where: "", menuAction: actionWithSub(action, ""),
|
|
50
|
+
disabled: entry.disabled === true, danger: entry.danger === true })
|
|
51
|
+
var sub = entry.submenu || []
|
|
52
|
+
for (var j = 0; j < sub.length; j++) {
|
|
53
|
+
if (!sub[j] || sub[j].separator === true) {
|
|
54
|
+
continue
|
|
55
|
+
}
|
|
56
|
+
var leafId = String(sub[j].id || "")
|
|
57
|
+
// A leaf with its own sheet wording reads whole, with no muted flyout suffix.
|
|
58
|
+
var sheetLabel = String(sub[j].sheetLabel || "")
|
|
59
|
+
out.push({ label: sheetLabel.length > 0 ? sheetLabel : String(sub[j].label || ""), keys: "",
|
|
60
|
+
section: 1, where: sheetLabel.length > 0 ? "" : String(entry.label || ""),
|
|
61
|
+
menuAction: actionWithSub(action, leafId), parentAction: action,
|
|
62
|
+
disabled: entry.disabled === true || sub[j].disabled === true,
|
|
63
|
+
danger: entry.danger === true })
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return out
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function actionWithSub(action, leafId) {
|
|
70
|
+
return leafId.length > 0 ? action + ":" + leafId : action
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// The group name the rail shows: Favorites, Places, or the network/device group.
|
|
74
|
+
function placeWhere(entry) {
|
|
75
|
+
var group = String((entry && entry.group) || "")
|
|
76
|
+
// flea-qml: a drive found by looking is a plain folder row drawn under DEVICES.
|
|
77
|
+
if (entry && entry.volume === true) {
|
|
78
|
+
return "Devices"
|
|
79
|
+
}
|
|
80
|
+
if (group === "favourite" || group === "favorite") {
|
|
81
|
+
return "Favorites"
|
|
82
|
+
}
|
|
83
|
+
if (group === "network") {
|
|
84
|
+
return "Network"
|
|
85
|
+
}
|
|
86
|
+
if (group === "device") {
|
|
87
|
+
return "Devices"
|
|
88
|
+
}
|
|
89
|
+
return "Places"
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Section 2 from the rail's entries; an exact NAME match ranks first.
|
|
93
|
+
function placeCandidates(railEntries) {
|
|
94
|
+
var out = []
|
|
95
|
+
var rows = railEntries || []
|
|
96
|
+
for (var i = 0; i < rows.length; i++) {
|
|
97
|
+
var entry = rows[i]
|
|
98
|
+
if (!entry || String(entry.label || "").length === 0) {
|
|
99
|
+
continue
|
|
100
|
+
}
|
|
101
|
+
if (String(entry.kind || "") === "recent") {
|
|
102
|
+
continue
|
|
103
|
+
}
|
|
104
|
+
out.push({ label: "Open " + entry.label, name: String(entry.label),
|
|
105
|
+
keys: "", section: 2, where: placeWhere(entry), railIndex: i, entry: entry })
|
|
106
|
+
}
|
|
107
|
+
return out
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Section 3 from the xbel source, read once per query line and bounded by Recent.LIMIT.
|
|
111
|
+
function recentCandidates(recentPaths, home) {
|
|
112
|
+
var out = []
|
|
113
|
+
var rows = recentPaths || []
|
|
114
|
+
var bound = Math.min(rows.length, Recent.LIMIT)
|
|
115
|
+
for (var i = 0; i < bound; i++) {
|
|
116
|
+
var path = String(rows[i] || "")
|
|
117
|
+
if (path.length === 0) {
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
var leaf = Recent.nameOf(path)
|
|
121
|
+
var parent = Format.tilde(Recent.locationOf(path), String(home || ""))
|
|
122
|
+
out.push({ label: "Open " + leaf, keys: "", section: 3,
|
|
123
|
+
where: parent, path: path })
|
|
124
|
+
}
|
|
125
|
+
return out
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// The matched run the specimen washes. Case-insensitive substring, null when none.
|
|
129
|
+
function matchOf(label, query) {
|
|
130
|
+
var text = String(label || "").toLowerCase()
|
|
131
|
+
var needle = String(query || "").trim().toLowerCase()
|
|
132
|
+
if (needle.length === 0) {
|
|
133
|
+
return null
|
|
134
|
+
}
|
|
135
|
+
var at = text.indexOf(needle)
|
|
136
|
+
if (at < 0) {
|
|
137
|
+
return null
|
|
138
|
+
}
|
|
139
|
+
return { start: at, length: needle.length }
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Sample input: a key row {action: "trash"} then a menu row {menuAction: "trash", label: "Move to Trash"} keeps the key row only, carrying menuLabel "Move to Trash".
|
|
143
|
+
// One action, one row: the key row stays, the menu's wording rides on it to be searched, and a disabled menu row's verdict rides on it too, so a folder that refuses Rename refuses it here.
|
|
144
|
+
function unique(candidates) {
|
|
145
|
+
var at = {}
|
|
146
|
+
var out = []
|
|
147
|
+
var list = candidates || []
|
|
148
|
+
for (var i = 0; i < list.length; i++) {
|
|
149
|
+
var run = String(list[i].action || list[i].menuAction || "")
|
|
150
|
+
if (run.length === 0) {
|
|
151
|
+
out.push(list[i])
|
|
152
|
+
} else if (at[run] === undefined) {
|
|
153
|
+
at[run] = out.length
|
|
154
|
+
out.push(list[i])
|
|
155
|
+
} else if (list[i].section === 1 && out[at[run]].section === 0) {
|
|
156
|
+
var held = Object.assign({}, out[at[run]], { menuLabel: String(list[i].label || ""),
|
|
157
|
+
menuAction: list[i].menuAction })
|
|
158
|
+
if (list[i].disabled === true) {
|
|
159
|
+
held.disabled = true
|
|
160
|
+
}
|
|
161
|
+
out[at[run]] = held
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return out
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// The row as the query reads it: the key row's wording when it matches, else the menu's wording that did.
|
|
168
|
+
function worded(row, needle) {
|
|
169
|
+
var label = String(row.label || "").toLowerCase()
|
|
170
|
+
var menuLabel = String(row.menuLabel || "")
|
|
171
|
+
if (label.indexOf(needle) < 0 && menuLabel.toLowerCase().indexOf(needle) >= 0) {
|
|
172
|
+
return Object.assign({}, row, { label: menuLabel })
|
|
173
|
+
}
|
|
174
|
+
return row
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Sample query: "down" matches "Open Downloads" but not "trash".
|
|
178
|
+
function rank(candidates, query) {
|
|
179
|
+
var needle = String(query || "").trim().toLowerCase()
|
|
180
|
+
var list = unique(candidates)
|
|
181
|
+
if (needle.length === 0) {
|
|
182
|
+
return list.slice(0, RESULT_LIMIT)
|
|
183
|
+
}
|
|
184
|
+
var exactPlace = []
|
|
185
|
+
var exact = []
|
|
186
|
+
var matched = []
|
|
187
|
+
var keyed = []
|
|
188
|
+
for (var i = 0; i < list.length; i++) {
|
|
189
|
+
var label = String(list[i].label || "").toLowerCase()
|
|
190
|
+
var menuLabel = String(list[i].menuLabel || "").toLowerCase()
|
|
191
|
+
var keys = String(list[i].keys || "").toLowerCase()
|
|
192
|
+
var name = String(list[i].name || "").toLowerCase()
|
|
193
|
+
// An exact NAME match ranks first, so "? trash Enter" opens Trash.
|
|
194
|
+
if (name.length > 0 && name === needle) {
|
|
195
|
+
exactPlace.push(list[i])
|
|
196
|
+
} else if (label === needle || menuLabel === needle) {
|
|
197
|
+
exact.push(worded(list[i], needle))
|
|
198
|
+
} else if (label.indexOf(needle) >= 0 || menuLabel.indexOf(needle) >= 0) {
|
|
199
|
+
matched.push(worded(list[i], needle))
|
|
200
|
+
} else if (keys.length > 0 && keys.indexOf(needle) >= 0) {
|
|
201
|
+
keyed.push(list[i])
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return withoutListedParents(exactPlace.concat(exact, matched, keyed).slice(0, RESULT_LIMIT))
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// A flyout parent whose leaves the bounded list shows is not itself a row; a key row, a leafless parent and a parent whose leaves the bound cut stay.
|
|
208
|
+
function withoutListedParents(rows) {
|
|
209
|
+
var listed = {}
|
|
210
|
+
for (var i = 0; i < rows.length; i++) {
|
|
211
|
+
if (String(rows[i].parentAction || "").length > 0) {
|
|
212
|
+
listed[rows[i].parentAction] = true
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return rows.filter(function (row) {
|
|
216
|
+
return !(row.section === 1 && !row.parentAction && listed[String(row.menuAction || "")] === true)
|
|
217
|
+
})
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Enter runs the highlighted row as its own surface would.
|
|
221
|
+
function dispatch(candidate) {
|
|
222
|
+
var row = candidate || {}
|
|
223
|
+
if (row.disabled === true) {
|
|
224
|
+
return { kind: "disabled" }
|
|
225
|
+
}
|
|
226
|
+
if (row.section === 0 && String(row.action || "").length > 0) {
|
|
227
|
+
return { kind: "action", action: String(row.action) }
|
|
228
|
+
}
|
|
229
|
+
if (row.section === 1 && String(row.menuAction || "").length > 0) {
|
|
230
|
+
if (row.danger === true) {
|
|
231
|
+
return { kind: "confirm", menuAction: String(row.menuAction) }
|
|
232
|
+
}
|
|
233
|
+
return { kind: "menu", menuAction: String(row.menuAction) }
|
|
234
|
+
}
|
|
235
|
+
if (row.section === 2 && row.entry) {
|
|
236
|
+
return { kind: "place", railIndex: row.railIndex, entry: row.entry }
|
|
237
|
+
}
|
|
238
|
+
if (row.section === 3 && String(row.path || "").length > 0) {
|
|
239
|
+
return { kind: "recent", path: String(row.path) }
|
|
240
|
+
}
|
|
241
|
+
return { kind: "none" }
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Enter skips the key gate, so Swap.swallows refuses listing actions here while allowing navigation.
|
|
245
|
+
function runAction(holder, action, close) {
|
|
246
|
+
if (Swap.swallows(holder.listInFlight, action)) {
|
|
247
|
+
holder.message(Swap.LOADING, false)
|
|
248
|
+
return
|
|
249
|
+
}
|
|
250
|
+
close()
|
|
251
|
+
if (holder.sheetAction) holder.sheetAction(action)
|
|
252
|
+
else Focus.dispatchAction(action, holder)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Every menu row resolves its rows through the snapshot, so it refuses while a listing is out, unlike navigations; the holder runs the row.
|
|
256
|
+
function runMenu(holder, menuAction, close) {
|
|
257
|
+
if (holder.listInFlight === true) {
|
|
258
|
+
holder.message(Swap.LOADING, false)
|
|
259
|
+
return
|
|
260
|
+
}
|
|
261
|
+
close()
|
|
262
|
+
holder.sheetMenuAction(menuAction)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Sample input: entries two favourites both labelled "src", decided with railIndex 1 answers 1.
|
|
266
|
+
// The rail rebuilds on its poll, so the row is resolved by the rail's own identity, never by label.
|
|
267
|
+
function placeIndex(entries, decided) {
|
|
268
|
+
var list = entries || []
|
|
269
|
+
var row = decided || {}
|
|
270
|
+
var want = Places.railIdentity(row.entry)
|
|
271
|
+
if (want.length === 0)
|
|
272
|
+
return -1
|
|
273
|
+
var at = Number(row.railIndex)
|
|
274
|
+
if (at >= 0 && at < list.length && Places.railIdentity(list[at]) === want)
|
|
275
|
+
return at
|
|
276
|
+
for (var i = 0; i < list.length; i++) {
|
|
277
|
+
if (Places.railIdentity(list[i]) === want)
|
|
278
|
+
return i
|
|
279
|
+
}
|
|
280
|
+
return -1
|
|
281
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// The pile file the bar plugin writes, read here for the Settings panel's Pinned list. Sample input:
|
|
4
|
+
// {"items":[{"path":"/home/gm/Invoices","name":"Invoices","folder":true,"pinned":true}]}
|
|
5
|
+
function pinned(text) {
|
|
6
|
+
var doc = {}
|
|
7
|
+
try {
|
|
8
|
+
doc = JSON.parse(String(text || "")) || {}
|
|
9
|
+
} catch (e) {
|
|
10
|
+
return []
|
|
11
|
+
}
|
|
12
|
+
var items = doc.items instanceof Array ? doc.items : []
|
|
13
|
+
var out = []
|
|
14
|
+
for (var i = 0; i < items.length; i++) {
|
|
15
|
+
if (items[i] && items[i].pinned === true && typeof items[i].path === "string") {
|
|
16
|
+
out.push({ path: items[i].path, name: leaf(items[i].path),
|
|
17
|
+
folder: items[i].folder === true, missing: items[i].missing === true })
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return out
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function leaf(path) {
|
|
24
|
+
var trimmed = String(path).replace(/\/+$/, "")
|
|
25
|
+
var at = trimmed.lastIndexOf("/")
|
|
26
|
+
return at < 0 ? trimmed : trimmed.substring(at + 1)
|
|
27
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// Slow-click rename shared by the list, grid and columns views: tap arms the pane timer, double click cancels, fire renames a still-held sole row.
|
|
4
|
+
var CLEARED = -2 // SlowClick.cancel's cleared value, read by Pane.qml's slowClickIndex.
|
|
5
|
+
|
|
6
|
+
// Pre-tap sole-selection fact the views capture before Tap.tapped selects for this tap.
|
|
7
|
+
function wasSoleSelection(pane, index) {
|
|
8
|
+
if (!pane || index < 0) return false
|
|
9
|
+
if (pane.selectionCount() !== 1 || !pane.isSelected(index)) return false
|
|
10
|
+
return pane.cursorIndex === index
|
|
11
|
+
}
|
|
12
|
+
// Whether this tap starts the timer; records every tap so a tap on another row re-arms.
|
|
13
|
+
function arm(pane, index, modifiers, now, interval, dragging, wasSole) {
|
|
14
|
+
var plain = (modifiers & (Qt.ControlModifier | Qt.ShiftModifier)) === 0
|
|
15
|
+
var drag = dragging === undefined ? pane.dragActive : dragging
|
|
16
|
+
var priorAt = pane.slowClickAt || 0
|
|
17
|
+
var priorIndex = pane.slowClickIndex === undefined ? CLEARED : pane.slowClickIndex
|
|
18
|
+
pane.slowClickAt = now
|
|
19
|
+
pane.slowClickIndex = index
|
|
20
|
+
if (!(index >= 0 && plain && pane.singleClick !== true && pane.clickRename !== false
|
|
21
|
+
&& pane.searchMode === "" && pane.renamingIndex < 0 && !pane.renamePending
|
|
22
|
+
&& pane.selectionBand === null && drag !== true))
|
|
23
|
+
return false
|
|
24
|
+
if (wasSole !== undefined) {
|
|
25
|
+
if (!wasSole) return false
|
|
26
|
+
} else if (!wasSoleSelection(pane, index)) {
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
return priorIndex === index && now - priorAt > interval
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// The timer firing renames only when the cursor and sole selection still hold the armed row.
|
|
33
|
+
function fire(pane, dragging) {
|
|
34
|
+
var index = pane.slowClickIndex
|
|
35
|
+
pane.slowClickIndex = CLEARED
|
|
36
|
+
if (index === undefined || index < 0) return false
|
|
37
|
+
if (pane.menuVisible === true) return false
|
|
38
|
+
var liveDrag = dragging === undefined ? pane.dragActive : dragging
|
|
39
|
+
if (liveDrag === true) return false
|
|
40
|
+
if (pane.renamingIndex >= 0 || pane.renamePending) return false
|
|
41
|
+
if (pane.singleClick === true || pane.clickRename === false) return false
|
|
42
|
+
if (pane.searchMode !== "" || pane.selectionBand !== null) return false
|
|
43
|
+
var picked = pane.selectedIndices()
|
|
44
|
+
if (picked.length !== 1 || picked[0] !== index || pane.cursorIndex !== index) return false
|
|
45
|
+
// The pointer chose this row, so the reveal carries context 0 and the list never moves under it.
|
|
46
|
+
pane.act("rename", 0, null, 0)
|
|
47
|
+
return true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// A second tap in time, or a tap failing the arm, disarms without renaming.
|
|
51
|
+
function cancel(pane) {
|
|
52
|
+
pane.slowClickIndex = CLEARED
|
|
53
|
+
}
|
package/ui/js/SlowOp.js
ADDED
package/ui/js/Sort.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
.import "DirSizes.js" as DirSizes
|
|
4
|
+
.import "FolderSorts.js" as FolderSorts
|
|
5
|
+
.import "RecentMode.js" as RecentMode
|
|
6
|
+
.import "Thumbs.js" as Thumbs
|
|
7
|
+
|
|
8
|
+
// What the header's click and the s and S keys do, taking ui/Pane.qml's root the way Nav.js and
|
|
9
|
+
// Ops.js do: the pane holds the state, this holds what the state does. ui/Backend.qml records the
|
|
10
|
+
// order the listing is actually in, because list re-sorts by name ascending and only this file
|
|
11
|
+
// changes it after that.
|
|
12
|
+
|
|
13
|
+
// The orders the backend can actually produce, in the order s steps through them, and the only keys
|
|
14
|
+
// that may move the recorded order. It is not the list of what gets refused: docs/protocol.md "sort"
|
|
15
|
+
// refuses every other key by name, and the backend is the one that says so, see ui/js/Errors.js, aliased from FolderSorts.ORDERS, the one key table.
|
|
16
|
+
var ORDERS = FolderSorts.ORDERS
|
|
17
|
+
|
|
18
|
+
// The three sort decisions, kept apart from what a pane does with them: the chooser makes the same ones over its narrower list.
|
|
19
|
+
|
|
20
|
+
// The sorted column reverses; any other starts ascending, the order the canvas header draws beside "Name".
|
|
21
|
+
function columnOrder(orders, by, desc, key) {
|
|
22
|
+
if (orders.indexOf(key) < 0)
|
|
23
|
+
return null
|
|
24
|
+
return { key: key, desc: by === key ? !desc : false }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Always ascending, column and direction separate; an outside order, a saved kind in the chooser, starts over at the first.
|
|
28
|
+
function nextOrder(orders, by) {
|
|
29
|
+
return { key: orders[(orders.indexOf(by) + 1) % orders.length], desc: false }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Whichever order the listing is in, offered or inherited: the user asked for the reverse of what they have.
|
|
33
|
+
function reverseOrder(by, desc) {
|
|
34
|
+
return { key: by, desc: !desc }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// An edit open or a rename pending holds the sort and commits an open edit; it applies once the rename settles.
|
|
38
|
+
function holdForRename(pane, request) {
|
|
39
|
+
if (!(pane.renamingIndex >= 0 || pane.renamePending)) return false
|
|
40
|
+
pane.pendingSort = request
|
|
41
|
+
if (pane.renamingIndex >= 0 && !pane.renamePending) pane.commitOpenRename()
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ui/Header.qml's click: only ORDERS leave this file except the forget row.
|
|
46
|
+
function column(pane, key) {
|
|
47
|
+
// The flyout's last row (issue 179) forgets the folder and lists it on the default.
|
|
48
|
+
// Recent stands on the root, so forgetting re-asks its history instead of listing the root over it.
|
|
49
|
+
if (key === "__default__") {
|
|
50
|
+
// Forgetting re-lists, so it holds like any other sort request.
|
|
51
|
+
if (holdForRename(pane, { forget: true })) return
|
|
52
|
+
if ((pane.recentMode || "").length > 0) {
|
|
53
|
+
RecentMode.run(pane, pane.recentPaths || [], pane.recentVisits, pane.recentMode)
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
if (pane.backend && pane.backend.forgetFolderSort)
|
|
57
|
+
pane.backend.forgetFolderSort(pane.path)
|
|
58
|
+
// A preserved pane skips the reset a list would do, so refresh here or it keeps its old order.
|
|
59
|
+
if (pane.backend && pane.backend.resetSort)
|
|
60
|
+
pane.backend.resetSort(pane.path)
|
|
61
|
+
pane.openWithoutHistory(pane.path)
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
// Unsupported columns remain labels rather than sending a sort the backend must refuse.
|
|
65
|
+
var order = columnOrder(ORDERS, pane.backend.sortBy, pane.backend.sortDesc, key)
|
|
66
|
+
if (order)
|
|
67
|
+
resort(pane, order.key, order.desc)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// s walks ORDERS so it never lands on a refusal-only column; an aimed click earns the reason, a walking key only noise.
|
|
71
|
+
function next(pane) {
|
|
72
|
+
var order = nextOrder(ORDERS, pane.backend.sortBy)
|
|
73
|
+
resort(pane, order.key, order.desc)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// S: the capital-is-the-variant pair g/G and j/J use.
|
|
77
|
+
function reverse(pane) {
|
|
78
|
+
var order = reverseOrder(pane.backend.sortBy, pane.backend.sortDesc)
|
|
79
|
+
resort(pane, order.key, order.desc)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// The request goes out for every key, so the refusal is the backend's alone. Only an order it will
|
|
83
|
+
// really produce moves the recorded one, or the mark would describe a listing that never changed.
|
|
84
|
+
function resort(pane, key, desc) {
|
|
85
|
+
if (holdForRename(pane, { key: key, desc: desc })) return
|
|
86
|
+
// Asking for the order the listing is already in would drop every row-indexed cache and put the
|
|
87
|
+
// cursor back to redraw the rows already on screen, so it is not asked for at all.
|
|
88
|
+
if (pane.backend.sortBy === key && pane.backend.sortDesc === desc) {
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
pane.backend.sort(key, desc)
|
|
92
|
+
if (ORDERS.indexOf(key) < 0) {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
pane.backend.sortBy = key
|
|
96
|
+
pane.backend.sortDesc = desc
|
|
97
|
+
// A walk's rows are matches, not the folder's, so sorting them writes nothing. Recent stands
|
|
98
|
+
// on the root, so its order is never remembered as the root's own.
|
|
99
|
+
if (pane.backend && pane.backend.rememberFolderSort
|
|
100
|
+
&& (pane.searchMode || "") === "" && (pane.recentMode || "") === "")
|
|
101
|
+
pane.backend.rememberFolderSort(pane.path, key, desc)
|
|
102
|
+
// A reorder moves every row, so the caches keyed by a row index are as stale as a new listing's,
|
|
103
|
+
// and a selection of row indices would silently come to name different files.
|
|
104
|
+
pane.thumbState = Thumbs.empty()
|
|
105
|
+
pane.dirSizeState = DirSizes.empty()
|
|
106
|
+
pane.clearSelection()
|
|
107
|
+
pane.setCursor(0)
|
|
108
|
+
// sort emits no rows of its own, so the reordered window is asked for here; see docs/protocol.md.
|
|
109
|
+
pane.backend.window(0, pane.windowSize)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// The held sort a resort deferred; runs when the edit ends or the listing lands.
|
|
113
|
+
function applyPending(pane) {
|
|
114
|
+
var held = pane.pendingSort
|
|
115
|
+
if (!held) return
|
|
116
|
+
// Not settled yet, or nowhere to send it: the hold stands.
|
|
117
|
+
if (pane.listInFlight || pane.renamingIndex >= 0 || pane.renamePending) return
|
|
118
|
+
if (!pane.backend || pane.backend.quitting || !pane.backend.running) { pane.pendingSort = null; return }
|
|
119
|
+
pane.pendingSort = null
|
|
120
|
+
if (held.forget) { column(pane, "__default__"); return }
|
|
121
|
+
resort(pane, held.key, held.desc)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Each flag is read the way its reader reads it, and state.sort stays as written because Pane.openWithoutHistory compares it with ViewState's own.
|
|
125
|
+
// Sample input: preferences({}) and preferences({hidden: false, foldersFirst: true, groupByKind: false, hiddenLast: false, rememberSort: true}) are the same string.
|
|
126
|
+
function preferences(state) {
|
|
127
|
+
return JSON.stringify([state.hidden === true, state.sort, state.foldersFirst !== false,
|
|
128
|
+
state.groupByKind === true, state.hiddenLast === true, state.rememberSort !== false])
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// A sorted column's title: the label and the geometric mark of the direction, characters the stock monospace has, so the mark scales with the font like the label.
|
|
132
|
+
function title(label, descending) {
|
|
133
|
+
return label + " " + (descending ? "\u25be" : "\u25b4")
|
|
134
|
+
}
|
package/ui/js/Startup.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// Where a window opens, and where a new tab opens. Both were fixed before 0.2.1: a window always
|
|
4
|
+
// opened on $HOME unless the command line named a path, and a new tab always cloned the folder the
|
|
5
|
+
// pane was resting on. Settings > View > Opening now decides, and this is the only place that reads
|
|
6
|
+
// those keys, so the panel, ui/shell.qml and ui/js/Tabs.js can never disagree about the answer.
|
|
7
|
+
|
|
8
|
+
// Sample state, as ui/ViewState.qml holds it:
|
|
9
|
+
// {startIn: "folder", startFolder: "/home/gm/Work", lastPath: "/home/gm/Pictures", newTab: "home"}
|
|
10
|
+
// argvPath is FLEA_PATH, which ui/shell.qml reads off the command line.
|
|
11
|
+
function startPath(state, home, argvPath) {
|
|
12
|
+
// A path the caller named outranks every setting: a file manager asked to open somewhere opens
|
|
13
|
+
// there, and this is the same precedence the --select flag already has over the remembered pair.
|
|
14
|
+
if (argvPath && String(argvPath).length > 0)
|
|
15
|
+
return String(argvPath)
|
|
16
|
+
var data = state || {}
|
|
17
|
+
var mode = data.startIn || "home"
|
|
18
|
+
if (mode === "last")
|
|
19
|
+
return orHome(data.lastPath, home)
|
|
20
|
+
if (mode === "folder")
|
|
21
|
+
return orHome(data.startFolder, home)
|
|
22
|
+
return home
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// A named folder goes to the focused side while the other keeps its own; launchSide says which took it.
|
|
26
|
+
// Sample dual state, as ui/ViewState.qml holds it: {paths: ["/home/gm", "/home/gm/Work"], focus: 1}.
|
|
27
|
+
function dualPaths(dual, start, argvPath) {
|
|
28
|
+
var saved = (dual || {}).paths || []
|
|
29
|
+
var named = argvPath && String(argvPath).length > 0 ? String(argvPath) : ""
|
|
30
|
+
// With no pair both sides open where one pane would, and a named folder outranks start here too.
|
|
31
|
+
if (saved.length !== 2) {
|
|
32
|
+
var only = named.length > 0 ? named : start
|
|
33
|
+
return { paths: [only, only], launchSide: named.length > 0 ? 0 : -1 }
|
|
34
|
+
}
|
|
35
|
+
if (named.length === 0)
|
|
36
|
+
return { paths: [String(saved[0]), String(saved[1])], launchSide: -1 }
|
|
37
|
+
if ((dual || {}).focus === 1)
|
|
38
|
+
return { paths: [String(saved[0]), named], launchSide: 1 }
|
|
39
|
+
return { paths: [named, String(saved[1])], launchSide: 0 }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// here is the folder the pane is resting on, which is what a new tab used to clone unconditionally.
|
|
43
|
+
function newTabPath(state, here, home) {
|
|
44
|
+
var mode = (state || {}).newTab || "current"
|
|
45
|
+
if (mode === "home")
|
|
46
|
+
return home
|
|
47
|
+
if (mode === "start")
|
|
48
|
+
return startPath(state, home, "")
|
|
49
|
+
return here
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// A chosen folder can be deleted or renamed between two runs, and a remembered one can be a stick
|
|
53
|
+
// that is no longer plugged in. Nothing here can stat a path, so an empty setting falls back to home
|
|
54
|
+
// and a path that no longer exists is left to the listing's own error, which names what is wrong.
|
|
55
|
+
function orHome(path, home) {
|
|
56
|
+
return path && String(path).length > 0 ? String(path) : home
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// How long a restored folder waits for its first listing before it stops loading.
|
|
60
|
+
var LISTING_WAIT_MS = 10000
|
|
61
|
+
|
|
62
|
+
// How long the favourite inspector waits for its answer before its guard clears anyway.
|
|
63
|
+
var INSPECT_WAIT_MS = 10000
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
.import "Format.js" as Format
|
|
4
|
+
|
|
5
|
+
// Permissions refusals keep their short state words; unavailable app rows use error ink alone.
|
|
6
|
+
var WORDS = {
|
|
7
|
+
permissionsLink: "symlink",
|
|
8
|
+
permissionsSpecial: "special file",
|
|
9
|
+
permissionsNotYours: "not yours"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// A link names itself; any other kind that is neither a file nor a folder is special, and a mode never read names nothing.
|
|
13
|
+
function permissions(mode) {
|
|
14
|
+
var kind = (Number(mode) || 0) & Format.S_IFMT
|
|
15
|
+
if (kind === 0) return ""
|
|
16
|
+
return kind === Format.S_IFLNK ? WORDS.permissionsLink : WORDS.permissionsSpecial
|
|
17
|
+
}
|