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,355 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "js/Lists.js" as Lists
|
|
3
|
+
import Quickshell.Io
|
|
4
|
+
import "js/Markdown.js" as Markdown
|
|
5
|
+
import "js/MarkdownMaths.js" as Maths
|
|
6
|
+
import "js/MarkdownPrepared.js" as Prepared
|
|
7
|
+
import "js/Search.js" as Search
|
|
8
|
+
|
|
9
|
+
// A rested cursor on a small local Markdown file prepares Quick Look's entry and holds its small pictures decoded for the first frame.
|
|
10
|
+
Item {
|
|
11
|
+
id: root
|
|
12
|
+
|
|
13
|
+
property var pane: null
|
|
14
|
+
// False while Quick Look is open: the entry is for the next Space.
|
|
15
|
+
property bool resting: true
|
|
16
|
+
// The rest the preview column's own settle waits, so a sweep reads nothing; the pane owns that settle.
|
|
17
|
+
property int restMs: root.pane ? root.pane.settleMs : 120
|
|
18
|
+
// What a suite reads: files read at rest, the bytes the last read returned, parses the worker answered, and the file the entry last took.
|
|
19
|
+
property int reads: 0
|
|
20
|
+
property int readBytes: 0
|
|
21
|
+
property int workerAnswers: 0
|
|
22
|
+
property string preparedPath: ""
|
|
23
|
+
// True once the cursor has rested on a listed row, false from its next move; Quick Look's own build waits on it.
|
|
24
|
+
property bool rested: false
|
|
25
|
+
// A cursor move bumps seq, so a read or a parse that answers after it is dropped.
|
|
26
|
+
property int seq: 0
|
|
27
|
+
// The one request waiting on the worker: its seq, path, text and the inputs the parse took.
|
|
28
|
+
property var asked: null
|
|
29
|
+
// The small local pictures the prepared document names, held decoded until the cursor moves, and whether each has finished loading.
|
|
30
|
+
property var pictures: []
|
|
31
|
+
property bool picturesSettled: true
|
|
32
|
+
// The formulas a rested document draws, typeset ahead so the open takes their drawings from the figure service's memory; empty once the cursor moves.
|
|
33
|
+
property var formulas: []
|
|
34
|
+
// A rested formula holds one decoded picture, so the process's first picture decode (about 20 ms of plugin set-up) is paid at rest.
|
|
35
|
+
property bool warmDecoder: false
|
|
36
|
+
readonly property bool decoderWarm: decoder.status === Image.Ready
|
|
37
|
+
// How many times a rest turned the warm on, which a suite reads to prove a held key never does.
|
|
38
|
+
property int decoderWarms: 0
|
|
39
|
+
onWarmDecoderChanged: if (root.warmDecoder) root.decoderWarms++
|
|
40
|
+
// A rested table builds one unseen table once, so the process's first table types, bold and code faces and rich import are paid at rest.
|
|
41
|
+
property bool tableWarmed: false
|
|
42
|
+
// How many warm tables a rest built and measured, which a suite reads to prove it runs once, never under a held key or after Space.
|
|
43
|
+
property int tableWarms: 0
|
|
44
|
+
// The warm table's Markdown and the width it lays out in: a bold cell, a code span and a link, so each face and the link markup are first used here.
|
|
45
|
+
readonly property string tableWarmText: "| A | B | C |\n|:--|:-:|--:|\n| **x** | `y` | [l](https://e.t) |\n"
|
|
46
|
+
readonly property int tableWarmWidth: 400
|
|
47
|
+
// The one stat child sizing them (null when none), and a suite's counts of those started and alive.
|
|
48
|
+
property var sizer: null
|
|
49
|
+
property int sizersStarted: 0
|
|
50
|
+
property int sizersAlive: 0
|
|
51
|
+
|
|
52
|
+
Timer {
|
|
53
|
+
id: rest
|
|
54
|
+
interval: root.restMs
|
|
55
|
+
onTriggered: root.prepare()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
Connections {
|
|
59
|
+
target: root.pane
|
|
60
|
+
function onCursorIndexChanged() { root.moved() }
|
|
61
|
+
function onRowsChanged() { root.moved() }
|
|
62
|
+
function onListInFlightChanged() { root.moved() }
|
|
63
|
+
function onStorageKnownChanged() { root.moved() }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function moved() {
|
|
67
|
+
root.rested = false
|
|
68
|
+
root.seq++
|
|
69
|
+
root.releaseSizer()
|
|
70
|
+
// The move back waits on the new rest below, never on the entry from before it.
|
|
71
|
+
root.preparedPath = ""
|
|
72
|
+
if (root.pictures.length > 0)
|
|
73
|
+
root.pictures = []
|
|
74
|
+
root.picturesSettled = true
|
|
75
|
+
root.warmDecoder = false
|
|
76
|
+
if (root.formulas.length > 0)
|
|
77
|
+
root.formulas = []
|
|
78
|
+
rest.restart()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// head caps the bytes actually read, whatever the file grew to since its row was listed.
|
|
82
|
+
Component {
|
|
83
|
+
id: readerComponent
|
|
84
|
+
Process {
|
|
85
|
+
id: proc
|
|
86
|
+
property int seq: 0
|
|
87
|
+
property string path: ""
|
|
88
|
+
command: ["head", "-c", String(Prepared.MAX_BYTES + 1), "--", proc.path]
|
|
89
|
+
stdout: StdioCollector {
|
|
90
|
+
onStreamFinished: {
|
|
91
|
+
root.landed(proc.seq, proc.path, this.text, this.data.byteLength)
|
|
92
|
+
proc.destroy()
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// stat sizes the pictures in one child, so none past PICTURE_MAX_BYTES is decoded ahead; the deadline drops a child a hung mount holds.
|
|
99
|
+
Timer {
|
|
100
|
+
id: sizerDeadline
|
|
101
|
+
interval: Prepared.PICTURE_SIZE_DEADLINE_MS
|
|
102
|
+
onTriggered: {
|
|
103
|
+
root.releaseSizer()
|
|
104
|
+
root.picturesSettled = true
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
Component {
|
|
109
|
+
id: sizerComponent
|
|
110
|
+
Process {
|
|
111
|
+
id: sizer
|
|
112
|
+
property int seq: 0
|
|
113
|
+
property var urls: []
|
|
114
|
+
command: ["stat", "-L", "--printf", "%s\\t%n\\n", "--"].concat(sizer.urls.map(Prepared.pathOfUrl))
|
|
115
|
+
Component.onCompleted: root.sizersAlive++
|
|
116
|
+
Component.onDestruction: root.sizersAlive--
|
|
117
|
+
stdout: StdioCollector {
|
|
118
|
+
onStreamFinished: {
|
|
119
|
+
// The child is let go first: a recount settles nothing while it is out.
|
|
120
|
+
var seq = sizer.seq
|
|
121
|
+
var urls = sizer.urls
|
|
122
|
+
var text = this.text
|
|
123
|
+
if (root.sizer === sizer)
|
|
124
|
+
root.releaseSizer()
|
|
125
|
+
root.sized(seq, urls, text)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// One held Image per picture, built as a block builds its own: the pixmap cache key holds url, transform and fill, so Stretch never hits.
|
|
132
|
+
Repeater {
|
|
133
|
+
id: held
|
|
134
|
+
model: root.pictures
|
|
135
|
+
delegate: Image {
|
|
136
|
+
required property string modelData
|
|
137
|
+
visible: false
|
|
138
|
+
fillMode: Image.PreserveAspectFit
|
|
139
|
+
asynchronous: true
|
|
140
|
+
autoTransform: true
|
|
141
|
+
source: modelData
|
|
142
|
+
onStatusChanged: root.recount()
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// One unseen figure per formula, built as the document builds its own, so the service holds the drawing under the key the open asks with.
|
|
147
|
+
Repeater {
|
|
148
|
+
id: typeset
|
|
149
|
+
model: root.formulas
|
|
150
|
+
delegate: MarkdownFigure {
|
|
151
|
+
required property var modelData
|
|
152
|
+
visible: false
|
|
153
|
+
kind: "math"
|
|
154
|
+
source: modelData.source
|
|
155
|
+
display: modelData.display
|
|
156
|
+
inline: true
|
|
157
|
+
bare: true
|
|
158
|
+
bgHex: Prepared.hexOf(Theme.color.background)
|
|
159
|
+
fgHex: Prepared.hexOf(Theme.color.foreground)
|
|
160
|
+
accentHex: Prepared.hexOf(Theme.color.accent)
|
|
161
|
+
mutedHex: Prepared.hexOf(Theme.color.muted)
|
|
162
|
+
surfaceHex: Prepared.hexOf(Theme.color.surface)
|
|
163
|
+
fontFamily: Theme.font.family
|
|
164
|
+
bodyPx: Theme.font.body
|
|
165
|
+
onSvgChanged: root.recount()
|
|
166
|
+
onErrorChanged: root.recount()
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
Image {
|
|
171
|
+
id: decoder
|
|
172
|
+
visible: false
|
|
173
|
+
asynchronous: true
|
|
174
|
+
source: root.warmDecoder ? Maths.CLEAR : ""
|
|
175
|
+
onStatusChanged: root.recount()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// MarkdownTable's preview at Quick Look's body size, holding the warm table: no card holds a Markdown pane at rest.
|
|
179
|
+
Component {
|
|
180
|
+
id: tableHost
|
|
181
|
+
Item {
|
|
182
|
+
id: host
|
|
183
|
+
visible: false
|
|
184
|
+
property var block: null
|
|
185
|
+
property real availableWidth: 0
|
|
186
|
+
readonly property alias table: tableLoader.item
|
|
187
|
+
readonly property int bodyPx: Theme.font.body
|
|
188
|
+
readonly property int blockGap: 0
|
|
189
|
+
readonly property real ruleOpacity: 0
|
|
190
|
+
// Loaded by file name and given its block before it completes, so the table builds once and only when a warm runs.
|
|
191
|
+
Loader {
|
|
192
|
+
id: tableLoader
|
|
193
|
+
Component.onCompleted: setSource("MarkdownTable.qml", { visible: false, preview: host, availableWidth: host.availableWidth, block: host.block })
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
Loader {
|
|
199
|
+
id: parser
|
|
200
|
+
active: false
|
|
201
|
+
sourceComponent: CountedWorker {
|
|
202
|
+
source: "MarkdownWorker.js"
|
|
203
|
+
onMessage: function (messageObject) { root.answered(messageObject) }
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function prepare() {
|
|
208
|
+
var pane = root.pane
|
|
209
|
+
if (!root.resting || !pane || pane.listInFlight)
|
|
210
|
+
return
|
|
211
|
+
root.rested = true
|
|
212
|
+
var row = pane.rowFor(pane.cursorIndex)
|
|
213
|
+
if (!Prepared.readsInline(row, pane.storageClass, pane.storageKnown))
|
|
214
|
+
return
|
|
215
|
+
root.reads++
|
|
216
|
+
var request = readerComponent.createObject(root, { seq: root.seq, path: pane.join(Search.baseOf(pane), row.n) })
|
|
217
|
+
request.running = true
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// The read landed: a stale or oversized answer is dropped, a held one is kept, and anything else goes to the worker.
|
|
221
|
+
function landed(seq, path, text, bytes) {
|
|
222
|
+
root.readBytes = bytes
|
|
223
|
+
if (seq !== root.seq || bytes > Prepared.MAX_BYTES || text.length === 0)
|
|
224
|
+
return
|
|
225
|
+
var dir = Markdown.dirOf(path)
|
|
226
|
+
var chrome = Prepared.hexOf(Theme.color.background)
|
|
227
|
+
var ink = Prepared.hexOf(Theme.color.foreground)
|
|
228
|
+
var entry = Prepared.take(path, text, dir, chrome, ink)
|
|
229
|
+
if (entry !== null) {
|
|
230
|
+
root.startPictures(entry, dir)
|
|
231
|
+
root.preparedPath = path
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
root.asked = { seq: seq, path: path, text: text, dir: dir, chrome: chrome, ink: ink }
|
|
235
|
+
parser.active = true
|
|
236
|
+
parser.item.sendMessage({ seq: seq, source: text, dir: dir, chrome: chrome, ink: ink })
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// The worker answered: the entry is stored only for the request still waiting and a cursor that has not moved.
|
|
240
|
+
function answered(reply) {
|
|
241
|
+
var a = root.asked
|
|
242
|
+
if (a === null || a.seq !== reply.seq)
|
|
243
|
+
return
|
|
244
|
+
root.asked = null
|
|
245
|
+
Qt.callLater(root.retire)
|
|
246
|
+
// A parse that throws is Quick Look's to report on Space, so nothing is kept here.
|
|
247
|
+
if (reply.seq !== root.seq || reply.error !== "")
|
|
248
|
+
return
|
|
249
|
+
if (a.warm === true) {
|
|
250
|
+
root.buildWarmTable(reply.blocks[0])
|
|
251
|
+
return
|
|
252
|
+
}
|
|
253
|
+
Prepared.store(a.path, a.text, a.dir, a.chrome, a.ink, reply.blocks)
|
|
254
|
+
root.workerAnswers++
|
|
255
|
+
root.startPictures(reply.blocks, a.dir)
|
|
256
|
+
root.preparedPath = a.path
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// The first rested document holding a table, a quote's or a list item's included, sends the warm table's Markdown to the worker.
|
|
260
|
+
function warmTable(blocks, dir) {
|
|
261
|
+
if (root.tableWarmed || !root.resting || root.asked !== null || !root.holdsTable(blocks))
|
|
262
|
+
return
|
|
263
|
+
// A warm never replaces a request still out; one the cursor overtakes is dropped with its seq, so the next rested table asks again.
|
|
264
|
+
parser.active = true
|
|
265
|
+
root.asked = { seq: root.seq, warm: true }
|
|
266
|
+
parser.item.sendMessage({ seq: root.seq, source: root.tableWarmText, dir: dir, chrome: Prepared.hexOf(Theme.color.background), ink: Prepared.hexOf(Theme.color.foreground) })
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// The warm table's blocks came back at rest: build the table unseen and drop it at once.
|
|
270
|
+
function buildWarmTable(block) {
|
|
271
|
+
if (!root.resting || !block)
|
|
272
|
+
return
|
|
273
|
+
root.tableWarmed = true
|
|
274
|
+
var host = tableHost.createObject(root, { block: block, availableWidth: root.tableWarmWidth })
|
|
275
|
+
// Reading the measured width lays its cells out now; only a table that built and measured counts.
|
|
276
|
+
if (host.table !== null && host.table.tableWidth > 0)
|
|
277
|
+
root.tableWarms++
|
|
278
|
+
host.destroy()
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function holdsTable(list) {
|
|
282
|
+
for (var i = 0; i < list.length; i++) {
|
|
283
|
+
var b = list[i]
|
|
284
|
+
// A list's parts hold one array of blocks per item.
|
|
285
|
+
if (b && (b.type === "table" || (Lists.isList(b) && root.holdsTable(b)) || (b.parts !== undefined && root.holdsTable(b.parts))))
|
|
286
|
+
return true
|
|
287
|
+
}
|
|
288
|
+
return false
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function releaseSizer() {
|
|
292
|
+
sizerDeadline.stop()
|
|
293
|
+
if (root.sizer !== null)
|
|
294
|
+
root.sizer.destroy()
|
|
295
|
+
root.sizer = null
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function startPictures(blocks, dir) {
|
|
299
|
+
root.releaseSizer()
|
|
300
|
+
root.formulas = Prepared.formulasIn(blocks, Prepared.FORMULA_LIMIT)
|
|
301
|
+
root.warmDecoder = root.formulas.length > 0
|
|
302
|
+
root.warmTable(blocks, dir)
|
|
303
|
+
var urls = Prepared.pictureUrls(blocks, Prepared.PICTURE_LIMIT, dir)
|
|
304
|
+
if (urls.length === 0) {
|
|
305
|
+
root.recount()
|
|
306
|
+
return
|
|
307
|
+
}
|
|
308
|
+
root.picturesSettled = false
|
|
309
|
+
root.sizersStarted++
|
|
310
|
+
root.sizer = sizerComponent.createObject(root, { seq: root.seq, urls: urls })
|
|
311
|
+
root.sizer.running = true
|
|
312
|
+
sizerDeadline.restart()
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// The sizes landed: only a cursor that has not moved holds the pictures that fit.
|
|
316
|
+
function sized(seq, urls, statText) {
|
|
317
|
+
if (seq !== root.seq)
|
|
318
|
+
return
|
|
319
|
+
root.pictures = Prepared.smallPictures(urls, statText)
|
|
320
|
+
root.recount()
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Settled once no held picture is still loading, a failed one included, and the decoder's picture and every typeset formula with them.
|
|
324
|
+
function recount() {
|
|
325
|
+
if (root.sizer !== null) {
|
|
326
|
+
root.picturesSettled = false
|
|
327
|
+
return
|
|
328
|
+
}
|
|
329
|
+
for (var f = 0; f < typeset.count; f++) {
|
|
330
|
+
var figure = typeset.itemAt(f)
|
|
331
|
+
if (figure !== null && figure.svg === "" && figure.error === "") {
|
|
332
|
+
root.picturesSettled = false
|
|
333
|
+
return
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (decoder.status === Image.Loading) {
|
|
337
|
+
root.picturesSettled = false
|
|
338
|
+
return
|
|
339
|
+
}
|
|
340
|
+
for (var i = 0; i < held.count; i++) {
|
|
341
|
+
var one = held.itemAt(i)
|
|
342
|
+
if (one !== null && one.status === Image.Loading) {
|
|
343
|
+
root.picturesSettled = false
|
|
344
|
+
return
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
root.picturesSettled = true
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// The worker thread lives only while a parse waits.
|
|
351
|
+
function retire() {
|
|
352
|
+
if (root.asked === null)
|
|
353
|
+
parser.active = false
|
|
354
|
+
}
|
|
355
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "." as Flea
|
|
3
|
+
|
|
4
|
+
// Quick Look wrapper, built on first open; it captures ui/Preview.qml's eager panes container.
|
|
5
|
+
Flea.PreviewSwap {
|
|
6
|
+
// Fills its Loader, or it measures zero and every hold answers at once.
|
|
7
|
+
anchors.fill: parent
|
|
8
|
+
property Item panesSource: null
|
|
9
|
+
captureSource: panesSource
|
|
10
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "." as Flea
|
|
3
|
+
import "js/QuickLookKinds.js" as LookKinds
|
|
4
|
+
|
|
5
|
+
// What Quick Look's first Space needs before it opens: the rested file's prepared entry and held pictures, the compiled units, and the card itself built closed.
|
|
6
|
+
Item {
|
|
7
|
+
id: root
|
|
8
|
+
|
|
9
|
+
// WindowBody builds this on the cursor's first landing on a file: a Markdown file at once, any other once a key has moved the cursor.
|
|
10
|
+
property var pane: null
|
|
11
|
+
// False while Quick Look is open: the entry is for the next Space.
|
|
12
|
+
readonly property bool resting: !(root.look !== null && root.look.active)
|
|
13
|
+
readonly property alias prepare: prepare
|
|
14
|
+
// Quick Look's own unit and the swap wrapper, held from the first idle after the window settles on a file Quick Look opens, and never instantiated, so the first Space compiles and loads no unit.
|
|
15
|
+
property var previewUnit: null
|
|
16
|
+
property var swapUnit: null
|
|
17
|
+
// The unit the rested file's kind opens its content from, "" for a folder or a kind with none (ui/js/QuickLookKinds.js).
|
|
18
|
+
readonly property string kindUnit: LookKinds.unitOf(root.pane ? root.pane.cursorRow : null)
|
|
19
|
+
onKindUnitChanged: if (unitTimer.running) unitTimer.restart()
|
|
20
|
+
// The kind units the cursor has rested on, held by file name as the two above are, so a kind the window never rested on (PdfViewer, PreviewMedia) is never compiled.
|
|
21
|
+
property var kindUnits: ({})
|
|
22
|
+
readonly property var markdownUnit: root.kindUnits[LookKinds.MARKDOWN] || null
|
|
23
|
+
readonly property int unitWarmMs: 1000
|
|
24
|
+
// The unit the rested file's kind opens from, once held.
|
|
25
|
+
readonly property var restUnit: root.kindUnit !== "" ? (root.kindUnits[root.kindUnit] || null) : null
|
|
26
|
+
readonly property bool unitsReady: root.previewUnit !== null && root.previewUnit.status === Component.Ready
|
|
27
|
+
&& root.restUnit !== null && root.restUnit.status === Component.Ready
|
|
28
|
+
&& root.swapUnit !== null && root.swapUnit.status === Component.Ready
|
|
29
|
+
// The cursor has rested on a file whose kind opens from a unit, every unit compiled: the card and its swap wrapper are built now, hidden and inactive, so the first Space only opens them.
|
|
30
|
+
readonly property bool cardDue: root.unitsReady && prepare.rested && root.pane !== null
|
|
31
|
+
onCardDueChanged: if (root.cardDue && root.pane.previewLoader) {
|
|
32
|
+
root.pane.previewLoader.active = true
|
|
33
|
+
if (root.pane.previewLoader.item) root.pane.previewLoader.item.ensureSwap()
|
|
34
|
+
}
|
|
35
|
+
readonly property bool windowSettled: root.pane !== null && root.pane.listingState === "ready" && !root.pane.listInFlight
|
|
36
|
+
|
|
37
|
+
// Counts from the last move onto a file with a unit, so a cursor passing over a kind holds none of it.
|
|
38
|
+
Timer {
|
|
39
|
+
id: unitTimer
|
|
40
|
+
running: root.windowSettled && root.previewUnit === null && root.kindUnit !== ""
|
|
41
|
+
interval: root.unitWarmMs
|
|
42
|
+
onTriggered: {
|
|
43
|
+
root.previewUnit = Qt.createComponent("Preview.qml", Component.Asynchronous)
|
|
44
|
+
root.swapUnit = Qt.createComponent("QuickLookSwap.qml", Component.Asynchronous)
|
|
45
|
+
root.holdKind()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// The cursor's file kind unit, held once and kept; the key that lands on a file never compiles it.
|
|
49
|
+
function holdKind() {
|
|
50
|
+
var file = root.kindUnit
|
|
51
|
+
if (file === "" || root.kindUnits[file] !== undefined)
|
|
52
|
+
return
|
|
53
|
+
var held = Object.assign({}, root.kindUnits)
|
|
54
|
+
held[file] = Qt.createComponent(file, Component.Asynchronous)
|
|
55
|
+
root.kindUnits = held
|
|
56
|
+
}
|
|
57
|
+
// Quick Look's own unit is held and the cursor has rested on a file whose kind has a unit: the first landing on a new kind holds its unit. A move clears rested, so a held key compiles none.
|
|
58
|
+
readonly property bool kindDue: root.previewUnit !== null && prepare.rested && root.kindUnit !== ""
|
|
59
|
+
onKindDueChanged: if (root.kindDue) root.holdKind()
|
|
60
|
+
Flea.QuickLookPrepare { id: prepare; pane: root.pane; resting: root.resting }
|
|
61
|
+
// The card Quick Look opens; resting reads it so a rest never prepares over an open card.
|
|
62
|
+
readonly property var look: root.pane ? root.pane.preview : null
|
|
63
|
+
// The cursor is already on its file when this is built, so the first rest starts here and not on a move.
|
|
64
|
+
Component.onCompleted: prepare.moved()
|
|
65
|
+
}
|
package/ui/RailDrop.qml
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "js/Drag.js" as DragOps
|
|
3
|
+
import "js/DragOut.js" as DragOut
|
|
4
|
+
import "js/RailDrop.js" as RailDrop
|
|
5
|
+
import "js/Tabs.js" as Tabs
|
|
6
|
+
|
|
7
|
+
// One receiver under the rail's rows; Trash keeps its own receiver above it.
|
|
8
|
+
DropArea {
|
|
9
|
+
id: root
|
|
10
|
+
|
|
11
|
+
required property var sidebar
|
|
12
|
+
property Item viewport: root.sidebar
|
|
13
|
+
readonly property var pane: root.sidebar.navigationPane
|
|
14
|
+
property var entered: null
|
|
15
|
+
property int rowIndex: -1
|
|
16
|
+
property var targetRow: null
|
|
17
|
+
property var held: null
|
|
18
|
+
property point pointer: Qt.point(0, 0)
|
|
19
|
+
property point cuePoint: Qt.point(0, 0)
|
|
20
|
+
anchors.fill: parent
|
|
21
|
+
keys: [DragOps.ROWS_MIME, DragOps.SHELF_MIME, "text/uri-list", "text/plain"]
|
|
22
|
+
|
|
23
|
+
function session() {
|
|
24
|
+
if (feedback.item) return feedback.item
|
|
25
|
+
feedback.setSource(Qt.resolvedUrl("FileDrag.qml"), { pane: Qt.binding(function () { return root.pane }) })
|
|
26
|
+
feedback.active = true
|
|
27
|
+
return feedback.item
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Sample input: a drag offers a marker, a shelf token, text/plain and file:///d/a.txt.
|
|
31
|
+
function read(drag) {
|
|
32
|
+
var urls = []
|
|
33
|
+
for (var i = 0; i < drag.urls.length; i++) urls.push(String(drag.urls[i]))
|
|
34
|
+
return { marker: drag.getDataAsString(DragOps.ROWS_MIME), urls: urls,
|
|
35
|
+
shelf: drag.getDataAsString(DragOps.SHELF_MIME), plain: drag.getDataAsString("text/plain"),
|
|
36
|
+
proposed: drag.proposedAction }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function clearTarget() {
|
|
40
|
+
if (root.targetRow) root.targetRow.trailingLabel = null
|
|
41
|
+
root.targetRow = null
|
|
42
|
+
root.held = null
|
|
43
|
+
root.rowIndex = -1
|
|
44
|
+
if (feedback.item) feedback.item.leaveTarget()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function aim(x, y) {
|
|
48
|
+
root.pointer = Qt.point(x, y)
|
|
49
|
+
if (!root.entered) return
|
|
50
|
+
var index = RailDrop.rowAt(root.sidebar, x, y)
|
|
51
|
+
var entry = index >= 0 ? root.sidebar.entries[index] : null
|
|
52
|
+
var data = root.entered
|
|
53
|
+
var path = root.pane && !root.pane.listInFlight
|
|
54
|
+
? RailDrop.destination(entry, data.marker, data.urls, data.shelf, data.plain) : ""
|
|
55
|
+
var row = index >= 0 ? root.sidebar.railItemFor(index) : null
|
|
56
|
+
if (index === root.rowIndex && row === root.targetRow && root.held && root.held.path === path) {
|
|
57
|
+
root.cuePoint = row.mapToItem(root.viewport, 0, 0)
|
|
58
|
+
root.sayTarget()
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
root.clearTarget()
|
|
62
|
+
if (!path) return
|
|
63
|
+
root.rowIndex = index
|
|
64
|
+
root.targetRow = row
|
|
65
|
+
root.cuePoint = row.mapToItem(root.viewport, 0, 0)
|
|
66
|
+
root.held = RailDrop.pending(path)
|
|
67
|
+
root.sayTarget()
|
|
68
|
+
root.pane.backend.send({ c: "devs", paths: [path], id: root.held.id })
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function sayTarget() {
|
|
72
|
+
if (!root.held || !feedback.item) return
|
|
73
|
+
feedback.item.showTarget(root.sidebar.entries[root.rowIndex].label, root.held.dev)
|
|
74
|
+
if (root.targetRow && cue.item) root.targetRow.trailingLabel = cue.item.label
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function leave() {
|
|
78
|
+
root.clearTarget()
|
|
79
|
+
root.entered = null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function reaim() { if (root.entered) root.aim(root.pointer.x, root.pointer.y) }
|
|
83
|
+
|
|
84
|
+
onPaneChanged: root.leave()
|
|
85
|
+
Component.onDestruction: root.clearTarget()
|
|
86
|
+
Connections {
|
|
87
|
+
target: root.sidebar
|
|
88
|
+
function onEntriesChanged() {
|
|
89
|
+
root.clearTarget()
|
|
90
|
+
// The aggregate changes before its repeaters finish replacing rows.
|
|
91
|
+
Qt.callLater(root.reaim)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
Connections {
|
|
95
|
+
target: root.pane ? root.pane.backend : null
|
|
96
|
+
function onMetaResult(message) {
|
|
97
|
+
if (message.t !== "devs" || !root.entered) return
|
|
98
|
+
root.held = RailDrop.answer(root.held, message.id, message.devs)
|
|
99
|
+
root.sayTarget()
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
Loader {
|
|
104
|
+
id: feedback
|
|
105
|
+
active: false
|
|
106
|
+
onStatusChanged: if (status === Loader.Error) throw new Error("FileDrag.qml did not load: Loader status " + status)
|
|
107
|
+
}
|
|
108
|
+
Loader {
|
|
109
|
+
id: cue
|
|
110
|
+
active: root.held !== null
|
|
111
|
+
parent: root.viewport
|
|
112
|
+
x: root.cuePoint.x
|
|
113
|
+
y: root.cuePoint.y
|
|
114
|
+
width: root.targetRow ? root.targetRow.width : 0
|
|
115
|
+
height: root.targetRow ? root.targetRow.height : 0
|
|
116
|
+
z: 1
|
|
117
|
+
onActiveChanged: {
|
|
118
|
+
if (!cue.active) { cue.source = ""; return }
|
|
119
|
+
cue.setSource(Qt.resolvedUrl("DropTarget.qml"), {
|
|
120
|
+
text: Qt.binding(function () { return DragOps.label(feedback.item ? feedback.item.dragCopy : true, feedback.item ? feedback.item.dragLink : false) })
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
onLoaded: root.sayTarget()
|
|
124
|
+
onStatusChanged: if (status === Loader.Error) throw new Error("DropTarget.qml did not load: Loader status " + status)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function enterAt(drag) {
|
|
128
|
+
if (!root.pane || !root.pane.backend || drag.getDataAsString(Tabs.TAB_MIME) !== "") { drag.accepted = false; return }
|
|
129
|
+
root.entered = root.read(drag)
|
|
130
|
+
DragOut.keys.enter(root.entered.marker, drag.getDataAsString(DragOut.keys.liftMime))
|
|
131
|
+
var session = root.session()
|
|
132
|
+
if (!session) { root.leave(); drag.accepted = false; return }
|
|
133
|
+
session.enterTarget(root.entered.marker, root.entered.urls, "", DragOps.markerDev(root.entered.marker), root.entered.shelf, drag.proposedAction)
|
|
134
|
+
root.aim(drag.x, drag.y)
|
|
135
|
+
}
|
|
136
|
+
function dropAt(drop) {
|
|
137
|
+
var ctrl = DragOut.keys.ctrl, shift = DragOut.keys.shift
|
|
138
|
+
DragOut.keys.clear()
|
|
139
|
+
root.aim(drop.x, drop.y)
|
|
140
|
+
var data = root.read(drop)
|
|
141
|
+
var entry = root.rowIndex >= 0 ? root.sidebar.entries[root.rowIndex] : null
|
|
142
|
+
if (RailDrop.drop(root.pane, entry, root.held, data.marker, data.urls, data.shelf, data.plain, drop.proposedAction, ctrl, shift)) {
|
|
143
|
+
drop.accept(Qt.CopyAction)
|
|
144
|
+
// The rail's key table ignores undo, so an accepted drop gives the receiving listing the keyboard.
|
|
145
|
+
root.pane.focusView = "list"
|
|
146
|
+
root.pane.focusRequested()
|
|
147
|
+
root.pane.listArea.forceActiveFocus()
|
|
148
|
+
}
|
|
149
|
+
root.leave()
|
|
150
|
+
}
|
|
151
|
+
onEntered: function (drag) { root.enterAt(drag) }
|
|
152
|
+
onPositionChanged: function (drag) { root.aim(drag.x, drag.y) }
|
|
153
|
+
onExited: { DragOut.keys.leave(); root.leave() }
|
|
154
|
+
onDropped: function (drop) { root.dropAt(drop) }
|
|
155
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
|
|
4
|
+
// One rail heading: the caption text with the rail's lead and tracking.
|
|
5
|
+
Text {
|
|
6
|
+
id: root
|
|
7
|
+
property real topExtra: 0
|
|
8
|
+
property bool noBottom: false
|
|
9
|
+
readonly property real headingLead: 0.15
|
|
10
|
+
readonly property real headingTracking: 1
|
|
11
|
+
x: Style.spacing.rowPaddingX
|
|
12
|
+
topPadding: root.topExtra + Math.ceil(font.pixelSize * root.headingLead)
|
|
13
|
+
bottomPadding: root.noBottom ? 0 : Style.spacing.rowGap
|
|
14
|
+
color: Theme.color.muted
|
|
15
|
+
font.family: Theme.font.family
|
|
16
|
+
font.pixelSize: Theme.font.caption
|
|
17
|
+
font.letterSpacing: root.headingTracking
|
|
18
|
+
textFormat: Text.PlainText
|
|
19
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
pragma Singleton
|
|
2
|
+
import QtQuick
|
|
3
|
+
import Quickshell
|
|
4
|
+
import "js/Icons.js" as Icons
|
|
5
|
+
import "js/Places.js" as Places
|
|
6
|
+
|
|
7
|
+
// Place data outlives the visible rail, so hiding it cannot remove query destinations.
|
|
8
|
+
QtObject {
|
|
9
|
+
id: root
|
|
10
|
+
readonly property var settings: ViewState.state.places || ({})
|
|
11
|
+
// flea-qml: the folders and the drives the backend found by looking (src/places.js), null
|
|
12
|
+
// until its first `places` line. Upstream read user-dirs.dirs here and drew what it named.
|
|
13
|
+
property var probed: null
|
|
14
|
+
property var probedVolumes: null
|
|
15
|
+
property string probedText: ""
|
|
16
|
+
// An answer that says the same again changes nothing, so no rail rebuilds its rows for it.
|
|
17
|
+
function found(places, volumes) {
|
|
18
|
+
var text = JSON.stringify([places, volumes])
|
|
19
|
+
if (text === root.probedText) return
|
|
20
|
+
root.probedText = text
|
|
21
|
+
root.probed = places
|
|
22
|
+
root.probedVolumes = volumes
|
|
23
|
+
}
|
|
24
|
+
readonly property var homeEntries: root.settings.showHome === false ? []
|
|
25
|
+
: Places.homeEntries(Quickshell.env("HOME"), root.probed, Icons.sidebarGlyphFor)
|
|
26
|
+
readonly property var favouriteEntries: Places.storedEntries(Favourites.records, Quickshell.env("HOME")).map(function (entry) {
|
|
27
|
+
entry.error = entry.error || Favourites.statuses[entry.favouriteIndex] || ""
|
|
28
|
+
return entry
|
|
29
|
+
})
|
|
30
|
+
readonly property var recentEntries: root.settings.showRecent === true
|
|
31
|
+
? [{ label: "Recent", path: "flea:recent", group: "recent", kind: "recent", glyph: "history" }] : []
|
|
32
|
+
readonly property var trashEntries: root.settings.showTrash === false ? []
|
|
33
|
+
: [{ label: "Trash", path: "trash:///", group: "trash", kind: "trash", glyph: "trash" }]
|
|
34
|
+
function entries() {
|
|
35
|
+
return root.homeEntries.slice(0, 1).concat(root.recentEntries,
|
|
36
|
+
root.homeEntries.slice(1), root.trashEntries, root.favouriteEntries)
|
|
37
|
+
}
|
|
38
|
+
}
|