flea-qml 0.0.0-stage → 0.1.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 +478 -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 +402 -0
- package/src/archiveops.js +697 -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 +129 -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/transfer.js +669 -0
- package/src/trash-record.js +41 -0
- package/src/trash.js +210 -0
- package/src/trashbrowse.js +326 -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 +241 -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-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-html-security.mjs +23 -0
- package/test/manual-html-ui.mjs +30 -0
- package/test/manual-syntax-preview.mjs +26 -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 +68 -0
- package/ui/ArchiveCompressDialog.qml +378 -0
- package/ui/ArchivePasswordDialog.qml +257 -0
- package/ui/Backend.qml +771 -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 +523 -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 +115 -0
- package/ui/Pane.qml +1296 -0
- package/ui/PaneMenuActions.qml +527 -0
- package/ui/PanePath.qml +90 -0
- package/ui/PaneRail.qml +239 -0
- package/ui/PaneStates.qml +88 -0
- package/ui/PaneSwap.qml +339 -0
- package/ui/PaneWire.qml +605 -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 +1004 -0
- package/ui/PreviewAnimation.qml +24 -0
- package/ui/PreviewArchive.qml +66 -0
- package/ui/PreviewColumn.qml +551 -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 +38 -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 +732 -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/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 +827 -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 +122 -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 +364 -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 +502 -0
- package/ui/js/FolderSorts.js +108 -0
- package/ui/js/FolderViews.js +44 -0
- package/ui/js/Format.js +305 -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 +736 -0
- package/ui/js/Tags.js +134 -0
- package/ui/js/Taildrop.js +128 -0
- package/ui/js/Tap.js +174 -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 +81 -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 +228 -0
package/ui/Backend.qml
ADDED
|
@@ -0,0 +1,771 @@
|
|
|
1
|
+
import Quickshell
|
|
2
|
+
import Quickshell.Io
|
|
3
|
+
import QtQuick
|
|
4
|
+
import "js/DropDev.js" as DropDev
|
|
5
|
+
import "js/Messages.js" as Messages
|
|
6
|
+
import "js/FolderSorts.js" as FolderSorts
|
|
7
|
+
import "js/Swap.js" as Swap
|
|
8
|
+
import "js/FleaBin.js" as FleaBin
|
|
9
|
+
import "js/Find.js" as Find
|
|
10
|
+
import "js/HostClipboard.js" as HostClipboard
|
|
11
|
+
|
|
12
|
+
Item {
|
|
13
|
+
id: root
|
|
14
|
+
|
|
15
|
+
signal listed(int total, real readMs, real sortMs, string path, var changed, real gen)
|
|
16
|
+
// The listing directory's filesystem, straight off the listed line: a drag compares it against
|
|
17
|
+
// the dropped-on folder's own to tell a move within one volume from a copy across two.
|
|
18
|
+
property var dirDev: 0
|
|
19
|
+
// False when the listed directory cannot be written. A drag from it copies. Absent on an
|
|
20
|
+
// older reply stays true, which is the move that reply always described.
|
|
21
|
+
property bool dirWritable: true
|
|
22
|
+
// The device of each ancestor of the listing by path, as the backend last answered; a path missing here is unknown and copies. See docs/protocol.md "devs".
|
|
23
|
+
property var pathDevs: ({})
|
|
24
|
+
// The listing the ancestors were last asked for, so a re-read or a live search answer of the same folder asks nothing.
|
|
25
|
+
property string _devsFor: ""
|
|
26
|
+
// The drag and the folder rows the last drop-target devs ask named, so one drag asks one set once.
|
|
27
|
+
property string _dropAsked: ""
|
|
28
|
+
// A drag entering a pane asks the devices of the column folders that name none, since a peek row carries none; a known answer stands until the new one lands, so a later drag never re-says Copy first.
|
|
29
|
+
function askDropDevs(token, paths) {
|
|
30
|
+
var key = token + "\n" + paths.join("\n")
|
|
31
|
+
if (root.pickerOnly || paths.length === 0 || key === root._dropAsked) return
|
|
32
|
+
root._dropAsked = key
|
|
33
|
+
root.send({ c: "devs", paths: paths })
|
|
34
|
+
}
|
|
35
|
+
onListed: function(total, readMs, sortMs, path, changed, gen) {
|
|
36
|
+
var ancestors = DropDev.askPaths(path)
|
|
37
|
+
var asked = path + "\n" + root.dirDev
|
|
38
|
+
if (!root.pickerOnly && ancestors.length > 0 && asked !== root._devsFor) {
|
|
39
|
+
root.pathDevs = DropDev.without(root.pathDevs, ancestors)
|
|
40
|
+
root.send({ c: "devs", paths: ancestors })
|
|
41
|
+
}
|
|
42
|
+
root._devsFor = asked
|
|
43
|
+
}
|
|
44
|
+
// listing is the numbering the rows are in, 0 from a backend that does not say; see docs/protocol.md "listing".
|
|
45
|
+
signal rows(int start, var items, real ms, var kinds, real listing, real gen)
|
|
46
|
+
// The numbering of the rows the pane holds, which every row-indexed request names back; ui/PaneSwap.qml writes it.
|
|
47
|
+
property real heldListing: 0
|
|
48
|
+
property real firstRowsAt: 0
|
|
49
|
+
onRows: function(start, items, ms, kinds) {
|
|
50
|
+
if (root.firstRowsAt === 0 && items.length > 0) root.firstRowsAt = Date.now()
|
|
51
|
+
}
|
|
52
|
+
// mode rides only on a denied listing, the one failure a pane draws more than a sentence for.
|
|
53
|
+
signal failed(string where, string input, string message, int mode)
|
|
54
|
+
// Directive 71: LocalSend's own CLI answers on its own thread, so both legs arrive as their own line.
|
|
55
|
+
signal localSendPeers(var peers, string reason)
|
|
56
|
+
signal localSendSent(bool ok, string reason)
|
|
57
|
+
signal thumbed(int row, string file)
|
|
58
|
+
signal dirSized(int row, real bytes, bool partial)
|
|
59
|
+
// Sample input: {"t":"dirsizedone","cancelled":false}
|
|
60
|
+
signal dirSizeDone(bool cancelled)
|
|
61
|
+
signal tagStatesResult(var message)
|
|
62
|
+
signal settagged(var message)
|
|
63
|
+
signal searching(int total, int scanned, real ms)
|
|
64
|
+
signal searched(int total, int scanned, real ms, bool cancelled, real gen, bool walking)
|
|
65
|
+
// Copy/move support undo; extract uses the same activity card without an undo journal.
|
|
66
|
+
signal transferStarted(int id, int n, bool moving, bool extract)
|
|
67
|
+
signal transferProgress(int id, int index, string name, real bytes, real total, real scanned, string phase, string drive)
|
|
68
|
+
signal transferItem(int id, int index, string name, bool ok, string err)
|
|
69
|
+
// into rides only on a merge: the one merging folder, or the destination several folded into.
|
|
70
|
+
signal transferDone(int id, int ok, int failed, int skipped, bool cancelled, var retryPaths, bool durable, string note, int merged, int keptBoth, string into)
|
|
71
|
+
// The names a transfer would land on, asked first; ui/CollideHost.qml holds the transfer until it lands.
|
|
72
|
+
signal collisions(int id, int total, var names, bool mergeable)
|
|
73
|
+
// What files inside merging folders already exist, asked by one walk after Merge.
|
|
74
|
+
signal mergeCollisions(int id, int total, var names)
|
|
75
|
+
// The names a FAT destination cannot hold, answered in place of the collisions answer; see docs/protocol.md "fatnames".
|
|
76
|
+
signal fatnames(int id, var renames, string fstype, string volume)
|
|
77
|
+
// MenuAdditions040: Paste as links answers one line per request.
|
|
78
|
+
signal linked(int ok, int failed, int skipped, string note)
|
|
79
|
+
// MenuAdditions040: Show original reveals the link's target in its own folder.
|
|
80
|
+
signal linkTarget(string path, string directory, string name, int id)
|
|
81
|
+
// Linktarget ids rise forever, so a late reply never matches a new request.
|
|
82
|
+
property int linkTargetSeq: 0
|
|
83
|
+
function nextLinkTargetId() { return root.linkTargetSeq += 1 }
|
|
84
|
+
signal trashed(int ok, int failed, string reason)
|
|
85
|
+
signal renamed(bool ok, string path)
|
|
86
|
+
// A remote write past its deadline answers this first and its own reply later; see docs/protocol.md "slow".
|
|
87
|
+
signal slowOp(string op, string path, string msg)
|
|
88
|
+
// Bulk rename answers one line for the whole batch, which one undo reverses.
|
|
89
|
+
signal bulkRenamed(int ok, int unchanged)
|
|
90
|
+
signal made(bool ok, string path)
|
|
91
|
+
signal duplicated(bool ok, string path)
|
|
92
|
+
signal undone(string op, bool ok)
|
|
93
|
+
signal paths(var list)
|
|
94
|
+
signal located(var message)
|
|
95
|
+
signal trashResult(var message)
|
|
96
|
+
// flea-qml: the Trash's item count as the backend last reported it; -1 until it has.
|
|
97
|
+
property int trashCount: -1
|
|
98
|
+
property int trashRevision: 0
|
|
99
|
+
// flea-qml: a `places` line lands in the one store every rail reads, so the second pane's
|
|
100
|
+
// backend and the chooser's own name the same rows the first did.
|
|
101
|
+
function placesFound(places, volumes) { RailPlaces.found(places, volumes) }
|
|
102
|
+
signal permissionsResult(var message)
|
|
103
|
+
signal pickerResult(var message)
|
|
104
|
+
signal menuResult(var message)
|
|
105
|
+
signal formatsResult(var message)
|
|
106
|
+
signal redone(string op, bool ok)
|
|
107
|
+
signal redoStarted(int id, int n, string op)
|
|
108
|
+
signal metaResult(var message)
|
|
109
|
+
// The system clipboard for files, one line for set, get and clear alike.
|
|
110
|
+
signal clipResult(var message)
|
|
111
|
+
property int metaToken: 0
|
|
112
|
+
// The coloured lines of one slot's file or text, answered late with the token askCode returned.
|
|
113
|
+
signal codeResult(var message)
|
|
114
|
+
signal htmlResult(var message)
|
|
115
|
+
// Sample input: {"t":"markdownhtml","slot":"look","token":9,"state":"ready","html":"<!doctype html>..."}
|
|
116
|
+
signal markdownHtmlResult(var message)
|
|
117
|
+
signal figureResult(var message)
|
|
118
|
+
property int codeToken: 0
|
|
119
|
+
// The unified diff of two files, or the reason there is none, answered late with the token askCompare returned.
|
|
120
|
+
signal compareResult(var message)
|
|
121
|
+
property int compareToken: 0
|
|
122
|
+
// One counter numbers every PDF fetch, so two viewers never share an id.
|
|
123
|
+
property int pdfCopySeq: 0
|
|
124
|
+
signal meta(int row, int w, int h, int orient, real durationMs, int sampleRate, int entries, real unpacked, bool archiveFailed, var names, real lines, bool partial, bool linesFailed, string target, bool targetDir, string owner)
|
|
125
|
+
signal shebang(string path, bool hasShebang, int id)
|
|
126
|
+
// A PDF fetched into a session-private copy under a deadline; err names the refusal, stalled is the wait that ran out.
|
|
127
|
+
signal pdfCopied(int id, string path, string err, bool stalled)
|
|
128
|
+
// A font's facts and three sample files, or err; ui/FontPane.qml builds the request, see src/backend/fontinfo/render.rs.
|
|
129
|
+
signal fontLooked(var message)
|
|
130
|
+
signal fsInfo(string fs, real free, string path, string storageClass, bool tagable, bool systemVolume)
|
|
131
|
+
// The one line no request asked for: the directory the current listing came from changed under
|
|
132
|
+
// it. path is that directory, so a pane that has since moved can ignore it; see docs/protocol.md.
|
|
133
|
+
signal changed(string path)
|
|
134
|
+
// The open mount went away: parent is the nearest existing folder, so the pane moves there.
|
|
135
|
+
signal unmounted(string path, string parent)
|
|
136
|
+
// readFailed tells an unreadable directory from an empty one (mode 0 when its stat failed too); hidden, hiddenLast, first, by and desc echo the request, so each of the three peek clients knows its own reply.
|
|
137
|
+
signal peeked(string path, bool hidden, int total, var rows, bool readFailed, int mode, bool hiddenLast, int first, var dev, var writable, string by, bool desc)
|
|
138
|
+
// The path bar's folder jump, the existing folders of each source in its own order; see docs/protocol.md "jump".
|
|
139
|
+
signal jumped(int id, var favourites, var zoxide, var recent, var frecency)
|
|
140
|
+
signal archiveStarted(int id)
|
|
141
|
+
signal archiveDone(int id, bool ok, bool verified, string err, string path, string dest)
|
|
142
|
+
signal convertChecked(var message)
|
|
143
|
+
signal convertStarted(int id, int requestId, string source)
|
|
144
|
+
signal convertDone(int id, bool ok, string path, string err, int requestId, string source, bool collision)
|
|
145
|
+
// Flash image: one image classified, every eligible drive, one flash at a time per backend.
|
|
146
|
+
signal flashImageResult(var message)
|
|
147
|
+
signal flashTargetsResult(var message)
|
|
148
|
+
signal flashStartedLine(int id, real total, bool known)
|
|
149
|
+
signal flashProgressLine(int id, string phase, real bytes, real total, real permille)
|
|
150
|
+
signal flashDoneLine(var message)
|
|
151
|
+
signal flashEjectLine(var message)
|
|
152
|
+
// The shell's exit gate: the backend has drained and this process can end.
|
|
153
|
+
signal quitReady()
|
|
154
|
+
|
|
155
|
+
// Capabilities arrive at launch and refresh at explicit menu and provider-action entry.
|
|
156
|
+
// The compress submenu is exactly this list, so a box with no 7zip never shows .7z.
|
|
157
|
+
property var archiveFormats: []
|
|
158
|
+
property bool canConvert: false
|
|
159
|
+
property var extraction: ({archive: false, sevenZip: false, zip: false})
|
|
160
|
+
property var providers: ({})
|
|
161
|
+
property int formatsToken: 0
|
|
162
|
+
|
|
163
|
+
readonly property bool running: child.running
|
|
164
|
+
|
|
165
|
+
// What order the current listing is actually in, which is what ui/Header.qml's mark draws.
|
|
166
|
+
// Only two things move it: list re-sorts by name ascending below, and an accepted sort, which
|
|
167
|
+
// ui/js/Sort.js records here because it is the one place that knows which keys are accepted.
|
|
168
|
+
property string sortBy: "name"
|
|
169
|
+
property bool sortDesc: false
|
|
170
|
+
property bool preserveSort: false
|
|
171
|
+
property bool hasListed: false
|
|
172
|
+
// The path the last list request named, so a settings change re-reads that folder's own order.
|
|
173
|
+
property string lastListedPath: ""
|
|
174
|
+
readonly property string sortPreference: JSON.stringify(ViewState.state.sort || {})
|
|
175
|
+
onSortPreferenceChanged: if (!root.preserveSort || !root.hasListed) root.resetSort(root.lastListedPath)
|
|
176
|
+
|
|
177
|
+
function resetSort(path) {
|
|
178
|
+
// Read once per listing, so browsing never writes; only Sort.resort does.
|
|
179
|
+
var order = FolderSorts.orderFor(ViewState.state.folderSorts, path,
|
|
180
|
+
ViewState.state.sort, ViewState.state.rememberSort !== false, UserDirs.newestFolders)
|
|
181
|
+
root.sortBy = order.key === "date" ? "mtime" : order.key
|
|
182
|
+
root.sortDesc = order.reverse === true
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Whether the Sort by flyout offers its forget row for this folder.
|
|
186
|
+
function folderHasSort(path) {
|
|
187
|
+
return ViewState.state.rememberSort !== false && FolderSorts.has(ViewState.state.folderSorts, path)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// A user sort writes its folder and moves it to the most recent end; past 500 the oldest goes.
|
|
191
|
+
function rememberFolderSort(path, key, desc) {
|
|
192
|
+
if (!FolderSorts.shouldRemember(ViewState.state.rememberSort, path))
|
|
193
|
+
return
|
|
194
|
+
var keyed = key === "mtime" ? "date" : key
|
|
195
|
+
var leaf = {}
|
|
196
|
+
leaf[path] = { key: keyed, reverse: desc === true }
|
|
197
|
+
ViewState.changeMapEntries("folderSorts", leaf, FolderSorts.set(ViewState.state.folderSorts, path, keyed, desc === true))
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function forgetFolderSort(path) {
|
|
201
|
+
if (!path)
|
|
202
|
+
return
|
|
203
|
+
var leaf = {}
|
|
204
|
+
leaf[path] = null
|
|
205
|
+
ViewState.changeMapEntries("folderSorts", leaf, FolderSorts.forget(ViewState.state.folderSorts, path))
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// What the settle gate asserts: how many thumb requests this process has attempted; see AGENTS.md.
|
|
209
|
+
property int thumbRequests: 0
|
|
210
|
+
// Same gate, for dirsize: a fling must issue none of these either.
|
|
211
|
+
property int dirSizeRequests: 0
|
|
212
|
+
// Same idiom again, for the watched re-read: a debt owed by the directory the pane has left must
|
|
213
|
+
// cost the one it arrived in no listing at all, which only a count can say; see tests/ui.sh watch.
|
|
214
|
+
property int listRequests: 0
|
|
215
|
+
|
|
216
|
+
// A write before the child is spawned is dropped silently, so an early request waits here.
|
|
217
|
+
property var pending: []
|
|
218
|
+
property bool queueing: true
|
|
219
|
+
|
|
220
|
+
// A quit is in flight, so the child's exit is the end the shell asked for, not a failure.
|
|
221
|
+
property bool quitting: false
|
|
222
|
+
// Only the portal chooser opts in: it has no filesystem write operations to drain.
|
|
223
|
+
property bool pickerOnly: false
|
|
224
|
+
|
|
225
|
+
// One of two writers: the chooser's listing worker builds its own list, listpaths and window lines.
|
|
226
|
+
function send(object) {
|
|
227
|
+
// The chooser opts out of writes, so a dropped command names the command it refused.
|
|
228
|
+
if (root.pickerOnly && object.c !== "picker" && object.c !== "formats") { console.warn("Backend refused command " + object.c); return }
|
|
229
|
+
// Every request that names rows names the numbering they were read in, its caller's if it read them earlier; src/backend/rowguard.rs refuses a stale one.
|
|
230
|
+
var line = JSON.stringify(Swap.named(object, root.heldListing)) + "\n"
|
|
231
|
+
if (root.queueing) {
|
|
232
|
+
// A password is never parked while the child starts; it fails as its own operation, naming its archive, not a dead backend.
|
|
233
|
+
if (object.password === undefined) root.pending.push(line)
|
|
234
|
+
else root.failed("archive", object.path !== undefined ? object.path : object.dest, "the backend is not running", 0)
|
|
235
|
+
return
|
|
236
|
+
}
|
|
237
|
+
if (!child.running) {
|
|
238
|
+
root.failed("backend", "", "the backend is not running", 0)
|
|
239
|
+
return
|
|
240
|
+
}
|
|
241
|
+
child.write(line)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// One composition, two senders: the chooser adds the caller's filter to it and counts its own
|
|
245
|
+
// replies, and issue 134 was the chooser building this by hand without the saved order in it.
|
|
246
|
+
// A fresh scan is always name ascending, so a refresh after a write puts the header's mark back.
|
|
247
|
+
function listRequest(path, first, hidden, wantChanged, select) {
|
|
248
|
+
root.listRequests += 1
|
|
249
|
+
root.lastListedPath = path
|
|
250
|
+
if (!root.preserveSort || !root.hasListed) root.resetSort(path)
|
|
251
|
+
root.hasListed = true
|
|
252
|
+
return { c: "list", path: path, first: first, hidden: hidden, wantChanged: wantChanged === true, by: root.sortBy, desc: root.sortDesc,
|
|
253
|
+
foldersFirst: ViewState.state.foldersFirst !== false, groupByKind: ViewState.state.groupByKind === true,
|
|
254
|
+
hiddenLast: ViewState.state.hiddenLast === true, select: select || undefined }
|
|
255
|
+
}
|
|
256
|
+
function list(path, first, hidden, wantChanged, select) { root.send(root.listRequest(path, first, hidden, wantChanged, select)) }
|
|
257
|
+
|
|
258
|
+
// A listing built from the paths named here, in that order and never sorted; see
|
|
259
|
+
// docs/protocol.md "listpaths". The header's sort mark is left where the caller set it, because
|
|
260
|
+
// this listing is in neither of the orders that mark can describe.
|
|
261
|
+
function listPaths(paths, first) {
|
|
262
|
+
root.send({ c: "listpaths", paths: paths, first: first })
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function window(start, count) {
|
|
266
|
+
root.send({ c: "window", start: start, count: count })
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function sort(by, desc) {
|
|
270
|
+
root.send({ c: "sort", by: by, desc: desc,
|
|
271
|
+
foldersFirst: ViewState.state.foldersFirst !== false,
|
|
272
|
+
groupByKind: ViewState.state.groupByKind === true,
|
|
273
|
+
hiddenLast: ViewState.state.hiddenLast === true })
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// flea-qml: Find runs `find SCOPE -iname PATTERN` itself rather than asking the backend to walk.
|
|
277
|
+
// The backend only names the command (a `findcommand` line: bunmsh beside the repository, then
|
|
278
|
+
// bunmsh on PATH, then the system find) and turns the paths into rows through `listpaths`, so
|
|
279
|
+
// every per-row facility keeps working. The paths stream in, a batch every findFlush interval;
|
|
280
|
+
// SIGINT stops a run and keeps what it printed. The four functions keep upstream's names and
|
|
281
|
+
// meanings, so ui/js/Search.js is unchanged in what it asks.
|
|
282
|
+
property var findArgv: null
|
|
283
|
+
// flea-qml: Ctrl+G's content search runs this grep instead (findcommand's `grep`).
|
|
284
|
+
property var grepArgv: null
|
|
285
|
+
// Whether the running walk is a content search, its matches beside findBatch, and the files
|
|
286
|
+
// already answered: -o can print several snippets of a file's one matching line.
|
|
287
|
+
property bool findContents: false
|
|
288
|
+
property var findMatches: []
|
|
289
|
+
property var findSeen: ({})
|
|
290
|
+
property string findScope: ""
|
|
291
|
+
property string findFolder: ""
|
|
292
|
+
property bool findHidden: false
|
|
293
|
+
property int findCount: 0
|
|
294
|
+
property real findGen: 0
|
|
295
|
+
property real findStarted: 0
|
|
296
|
+
property bool findCancelled: false
|
|
297
|
+
// The query waiting for the running find to stop: {query, gen}, or null.
|
|
298
|
+
property var findPending: null
|
|
299
|
+
property var findBatch: []
|
|
300
|
+
property bool findClosing: false
|
|
301
|
+
|
|
302
|
+
// Opens the scope; the next query walks it.
|
|
303
|
+
function searchOpen(scope, folder, hidden) {
|
|
304
|
+
root.findScope = scope
|
|
305
|
+
root.findFolder = folder
|
|
306
|
+
root.findHidden = hidden === true
|
|
307
|
+
root.findPending = null
|
|
308
|
+
root.stopFind(true)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Each query is one find; a newer one stops the older first and starts once it has exited.
|
|
312
|
+
function searchQuery(query, gen, count, sizes, contents) {
|
|
313
|
+
root.findCount = count
|
|
314
|
+
root.findPending = { query: String(query || ""), gen: gen, contents: contents === true }
|
|
315
|
+
if (finder.running) { root.findClosing = true; finder.signal(2); return }
|
|
316
|
+
root.startFind()
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function searchClose() {
|
|
320
|
+
root.findPending = null
|
|
321
|
+
root.stopFind(true)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Esc while it runs: SIGINT, and the results found so far stay as the answer.
|
|
325
|
+
function searchCancel() {
|
|
326
|
+
if (!finder.running) return
|
|
327
|
+
root.findCancelled = true
|
|
328
|
+
finder.signal(2)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function stopFind(closing) {
|
|
332
|
+
if (!finder.running) return
|
|
333
|
+
root.findClosing = closing
|
|
334
|
+
finder.signal(2)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function startFind() {
|
|
338
|
+
var next = root.findPending
|
|
339
|
+
root.findPending = null
|
|
340
|
+
if (!next) return
|
|
341
|
+
root.findGen = next.gen
|
|
342
|
+
root.findCancelled = false
|
|
343
|
+
root.findClosing = false
|
|
344
|
+
root.findBatch = []
|
|
345
|
+
root.findMatches = []
|
|
346
|
+
root.findSeen = ({})
|
|
347
|
+
root.findContents = next.contents === true
|
|
348
|
+
root.findStarted = Date.now()
|
|
349
|
+
var done = { scanned: 0, ms: 0, cancelled: false, walking: false }
|
|
350
|
+
// An emptied query is the folder itself again.
|
|
351
|
+
if (next.query.length === 0) {
|
|
352
|
+
var listing = root.listRequest(root.findFolder, root.findCount, root.findHidden)
|
|
353
|
+
listing.gen = next.gen
|
|
354
|
+
listing.searched = done
|
|
355
|
+
root.send(listing)
|
|
356
|
+
return
|
|
357
|
+
}
|
|
358
|
+
var argv = root.findContents ? root.grepArgv : root.findArgv
|
|
359
|
+
if (!argv || root.findScope.length === 0) {
|
|
360
|
+
root.send({ c: "listpaths", base: root.findScope || "/", paths: [], first: root.findCount, gen: next.gen, searched: done })
|
|
361
|
+
return
|
|
362
|
+
}
|
|
363
|
+
// The old rows go at once; the first batch appends to this empty listing.
|
|
364
|
+
root.send({ c: "listpaths", base: root.findScope, paths: [], first: root.findCount, gen: next.gen })
|
|
365
|
+
// Hidden folders are pruned rather than filtered, so find never walks into .cache or .git;
|
|
366
|
+
// grep skips the same names unless hidden files are shown.
|
|
367
|
+
finder.workingDirectory = root.findScope
|
|
368
|
+
finder.command = root.findContents
|
|
369
|
+
? argv.concat(Find.grepArguments(next.query, root.findHidden))
|
|
370
|
+
: argv.concat(["."], Find.expression(next.query, root.findHidden))
|
|
371
|
+
finder.running = true
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function flushFind(last) {
|
|
375
|
+
if (root.findBatch.length === 0 && !last) return
|
|
376
|
+
var request = { c: "listpaths", base: root.findScope, paths: root.findBatch, first: root.findCount, gen: root.findGen, append: true }
|
|
377
|
+
if (root.findContents) request.matches = root.findMatches
|
|
378
|
+
// Every batch ends with a terminal line, walking until the last, as upstream's live answers
|
|
379
|
+
// do: that is what moves the count and lands the rows while the find still runs.
|
|
380
|
+
request.searched = { scanned: 0, ms: Date.now() - root.findStarted, cancelled: last && root.findCancelled, walking: !last }
|
|
381
|
+
root.findBatch = []
|
|
382
|
+
root.findMatches = []
|
|
383
|
+
root.send(request)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
Process {
|
|
387
|
+
id: finder
|
|
388
|
+
stdout: SplitParser {
|
|
389
|
+
onRead: function (line) {
|
|
390
|
+
if (root.findClosing) return
|
|
391
|
+
if (root.findContents) {
|
|
392
|
+
// One row per file: the first snippet of its matching line.
|
|
393
|
+
var hit = Find.grepLine(line)
|
|
394
|
+
if (!hit || root.findSeen[hit.path] === true) return
|
|
395
|
+
root.findSeen[hit.path] = true
|
|
396
|
+
root.findBatch.push(hit.path)
|
|
397
|
+
root.findMatches.push({ l: hit.line, t: hit.text })
|
|
398
|
+
return
|
|
399
|
+
}
|
|
400
|
+
var path = String(line)
|
|
401
|
+
if (path.length > 0 && path !== ".") root.findBatch.push(path)
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
stderr: StdioCollector {}
|
|
405
|
+
onExited: function (code, status) {
|
|
406
|
+
findFlush.stop()
|
|
407
|
+
// A run stopped for a newer query or a close answers nothing; one that ended or was cancelled lands.
|
|
408
|
+
if (!root.findClosing) root.flushFind(true)
|
|
409
|
+
root.findClosing = false
|
|
410
|
+
root.startFind()
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
Timer {
|
|
414
|
+
id: findFlush
|
|
415
|
+
// A batch re-lands the first window, which costs a slow renderer a full redraw; once a second
|
|
416
|
+
// keeps the stream moving without spending the run on redraws.
|
|
417
|
+
interval: 1000
|
|
418
|
+
repeat: true
|
|
419
|
+
running: finder.running
|
|
420
|
+
onTriggered: root.flushFind(false)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// rows, not paths: a client can only build a path for a row inside the window it holds, and a
|
|
424
|
+
// selection can be wider than that; the backend resolves them at request time, see docs/protocol.md.
|
|
425
|
+
function transfer(op, rows, dest) {
|
|
426
|
+
if (rows.length === 0) {
|
|
427
|
+
return
|
|
428
|
+
}
|
|
429
|
+
root.send({ c: "transfer", op: op, rows: rows, dest: dest })
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function transfercancel(id) {
|
|
433
|
+
root.send({ c: "transfercancel", id: id })
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function trash(rows, menuId) {
|
|
437
|
+
if (rows.length === 0) {
|
|
438
|
+
return
|
|
439
|
+
}
|
|
440
|
+
root.send({ c: "trash", rows: rows, menuId: menuId || 0 })
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function rename(path, to, menuId) {
|
|
444
|
+
root.send({ c: "rename", path: path, to: to, menuId: menuId || 0 })
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Parallel paths and bare new names, validated whole before any rename.
|
|
448
|
+
function bulkRename(paths, names) {
|
|
449
|
+
if (paths.length === 0 || paths.length !== names.length) {
|
|
450
|
+
return
|
|
451
|
+
}
|
|
452
|
+
root.send({ c: "bulkrename", paths: paths, names: names })
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function duplicate(path, menuId) {
|
|
456
|
+
root.send({ c: "duplicate", path: path, menuId: menuId || 0 })
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// No name field: omitting it is what makes the backend take the first free "New Folder", so the
|
|
460
|
+
// client needs no retry loop and no collision handling; see docs/protocol.md "mkdir".
|
|
461
|
+
function mkdir(path) {
|
|
462
|
+
root.send({ c: "mkdir", path: path })
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function undo() {
|
|
466
|
+
root.send({ c: "undo" })
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function redo() { root.send({ c: "redo" }) }
|
|
470
|
+
|
|
471
|
+
// Resolves indices to absolute paths, so a clipboard can hold a selection wider than the window.
|
|
472
|
+
function askPaths(rows) {
|
|
473
|
+
root.send({ c: "paths", rows: rows })
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// One row, only when a surface asks: the same no-sweep rule thumb and dirsize already follow.
|
|
477
|
+
// media and archive each cost a subprocess in the backend, so each is only ever true for a row
|
|
478
|
+
// whose kind actually names the facts it would answer.
|
|
479
|
+
// One document, only when a surface asks: the same no-sweep rule thumb and dirsize follow.
|
|
480
|
+
// The id is minted here and returned, so the viewer matches the answer it asked for.
|
|
481
|
+
function pdfCopy(path, slot) {
|
|
482
|
+
root.pdfCopySeq += 1
|
|
483
|
+
root.send({ c: "pdfcopy", id: root.pdfCopySeq, slot: slot || "", path: path })
|
|
484
|
+
return root.pdfCopySeq
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
function askMeta(row, text, media, archive) {
|
|
488
|
+
root.metaToken += 1
|
|
489
|
+
root.send({ c: "meta", row: row, text: text, media: media, archive: archive, token: root.metaToken })
|
|
490
|
+
return root.metaToken
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// source is {path} for a file the backend opens or {text, name, lang} for bytes the UI holds; a newer ask on a slot ends the older one.
|
|
494
|
+
function askCode(slot, source, first, count) {
|
|
495
|
+
root.codeToken += 1
|
|
496
|
+
root.send(Object.assign({ c: "code", token: root.codeToken, slot: slot, first: first, count: count }, source))
|
|
497
|
+
return root.codeToken
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// A Markdown file as one passive page for WebPreview; theme holds the page's #rrggbb colours and body size.
|
|
501
|
+
// One Mermaid diagram (src/figure.js); the answer comes back as figureResult with this id.
|
|
502
|
+
property int figureSeq: 0
|
|
503
|
+
function askFigure(source, theme) {
|
|
504
|
+
root.figureSeq += 1
|
|
505
|
+
root.send({ c: "figure", id: root.figureSeq, source: source, theme: theme })
|
|
506
|
+
return root.figureSeq
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function askMarkdownHtml(slot, path, theme) {
|
|
510
|
+
root.codeToken += 1
|
|
511
|
+
root.send({ c: "markdownhtml", token: root.codeToken, slot: slot, path: path, theme: theme })
|
|
512
|
+
return root.codeToken
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function askHtml(slot, path, width, cancel, height) {
|
|
516
|
+
root.codeToken += 1
|
|
517
|
+
var message = { c: "html", token: root.codeToken, slot: slot, path: path, width: width, cancel: cancel }
|
|
518
|
+
if (height > 0) message.height = height
|
|
519
|
+
root.send(message)
|
|
520
|
+
return root.codeToken
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function askCompare(a, b) {
|
|
524
|
+
root.compareToken += 1
|
|
525
|
+
root.send({ c: "compare", token: root.compareToken, a: a, b: b })
|
|
526
|
+
return root.compareToken
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function askFsInfo() {
|
|
530
|
+
root.send({ c: "fsinfo" })
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// A read-only look elsewhere; Tab passes hiddenLast false, other callers keep the listing order, and only a column passes keep, the directories drawn, and its folder's own remembered order.
|
|
534
|
+
function peek(path, first, hidden, hiddenLast, keep) {
|
|
535
|
+
var last = hiddenLast === undefined ? ViewState.state.hiddenLast === true : hiddenLast === true
|
|
536
|
+
var order = FolderSorts.peekOrder(ViewState.state.folderSorts, path, ViewState.state.rememberSort, keep, UserDirs.newestFolders, ViewState.state.sort)
|
|
537
|
+
root.send({ c: "peek", path: path, first: first, hidden: hidden, hiddenLast: last, watch: Array.isArray(keep), keep: keep, by: order.by, desc: order.desc })
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// op is "peers" for the flyout's list and "send" for the transfer it chooses; both answer late.
|
|
541
|
+
// Once per open of the path bar: the client's favourites and recent files, joined there with zoxide; id comes back on the answer.
|
|
542
|
+
function jump(id, ranking, favourites, recent) {
|
|
543
|
+
var message = { c: "jump", id: id, favourites: favourites, recent: recent }
|
|
544
|
+
// A whole ask names its provisional ask so the backend runs zoxide once for the open; any other ask names none.
|
|
545
|
+
if (ranking !== 0) message.ranking = ranking
|
|
546
|
+
root.send(message)
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function localSend(op, peer, paths) {
|
|
550
|
+
root.send({ c: "localsend", op: op, peer: peer, paths: paths, id: ++root.formatsToken })
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function askFormats() {
|
|
554
|
+
root.send({ c: "formats", id: ++root.formatsToken })
|
|
555
|
+
return root.formatsToken
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// paths are absolute and share a parent, which is what a selection from one listing is.
|
|
559
|
+
function compress(paths, dest, format, menuId) {
|
|
560
|
+
root.send({ c: "archive", op: "compress", paths: paths, dest: dest, format: format, menuId: menuId || 0 })
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// The With-password compress: the secret rides this wire and leaves it only on 7z's stdin pipe.
|
|
564
|
+
function compressPassword(paths, dest, format, password, encryptNames, menuId) {
|
|
565
|
+
root.send({ c: "archive", op: "compress", paths: paths, dest: dest, format: format,
|
|
566
|
+
password: password, encryptNames: encryptNames === true, menuId: menuId || 0 })
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function extract(path, dest, menuId) {
|
|
570
|
+
root.send({ c: "archive", op: "extract", path: path, dest: dest, menuId: menuId || 0 })
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// The extract card's retry with a password, over the same destination the first attempt named.
|
|
574
|
+
function extractPassword(path, dest, password, menuId) {
|
|
575
|
+
root.send({ c: "archive", op: "extract", path: path, dest: dest, password: password, menuId: menuId || 0 })
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// No format field: magick reads the codec off dest's own extension, see docs/protocol.md "convert".
|
|
579
|
+
function convertImage(path, dest, strip, menuId, requestId, check) {
|
|
580
|
+
root.send({ c: "convert", path: path, dest: dest, strip: strip, menuId: menuId || 0,
|
|
581
|
+
requestId: requestId || 0, check: check === true })
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// Flash image: the identity fields ride the flash request so the backend re-checks the drive it showed.
|
|
585
|
+
function flashImage(path) {
|
|
586
|
+
root.send({ c: "flashimage", path: path })
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
function flashTargets(image) {
|
|
590
|
+
root.send({ c: "flashtargets", image: image || "" })
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
function flash(id, image, dev, seq, serial, bytes) {
|
|
594
|
+
root.send({ c: "flash", id: id, image: image, dev: dev, seq: seq, serial: serial, bytes: bytes })
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
function flashCancel(id) {
|
|
598
|
+
root.send({ c: "flashcancel", id: id })
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
function flashEject(dev, seq) {
|
|
602
|
+
root.send({ c: "flasheject", dev: dev, seq: seq })
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
function thumb(rows, cacheOnly) {
|
|
606
|
+
if (rows.length === 0) {
|
|
607
|
+
return
|
|
608
|
+
}
|
|
609
|
+
root.thumbRequests += 1
|
|
610
|
+
root.send({ c: "thumb", rows: rows, cacheOnly: cacheOnly === true })
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// An empty rows cancels EVERYTHING queued, so an empty list is never sent; see docs/protocol.md.
|
|
614
|
+
function thumbcancel(rows) {
|
|
615
|
+
if (rows.length === 0) {
|
|
616
|
+
return
|
|
617
|
+
}
|
|
618
|
+
root.send({ c: "thumbcancel", rows: rows })
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// An eject releases the volume, so queued thumbnail and size work stops before the unmount.
|
|
622
|
+
function quiesce() {
|
|
623
|
+
root.send({ c: "thumbcancel", rows: [] })
|
|
624
|
+
root.send({ c: "dirsizecancel" })
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
function dirsize(rows) {
|
|
628
|
+
if (rows.length === 0) {
|
|
629
|
+
return
|
|
630
|
+
}
|
|
631
|
+
root.dirSizeRequests += 1
|
|
632
|
+
root.send({ c: "dirsize", rows: rows })
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// The Size header's ⚖️: every folder in the listing, in the backend's own numbering.
|
|
636
|
+
function dirsizeAll() {
|
|
637
|
+
root.dirSizeRequests += 1
|
|
638
|
+
root.send({ c: "dirsize", all: true })
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// Unlike thumbcancel, dirsizecancel carries no rows: it always means everything queued, see docs/protocol.md.
|
|
642
|
+
function dirsizecancel() {
|
|
643
|
+
root.send({ c: "dirsizecancel" })
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// The shell's last request, see docs/protocol.md "quit". The backend cancels the running
|
|
647
|
+
// operation as it drains, and a cancelled copy removes its own partial destination, so waiting
|
|
648
|
+
// for quitReady is what keeps a close from leaving a half-written file under the final name.
|
|
649
|
+
function quit() {
|
|
650
|
+
if (root.quitting) {
|
|
651
|
+
return
|
|
652
|
+
}
|
|
653
|
+
root.quitting = true
|
|
654
|
+
if (root.pickerOnly) {
|
|
655
|
+
root.pending = []
|
|
656
|
+
if (child.running) child.signal(9)
|
|
657
|
+
else root.quitReady()
|
|
658
|
+
return
|
|
659
|
+
}
|
|
660
|
+
// Before the child is up a quit would only join the pending queue and never be written,
|
|
661
|
+
// and nothing can be in flight yet, so there is nothing to drain and the shell goes now.
|
|
662
|
+
if (root.queueing || !child.running) {
|
|
663
|
+
root.quitReady()
|
|
664
|
+
return
|
|
665
|
+
}
|
|
666
|
+
root.send({ c: "quit" })
|
|
667
|
+
quitDeadline.start()
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// Sample input: {"t":"rows","start":0,"rows":[{"n":"a.txt","d":false,"s":3,"m":1787790423,"p":33188,"i":"text-x-generic","t":false,"k":0}],"kinds":["Plain text document"],"ms":1.250}
|
|
671
|
+
// Sample input: {"t":"thumbed","row":2,"file":"/home/gm/.cache/thumbnails/large/b98fa4.png","ms":75.823}
|
|
672
|
+
// Sample input: {"t":"dirsized","row":4,"bytes":1048576,"partial":false,"ms":12.500}
|
|
673
|
+
// Sample input: {"t":"settagged","ok":2,"op":"remove"}
|
|
674
|
+
// Sample input: {"t":"settagged","ok":2,"op":"add","skipped":["c.lnk"]}
|
|
675
|
+
// Sample input: {"t":"tagstates","id":3,"applied":["Red"],"mixed":["Blue"],"listing":7}
|
|
676
|
+
// Sample input: {"t":"searching","n":812,"scanned":41200,"ms":300.114}
|
|
677
|
+
// Sample input: {"t":"changed","path":"/home/gm/Downloads"}
|
|
678
|
+
// Sample input: {"t":"unmounted","path":"/media/stick","parent":"/media"}
|
|
679
|
+
// Sample input: {"t":"transferstarted","id":12,"n":2,"moving":true}
|
|
680
|
+
// Sample input: {"t":"transferstarted","id":12,"n":1,"moving":false,"extract":true}
|
|
681
|
+
// Sample input: {"t":"transferprogress","id":12,"index":0,"name":"a.txt","bytes":40000000,"total":120000000,"scanned":8400000000}
|
|
682
|
+
// Sample input: {"t":"transferprogress","id":12,"index":0,"name":"","bytes":0,"total":0,"scanned":0,"phase":"writing","drive":"128GB"}
|
|
683
|
+
// Sample input: {"t":"transferitem","id":12,"index":1,"name":"photos","ok":false,"err":"permission denied"}
|
|
684
|
+
// Sample input: {"t":"transferdone","id":12,"ok":1,"failed":0,"skipped":0,"cancelled":false,"durable":false,"note":"","merged":212,"keptBoth":3,"into":"trip"}
|
|
685
|
+
// Sample input: {"t":"transferdone","id":12,"ok":1,"failed":1,"skipped":0,"cancelled":false,"note":"rclone uploads them in the background"}
|
|
686
|
+
// Sample input: {"t":"flashimage","path":"/home/gm/Downloads/raspios-arm64.img.xz","kind":"xz","bytes":1263537968,"unpacked":6280974336,"known":true,"member":""}
|
|
687
|
+
// Sample input: {"t":"flashtargets","drives":[{"dev":"sda","seq":2,"serial":"2003007157171692","label":"128GB","model":"General USB Flash Disk","bytes":124623257600,"volumes":["128GB"],"refused":""}]}
|
|
688
|
+
// Sample input: {"t":"flashstarted","id":31,"total":4294967296,"known":true}
|
|
689
|
+
// Sample input: {"t":"flashprogress","id":31,"phase":"write","bytes":1283457024,"total":4294967296,"permille":299}
|
|
690
|
+
// Sample input: {"t":"flashdone","id":31,"ok":true,"phase":"","at":0,"err":"","blank":false}
|
|
691
|
+
// Sample input: {"t":"flasheject","ok":true,"err":""}
|
|
692
|
+
// Sample input: {"t":"collisions","id":7,"total":1,"names":[{"n":"screenshot.png","d":false,"i":"image-x-generic"}],"mergeable":false}
|
|
693
|
+
// Sample input: {"t":"mergecollisions","id":8,"total":3,"names":[{"n":"IMG_4120.HEIC","d":false,"i":"image-x-generic"}]}
|
|
694
|
+
// Sample input: {"t":"linked","ok":1,"failed":1,"skipped":0,"note":"the link left at /home/gm/b.txt could not be removed (stale)"}
|
|
695
|
+
// Sample input: {"t":"fatnames","id":7,"fstype":"exfat","volume":"128GB","renames":[{"old":"clip: x.mp4","new":"clip_ x.mp4","d":false,"i":"video-x-generic"}]}
|
|
696
|
+
// Sample input: {"t":"trashed","id":3,"ok":1,"failed":0,"moved":["/home/gm/old.txt"]}
|
|
697
|
+
// Sample input: {"t":"bulkrenamed","ok":5,"unchanged":1}
|
|
698
|
+
// Sample input: {"t":"made","ok":true,"path":"/home/gm/Pictures/New Folder"}
|
|
699
|
+
// Sample input: {"t":"undone","op":"move","ok":true}
|
|
700
|
+
// Sample input: {"t":"devs","devs":{"/":66305,"/home":66306,"/home/gm/gone":0}}
|
|
701
|
+
// Sample input: {"t":"jumped","id":3,"favourites":["/home/gm/Projects"],"zoxide":["/home/gm/Documents"],"recent":[],"frecency":{"/home/gm/Documents":80},"ms":4.210}
|
|
702
|
+
function receive(line) {
|
|
703
|
+
if (!line || line.length === 0) {
|
|
704
|
+
return
|
|
705
|
+
}
|
|
706
|
+
var message = null
|
|
707
|
+
try {
|
|
708
|
+
message = JSON.parse(line)
|
|
709
|
+
} catch (e) {
|
|
710
|
+
root.failed("parse", "", "the backend sent a line this build cannot read", 0)
|
|
711
|
+
return
|
|
712
|
+
}
|
|
713
|
+
if (message.t === "clipHost") { HostClipboard.handle(root, Quickshell, message); return }
|
|
714
|
+
Messages.route(root, message)
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Longer than the backend's own 25 s drain limit, so this only fires for a child that never
|
|
718
|
+
// answers a quit at all; without it such a child would leave a shell resident with no window.
|
|
719
|
+
Timer {
|
|
720
|
+
id: quitDeadline
|
|
721
|
+
interval: 30000
|
|
722
|
+
onTriggered: root.quitReady()
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
Process {
|
|
726
|
+
id: child
|
|
727
|
+
// FLEA_BIN is the dev seam, see AGENTS.md "Where the backend binary comes from".
|
|
728
|
+
command: FleaBin.command(Quickshell.env("FLEA_BIN"), Quickshell.env("BUNINU_BUN"), Quickshell.shellDir, ["--backend"])
|
|
729
|
+
running: true
|
|
730
|
+
stdinEnabled: true
|
|
731
|
+
|
|
732
|
+
stdout: SplitParser {
|
|
733
|
+
splitMarker: "\n"
|
|
734
|
+
onRead: function (data) { root.receive(data) }
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
onStarted: {
|
|
738
|
+
if (root.pickerOnly && root.quitting) { child.signal(9); return }
|
|
739
|
+
root.queueing = false
|
|
740
|
+
// Asked once per process: which formats exist cannot change while the backend runs.
|
|
741
|
+
root.askFormats()
|
|
742
|
+
if (!root.pickerOnly) root.send({ c: "clipWatch", hostText: true })
|
|
743
|
+
for (var i = 0; i < root.pending.length; i++) {
|
|
744
|
+
child.write(root.pending[i])
|
|
745
|
+
}
|
|
746
|
+
root.pending = []
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// A spawn that fails raises runningChanged and never exited, measured, so it reports here.
|
|
750
|
+
onRunningChanged: {
|
|
751
|
+
if (root.queueing && !child.running) {
|
|
752
|
+
root.queueing = false
|
|
753
|
+
root.pending = []
|
|
754
|
+
// FailedToStart has no exited signal. A chooser already cancelling still owes its
|
|
755
|
+
// lifecycle an answer; a started child clears queueing and must be reaped in exited.
|
|
756
|
+
if (root.pickerOnly && root.quitting) root.quitReady()
|
|
757
|
+
else root.failed("backend", "", "the backend could not be started", 0)
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// A dead backend is a message, not a crash, so the window can say what happened.
|
|
762
|
+
onExited: function (exitCode, exitStatus) {
|
|
763
|
+
if (root.quitting) {
|
|
764
|
+
quitDeadline.stop()
|
|
765
|
+
root.quitReady()
|
|
766
|
+
return
|
|
767
|
+
}
|
|
768
|
+
root.failed("backend", "", "the backend exited with code " + exitCode, 0)
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|