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
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import qs.Commons
|
|
3
|
+
import "." as Flea
|
|
4
|
+
import "js/Flash.js" as Flash
|
|
5
|
+
import "js/Transfer.js" as Transfer
|
|
6
|
+
|
|
7
|
+
// The FLASH step: one 37 px row with the alert mark, erase line and action, then the running bar and the ending row.
|
|
8
|
+
Column {
|
|
9
|
+
id: root
|
|
10
|
+
property var transfer: null
|
|
11
|
+
property real rate: 0
|
|
12
|
+
property var words: ({ erase: "", action: "" })
|
|
13
|
+
property bool live: false
|
|
14
|
+
property bool running: false
|
|
15
|
+
property var ending: null
|
|
16
|
+
property bool ejected: false
|
|
17
|
+
property bool cursor: false
|
|
18
|
+
property bool focused: true
|
|
19
|
+
signal pressFlash()
|
|
20
|
+
signal pressCancel()
|
|
21
|
+
signal pressEnd()
|
|
22
|
+
readonly property var flashItem: flashButton
|
|
23
|
+
readonly property var cancelItem: cancelButton
|
|
24
|
+
readonly property var endItem: endButton
|
|
25
|
+
width: 0
|
|
26
|
+
// The running bar takes the transfer card's recipe: half a caption thick, a quarter-ink track.
|
|
27
|
+
readonly property int barHeight: Math.round(Theme.font.caption / 2)
|
|
28
|
+
readonly property real trackOpacity: 0.25
|
|
29
|
+
Text {
|
|
30
|
+
x: Theme.spacing.rowPaddingX
|
|
31
|
+
// A later section opens a panel gap under the one above, as the rail's FAVORITES does.
|
|
32
|
+
topPadding: Math.round(Style.spacing.panelGap * Theme.sizeRatio) + Math.ceil(font.pixelSize * 0.15)
|
|
33
|
+
bottomPadding: Theme.spacing.gap
|
|
34
|
+
text: "FLASH"
|
|
35
|
+
color: Theme.color.muted
|
|
36
|
+
font.family: Theme.font.family
|
|
37
|
+
font.pixelSize: Theme.font.caption
|
|
38
|
+
font.letterSpacing: 1
|
|
39
|
+
textFormat: Text.PlainText
|
|
40
|
+
}
|
|
41
|
+
Rectangle {
|
|
42
|
+
width: root.width
|
|
43
|
+
height: Theme.rowHeight
|
|
44
|
+
// The cursor uses accent ink, as every listing row does; the greyed Flash row only dims.
|
|
45
|
+
color: root.cursor ? (root.focused ? Style.selectedAccentFill : "transparent") : "transparent"
|
|
46
|
+
opacity: !root.running && root.ending === null && !root.live ? Theme.disabledOpacity : 1
|
|
47
|
+
Rectangle {
|
|
48
|
+
visible: root.cursor
|
|
49
|
+
width: Theme.spacing.hairline * 2
|
|
50
|
+
height: parent.height
|
|
51
|
+
color: root.focused ? Theme.color.accent : Theme.color.mutedFrame
|
|
52
|
+
}
|
|
53
|
+
Row {
|
|
54
|
+
anchors.fill: parent
|
|
55
|
+
anchors.leftMargin: Theme.spacing.rowPaddingX
|
|
56
|
+
anchors.rightMargin: Theme.spacing.rowPaddingX
|
|
57
|
+
spacing: Theme.spacing.gap
|
|
58
|
+
Flea.Glyph {
|
|
59
|
+
width: Theme.markSize
|
|
60
|
+
height: parent.height
|
|
61
|
+
visible: !root.running && root.ending === null
|
|
62
|
+
name: "alert"
|
|
63
|
+
color: Theme.color.error
|
|
64
|
+
}
|
|
65
|
+
Flea.Spinner {
|
|
66
|
+
width: Theme.markSize
|
|
67
|
+
height: parent.height
|
|
68
|
+
visible: root.running
|
|
69
|
+
color: Theme.color.mutedFrame
|
|
70
|
+
}
|
|
71
|
+
Flea.Glyph {
|
|
72
|
+
width: Theme.markSize
|
|
73
|
+
height: parent.height
|
|
74
|
+
visible: root.ending !== null
|
|
75
|
+
name: root.ending ? root.ending.mark : "check"
|
|
76
|
+
color: root.ending && root.ending.role === "error" ? Theme.color.error
|
|
77
|
+
: root.ending && root.ending.role === "foreground" ? Theme.color.foreground : Theme.color.mutedFrame
|
|
78
|
+
}
|
|
79
|
+
Text {
|
|
80
|
+
width: Math.max(0, parent.width - Theme.markSize - flashControl.width - 2 * parent.spacing)
|
|
81
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
82
|
+
text: root.running ? Transfer.head(root.transfer)
|
|
83
|
+
: root.ending ? root.ending.headline : root.words.erase
|
|
84
|
+
textFormat: Text.PlainText
|
|
85
|
+
elide: Text.ElideRight
|
|
86
|
+
color: Flash.stepRole(root.running, root.ending) === "error" ? Theme.color.error : Theme.color.foreground
|
|
87
|
+
font { family: Theme.font.family; pixelSize: Theme.font.body }
|
|
88
|
+
}
|
|
89
|
+
Item {
|
|
90
|
+
id: flashControl
|
|
91
|
+
width: Math.max(flashButton.implicitWidth, cancelButton.implicitWidth, endButton.implicitWidth)
|
|
92
|
+
height: parent.height
|
|
93
|
+
Flea.DialogButton {
|
|
94
|
+
id: flashButton
|
|
95
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
96
|
+
visible: !root.running && root.ending === null
|
|
97
|
+
label: root.words.action
|
|
98
|
+
primary: true
|
|
99
|
+
available: root.live
|
|
100
|
+
onActivated: root.pressFlash()
|
|
101
|
+
}
|
|
102
|
+
Flea.DialogButton {
|
|
103
|
+
id: cancelButton
|
|
104
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
105
|
+
visible: root.running
|
|
106
|
+
label: "Cancel"
|
|
107
|
+
available: Transfer.cancelEnabled(root.transfer)
|
|
108
|
+
onActivated: root.pressCancel()
|
|
109
|
+
}
|
|
110
|
+
Flea.DialogButton {
|
|
111
|
+
id: endButton
|
|
112
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
113
|
+
visible: !root.running && root.ending !== null && (root.ending.eject || root.ending.flashBack) && !root.ejected
|
|
114
|
+
label: root.ending && root.ending.flashBack ? root.words.action : "Eject"
|
|
115
|
+
primary: root.ending ? root.ending.flashBack : false
|
|
116
|
+
available: root.ending && root.ending.flashBack ? root.live : true
|
|
117
|
+
onActivated: root.pressEnd()
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// The running step's own lines under the label column, the bar and then the byte line.
|
|
123
|
+
Column {
|
|
124
|
+
visible: root.running
|
|
125
|
+
x: Theme.spacing.rowPaddingX + Theme.markSize + Theme.spacing.gap
|
|
126
|
+
width: root.width - x - Theme.spacing.rowPaddingX - Theme.column.size
|
|
127
|
+
topPadding: Theme.spacing.rowPaddingY
|
|
128
|
+
spacing: root.barHeight
|
|
129
|
+
// The fill is a sibling of the track and not its child, because opacity multiplies down into children.
|
|
130
|
+
Item {
|
|
131
|
+
width: parent.width
|
|
132
|
+
height: root.barHeight
|
|
133
|
+
Rectangle {
|
|
134
|
+
anchors.fill: parent
|
|
135
|
+
color: Theme.color.mutedFrame
|
|
136
|
+
opacity: root.trackOpacity
|
|
137
|
+
}
|
|
138
|
+
Rectangle {
|
|
139
|
+
width: parent.width * Transfer.fraction(root.transfer)
|
|
140
|
+
height: parent.height
|
|
141
|
+
color: Theme.color.accentFrame
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
Row {
|
|
145
|
+
id: byteLine
|
|
146
|
+
readonly property var parts: Transfer.byteParts(root.transfer, root.rate)
|
|
147
|
+
Repeater {
|
|
148
|
+
model: byteLine.parts
|
|
149
|
+
delegate: Text {
|
|
150
|
+
required property var modelData
|
|
151
|
+
text: modelData.text
|
|
152
|
+
color: modelData.figure ? Theme.color.foreground : Theme.color.muted
|
|
153
|
+
font.family: Theme.font.family
|
|
154
|
+
font.pixelSize: Theme.font.caption
|
|
155
|
+
textFormat: Text.PlainText
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
Text {
|
|
161
|
+
visible: root.ending !== null && root.ending.hint.length > 0
|
|
162
|
+
x: Theme.spacing.rowPaddingX + Theme.markSize + Theme.spacing.gap
|
|
163
|
+
topPadding: Theme.spacing.rowPaddingY
|
|
164
|
+
bottomPadding: Theme.spacing.rowPaddingY
|
|
165
|
+
width: root.width - x - Theme.spacing.rowPaddingX
|
|
166
|
+
wrapMode: Text.Wrap
|
|
167
|
+
text: root.ending ? root.ending.hint : ""
|
|
168
|
+
color: Theme.color.muted
|
|
169
|
+
font { family: Theme.font.family; pixelSize: Theme.font.caption }
|
|
170
|
+
textFormat: Text.PlainText
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import "." as Flea
|
|
3
|
+
|
|
4
|
+
// The flasher's strip: Back, an unavailable Up and the title; every exit leaves through the view's close.
|
|
5
|
+
Rectangle {
|
|
6
|
+
id: root
|
|
7
|
+
signal back()
|
|
8
|
+
width: 0
|
|
9
|
+
height: Theme.chromeHeight
|
|
10
|
+
color: Theme.color.surface
|
|
11
|
+
Row {
|
|
12
|
+
anchors.fill: parent
|
|
13
|
+
anchors.leftMargin: Theme.spacing.rowPaddingX
|
|
14
|
+
anchors.rightMargin: Theme.spacing.rowPaddingX
|
|
15
|
+
spacing: Theme.spacing.gap
|
|
16
|
+
Flea.ChromeButton {
|
|
17
|
+
ruleRows: Theme.spacing.hairline
|
|
18
|
+
glyph: "arrow-left"
|
|
19
|
+
onActivated: root.back()
|
|
20
|
+
}
|
|
21
|
+
Flea.ChromeButton {
|
|
22
|
+
ruleRows: Theme.spacing.hairline
|
|
23
|
+
glyph: "arrow-up"
|
|
24
|
+
accessName: "Up unavailable in Flash"
|
|
25
|
+
enabled: false
|
|
26
|
+
Accessible.ignored: false
|
|
27
|
+
}
|
|
28
|
+
Text {
|
|
29
|
+
anchors.verticalCenter: parent.verticalCenter
|
|
30
|
+
text: "Flash image"
|
|
31
|
+
textFormat: Text.PlainText
|
|
32
|
+
elide: Text.ElideRight
|
|
33
|
+
color: Theme.color.foreground
|
|
34
|
+
font { family: Theme.font.family; pixelSize: Theme.font.caption }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
Rectangle { anchors.bottom: parent.bottom; width: parent.width; height: Theme.spacing.hairline; color: Theme.color.foreground; opacity: 0.12 }
|
|
38
|
+
}
|
package/ui/FlashView.qml
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import Quickshell
|
|
3
|
+
import Quickshell.Io
|
|
4
|
+
import "." as Flea
|
|
5
|
+
import "js/Flash.js" as Flash
|
|
6
|
+
import "js/FlashPane.js" as FlashPane
|
|
7
|
+
import "js/Keymap.js" as Keymap
|
|
8
|
+
import "js/Ops.js" as Ops
|
|
9
|
+
|
|
10
|
+
// Flash image swaps the listing like Trash does; Esc, Back and Backspace leave the pane and never cancel a flash.
|
|
11
|
+
FocusScope {
|
|
12
|
+
id: root
|
|
13
|
+
required property var pane
|
|
14
|
+
property var statusBar: null
|
|
15
|
+
property bool opened: false
|
|
16
|
+
// The image under test, or null before the picker names one.
|
|
17
|
+
property var image: null
|
|
18
|
+
// A rail volume's device path waiting for the drive list to name its disk.
|
|
19
|
+
property string pendingDrive: ""
|
|
20
|
+
property var drives: []
|
|
21
|
+
property bool drivesReady: false
|
|
22
|
+
// The chosen drive's row, held by identity so a poll that reorders the list never retargets Flash or Eject.
|
|
23
|
+
property var chosen: null
|
|
24
|
+
// Set once this opening holds a drive, so a choice that left stays empty instead of falling to the one fitting drive left.
|
|
25
|
+
property bool held: false
|
|
26
|
+
readonly property int selected: FlashPane.indexOf(root.drives, root.chosen)
|
|
27
|
+
property int cursor: 0
|
|
28
|
+
property int requestId: 0
|
|
29
|
+
property bool ejected: false
|
|
30
|
+
// The flash's own run, answered by the backend; the view owns the cursor and the rows.
|
|
31
|
+
readonly property var transfer: runner.transfer
|
|
32
|
+
readonly property bool running: runner.running
|
|
33
|
+
readonly property var ending: runner.ending
|
|
34
|
+
readonly property real rate: runner.rate
|
|
35
|
+
readonly property int driveCount: root.drives.length
|
|
36
|
+
readonly property var chosenDrive: root.selected >= 0 && root.selected < root.drives.length ? root.drives[root.selected] : null
|
|
37
|
+
readonly property int flashRow: Flash.flashPos(root.drives.length)
|
|
38
|
+
readonly property bool imageOk: root.image !== null && root.image.refused !== true
|
|
39
|
+
readonly property bool live: Flash.flashLive(root.imageOk, root.chosenDrive)
|
|
40
|
+
readonly property var words: Flash.flashWords(root.imageOk, root.chosenDrive, root.drives)
|
|
41
|
+
signal backRequested()
|
|
42
|
+
signal focusRailRequested()
|
|
43
|
+
anchors.fill: parent
|
|
44
|
+
visible: opened
|
|
45
|
+
// The seam's own handles onto the step's controls, so a driven case clicks what it named.
|
|
46
|
+
readonly property var flashItem: stepRow.flashItem
|
|
47
|
+
readonly property var cancelItem: stepRow.cancelItem
|
|
48
|
+
readonly property var endItem: stepRow.endItem
|
|
49
|
+
|
|
50
|
+
function open() {
|
|
51
|
+
// Reopening onto a running flash shows it, never restarts it, and takes its card back from the pane.
|
|
52
|
+
if (runner.running) {
|
|
53
|
+
FlashPane.reclaim(root.pane)
|
|
54
|
+
root.opened = true
|
|
55
|
+
root.forceActiveFocus()
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
runner.reset()
|
|
59
|
+
root.ejected = false
|
|
60
|
+
root.opened = true
|
|
61
|
+
root.drives = []
|
|
62
|
+
root.drivesReady = false
|
|
63
|
+
root.forceActiveFocus()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function openWithImage(path) {
|
|
67
|
+
if (runner.running)
|
|
68
|
+
return root.open()
|
|
69
|
+
root.image = { path: path, kind: "", bytes: 0, unpacked: 0, known: false, member: "", refused: false }
|
|
70
|
+
root.pendingDrive = ""
|
|
71
|
+
root.chosen = null
|
|
72
|
+
root.cursor = 0
|
|
73
|
+
root.open()
|
|
74
|
+
root.pane.backend.flashImage(path)
|
|
75
|
+
root.pane.backend.flashTargets(path)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function openWithDrive(device) {
|
|
79
|
+
if (runner.running)
|
|
80
|
+
return root.open()
|
|
81
|
+
root.pendingDrive = device
|
|
82
|
+
root.chosen = null
|
|
83
|
+
root.cursor = 0
|
|
84
|
+
root.open()
|
|
85
|
+
if (root.image)
|
|
86
|
+
root.pane.backend.flashImage(root.image.path)
|
|
87
|
+
root.pane.backend.flashTargets(root.image ? root.image.path : "")
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function close() {
|
|
91
|
+
if (!root.opened)
|
|
92
|
+
return
|
|
93
|
+
root.opened = false
|
|
94
|
+
// After Back the running flash joins the pane's transfer the way a copy's does.
|
|
95
|
+
if (root.running) {
|
|
96
|
+
root.pane.transfer = root.transfer
|
|
97
|
+
root.pane.sticky(Ops.progressLine(root.transfer))
|
|
98
|
+
}
|
|
99
|
+
root.backRequested()
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function chooseImage() {
|
|
103
|
+
if (chooser.running || root.running)
|
|
104
|
+
return
|
|
105
|
+
var home = Quickshell.env("HOME") || ""
|
|
106
|
+
chooser.command = [Quickshell.env("FLEA_BIN") || "flea", "flash", "choose", home + "/Downloads"]
|
|
107
|
+
chooser.running = true
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function pressFlash() {
|
|
111
|
+
if (runner.pressSent || !root.live || root.running)
|
|
112
|
+
return
|
|
113
|
+
var drive = root.chosenDrive
|
|
114
|
+
root.requestId += 1
|
|
115
|
+
runner.pressSent = true
|
|
116
|
+
runner.pendingId = root.requestId
|
|
117
|
+
root.pane.backend.flash(root.requestId, root.image.path, drive.dev, drive.seq, drive.serial, drive.bytes)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function pressCancel() {
|
|
121
|
+
if (!root.running)
|
|
122
|
+
return
|
|
123
|
+
root.pane.backend.flashCancel(root.transfer.id)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function ejectChosen() {
|
|
127
|
+
var drive = root.chosenDrive
|
|
128
|
+
if (!drive || root.running || root.ejected)
|
|
129
|
+
return
|
|
130
|
+
root.pane.backend.flashEject(drive.dev, drive.seq)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function cursorDrive() {
|
|
134
|
+
return root.cursor > 0 && root.cursor <= root.drives.length ? root.cursor - 1 : -1
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function moveCursor(delta) {
|
|
138
|
+
// While a flash runs the cursor stays between the drive being flashed and Cancel.
|
|
139
|
+
if (root.running) {
|
|
140
|
+
root.cursor = root.cursor === root.flashRow ? root.selected + 1 : root.flashRow
|
|
141
|
+
root.parkFocus()
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
root.cursor = Flash.step(root.cursor, delta, root.drives, root.image !== null, true)
|
|
145
|
+
root.chosen = FlashPane.chooseKept(root.cursor, root.drives, root.chosen)
|
|
146
|
+
root.parkFocus()
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function parkFocus() {
|
|
150
|
+
if (!root.opened)
|
|
151
|
+
return
|
|
152
|
+
// After Eject no button is drawn, so the keyboard rests on the pane itself.
|
|
153
|
+
if (root.ejected) {
|
|
154
|
+
root.forceActiveFocus()
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
if (root.cursor === root.flashRow && !root.running) {
|
|
158
|
+
if (root.ending && (root.ending.flashBack || root.ending.eject) && stepRow.endItem)
|
|
159
|
+
stepRow.endItem.forceActiveFocus()
|
|
160
|
+
else if (!root.ending && stepRow.flashItem)
|
|
161
|
+
stepRow.flashItem.forceActiveFocus()
|
|
162
|
+
else
|
|
163
|
+
root.forceActiveFocus()
|
|
164
|
+
} else if (root.cursor === root.flashRow && stepRow.cancelItem) {
|
|
165
|
+
stepRow.cancelItem.forceActiveFocus()
|
|
166
|
+
} else {
|
|
167
|
+
root.forceActiveFocus()
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// A focused button owns Enter and Space itself, so the scope stands aside for those keys.
|
|
172
|
+
function buttonFocused() {
|
|
173
|
+
return (stepRow.flashItem && stepRow.flashItem.activeFocus)
|
|
174
|
+
|| (stepRow.cancelItem && stepRow.cancelItem.activeFocus)
|
|
175
|
+
|| (stepRow.endItem && stepRow.endItem.activeFocus)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// The ending row's own action: Eject where one is offered, Flash again under a failure.
|
|
179
|
+
function pressEnd() {
|
|
180
|
+
if (root.ending && root.ending.flashBack)
|
|
181
|
+
root.pressFlash()
|
|
182
|
+
else
|
|
183
|
+
root.ejectChosen()
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function contextPress() {
|
|
187
|
+
var atDrive = root.cursorDrive()
|
|
188
|
+
if (root.running) {
|
|
189
|
+
if (root.cursor === root.flashRow)
|
|
190
|
+
root.pressCancel()
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
if (root.ending !== null) {
|
|
194
|
+
if (root.cursor === root.flashRow) {
|
|
195
|
+
if (root.ending.eject)
|
|
196
|
+
root.ejectChosen()
|
|
197
|
+
else if (root.ending.flashBack)
|
|
198
|
+
root.pressFlash()
|
|
199
|
+
} else if (root.cursor === 0) {
|
|
200
|
+
root.chooseImage()
|
|
201
|
+
} else if (atDrive >= 0) {
|
|
202
|
+
root.chosen = root.drives[atDrive]
|
|
203
|
+
root.cursor = root.flashRow
|
|
204
|
+
root.parkFocus()
|
|
205
|
+
}
|
|
206
|
+
return
|
|
207
|
+
}
|
|
208
|
+
if (root.cursor === 0) {
|
|
209
|
+
root.chooseImage()
|
|
210
|
+
return
|
|
211
|
+
}
|
|
212
|
+
if (atDrive >= 0) {
|
|
213
|
+
root.chosen = root.drives[atDrive]
|
|
214
|
+
root.cursor = root.flashRow
|
|
215
|
+
root.parkFocus()
|
|
216
|
+
return
|
|
217
|
+
}
|
|
218
|
+
if (root.cursor === root.flashRow)
|
|
219
|
+
root.pressFlash()
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function receiveImage(message) {
|
|
223
|
+
if (!root.opened && !root.running)
|
|
224
|
+
return
|
|
225
|
+
var image = Flash.imageFrom(root.image, message)
|
|
226
|
+
if (image)
|
|
227
|
+
root.image = image
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function receiveTargets(message) {
|
|
231
|
+
if (!root.opened && !root.running)
|
|
232
|
+
return
|
|
233
|
+
var rows = message.drives || []
|
|
234
|
+
var was = root.drives
|
|
235
|
+
var first = !root.drivesReady
|
|
236
|
+
root.drives = rows
|
|
237
|
+
root.drivesReady = true
|
|
238
|
+
if (root.running)
|
|
239
|
+
return
|
|
240
|
+
// A fitting drive plugged in after Eject brings the Flash row back.
|
|
241
|
+
if (root.ejected) {
|
|
242
|
+
if (rows.filter(function (drive) { return Flash.fits(drive) }).length === 0)
|
|
243
|
+
return
|
|
244
|
+
root.ejected = false
|
|
245
|
+
runner.ending = null
|
|
246
|
+
}
|
|
247
|
+
var next = FlashPane.reconcile({ chosen: root.chosen, cursor: root.cursor, drives: was, first: first,
|
|
248
|
+
held: root.held, pendingDisk: root.pendingDrive }, rows)
|
|
249
|
+
FlashPane.land(root, next)
|
|
250
|
+
if (next.moved)
|
|
251
|
+
root.parkFocus()
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function startTransfer(id, total, known) {
|
|
255
|
+
var drive = root.chosenDrive
|
|
256
|
+
var label = drive ? Flash.driveName(drive, root.drives) : ""
|
|
257
|
+
runner.startTransfer(id, total, known, root.image ? Flash.leaf(root.image.path) : "", label, root.opened)
|
|
258
|
+
root.cursor = root.flashRow
|
|
259
|
+
root.parkFocus()
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function progressTransfer(id, phase, bytes, total, permille) {
|
|
263
|
+
runner.progressTransfer(id, phase, bytes, total, permille, root.opened)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function finishTransfer(message) {
|
|
267
|
+
var imageName = root.image ? Flash.leaf(root.image.path) : ""
|
|
268
|
+
var landed = runner.finishTransfer(message, imageName, root.transfer.drive,
|
|
269
|
+
root.chosen ? root.chosen.bytes : 0, root.opened)
|
|
270
|
+
if (landed === "refused")
|
|
271
|
+
root.pane.backend.flashImage(root.image ? root.image.path : "")
|
|
272
|
+
else if (landed) {
|
|
273
|
+
root.cursor = root.flashRow
|
|
274
|
+
root.parkFocus()
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function finishEject(message) {
|
|
279
|
+
var drive = root.chosenDrive
|
|
280
|
+
runner.finishEject(message, drive ? Flash.driveName(drive, root.drives) : "")
|
|
281
|
+
if (message.ok === true) {
|
|
282
|
+
root.ejected = true
|
|
283
|
+
root.parkFocus()
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
Keys.onPressed: function (event) {
|
|
288
|
+
var action = Keymap.lookup(event.key, event.text, event.modifiers, "listing", "gui")
|
|
289
|
+
var unmodified = (event.modifiers & (Qt.ControlModifier | Qt.ShiftModifier | Qt.AltModifier | Qt.MetaModifier)) === 0
|
|
290
|
+
if (action === "escape" && root.statusBar && root.statusBar.escapePressed()) { event.accepted = true; return }
|
|
291
|
+
if (action === "escape" || (event.key === Qt.Key_Backspace && unmodified)) root.close()
|
|
292
|
+
else if (action === "cursorDown") root.moveCursor(1)
|
|
293
|
+
else if (action === "cursorUp") root.moveCursor(-1)
|
|
294
|
+
else if (action === "eject") root.ejectChosen()
|
|
295
|
+
else if (action === "focusNext") root.focusRailRequested()
|
|
296
|
+
else if (action === "open" || (event.key === Qt.Key_Space && unmodified)) {
|
|
297
|
+
if (root.buttonFocused()) { event.accepted = true; return }
|
|
298
|
+
// A held Enter stops on Flash instead of pressing it: only a fresh press confirms.
|
|
299
|
+
if (event.isAutoRepeat && root.cursor === root.flashRow && root.ending === null) { event.accepted = true; return }
|
|
300
|
+
root.contextPress()
|
|
301
|
+
}
|
|
302
|
+
event.accepted = true
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
Process {
|
|
306
|
+
id: chooser
|
|
307
|
+
stdout: StdioCollector { id: chosenText }
|
|
308
|
+
// A chooser that never answers is the backend's refusal, so the pane keeps its drives.
|
|
309
|
+
onExited: function (exitCode, exitStatus) {
|
|
310
|
+
if (exitCode !== 0)
|
|
311
|
+
return
|
|
312
|
+
var path = chosenText.text.trim()
|
|
313
|
+
if (path.length > 0)
|
|
314
|
+
root.openWithImage(path)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
Connections {
|
|
319
|
+
target: root.pane.backend
|
|
320
|
+
function onFlashImageResult(message) { root.receiveImage(message) }
|
|
321
|
+
function onFlashTargetsResult(message) { root.receiveTargets(message) }
|
|
322
|
+
function onFlashStartedLine(id, total, known) { root.startTransfer(id, total, known) }
|
|
323
|
+
function onFlashProgressLine(id, phase, bytes, total, permille) { root.progressTransfer(id, phase, bytes, total, permille) }
|
|
324
|
+
function onFlashDoneLine(message) { root.finishTransfer(message) }
|
|
325
|
+
function onFlashEjectLine(message) { root.finishEject(message) }
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// A fitting drive plugged in after Eject brings the Flash row back; the rail's own poll period is the tick.
|
|
329
|
+
readonly property int pollMs: 5000
|
|
330
|
+
Timer {
|
|
331
|
+
interval: root.pollMs
|
|
332
|
+
repeat: true
|
|
333
|
+
running: root.opened && !root.running
|
|
334
|
+
onTriggered: root.pane.backend.flashTargets(root.image ? root.image.path : "")
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// The flash's own run, answered by the backend; the view owns the cursor and the rows.
|
|
338
|
+
Flea.FlashRunner {
|
|
339
|
+
id: runner
|
|
340
|
+
pane: root.pane
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
Rectangle { anchors.fill: parent; color: Theme.color.background }
|
|
344
|
+
|
|
345
|
+
Column {
|
|
346
|
+
anchors.fill: parent
|
|
347
|
+
spacing: 0
|
|
348
|
+
// The strip without an action: Back, an unavailable Up, the title, nothing else.
|
|
349
|
+
Flea.FlashStrip {
|
|
350
|
+
width: parent.width
|
|
351
|
+
onBack: root.close()
|
|
352
|
+
}
|
|
353
|
+
Flea.FlashImageRow {
|
|
354
|
+
width: parent.width
|
|
355
|
+
image: root.image
|
|
356
|
+
cursor: root.cursor === 0
|
|
357
|
+
focused: root.activeFocus
|
|
358
|
+
running: root.running
|
|
359
|
+
onChoose: {
|
|
360
|
+
root.cursor = 0
|
|
361
|
+
root.parkFocus()
|
|
362
|
+
root.contextPress()
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
Flea.FlashDriveRows {
|
|
366
|
+
width: parent.width
|
|
367
|
+
drives: root.drives
|
|
368
|
+
drivesReady: root.drivesReady
|
|
369
|
+
selected: root.selected
|
|
370
|
+
cursor: root.cursor
|
|
371
|
+
focused: root.activeFocus
|
|
372
|
+
running: root.running
|
|
373
|
+
onChooseDrive: function (index) {
|
|
374
|
+
root.chosen = root.drives[index]
|
|
375
|
+
root.cursor = root.flashRow
|
|
376
|
+
root.parkFocus()
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
// The Flash step: one 37 px row carrying the alert mark, the erase line and the action.
|
|
380
|
+
Flea.FlashStepRow {
|
|
381
|
+
id: stepRow
|
|
382
|
+
width: parent.width
|
|
383
|
+
transfer: root.transfer
|
|
384
|
+
rate: root.rate
|
|
385
|
+
words: root.words
|
|
386
|
+
live: root.live
|
|
387
|
+
running: root.running
|
|
388
|
+
ending: root.ending
|
|
389
|
+
ejected: root.ejected
|
|
390
|
+
cursor: root.cursor === root.flashRow
|
|
391
|
+
focused: root.activeFocus
|
|
392
|
+
onPressFlash: root.pressFlash()
|
|
393
|
+
onPressCancel: root.pressCancel()
|
|
394
|
+
onPressEnd: root.pressEnd()
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
package/ui/FleaMark.qml
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import QtQuick
|
|
2
|
+
import QtQuick.Shapes
|
|
3
|
+
import "js/Motion.js" as Motion
|
|
4
|
+
|
|
5
|
+
// Flea's own mark: the Omarchy spiral redrawn as a 24-grid stroke glyph, per BrandMoments.dc.html's
|
|
6
|
+
// "The mark" cell. It paints itself in from blank and then holds. The caller drives the repeat, so
|
|
7
|
+
// the empty state's mark and its caption share one beat; the loading crawl (ui/Spinner.qml) stays a
|
|
8
|
+
// separate gesture on purpose, continuous where this one arrives and rests.
|
|
9
|
+
Item {
|
|
10
|
+
id: root
|
|
11
|
+
|
|
12
|
+
property color color: Theme.color.mutedFrame
|
|
13
|
+
// The mark draws on the same 24 unit grid as every Glyph, scaled to the slot.
|
|
14
|
+
readonly property real grid: 24
|
|
15
|
+
readonly property real markScale: Math.min(root.width, root.height) / root.grid
|
|
16
|
+
// The path below sums to this along its centreline: 18+18+18+14+14+10+10+6+6.
|
|
17
|
+
readonly property real markUnits: 114
|
|
18
|
+
// A brand mark, not a cut glyph: the spiral keeps the brand's 2 and is exempt from Theme.strokeWidth on purpose.
|
|
19
|
+
readonly property real brandStroke: 2
|
|
20
|
+
// QML dash units are strokeWidth multiples, so the whole mark is this many dashes long.
|
|
21
|
+
readonly property real markDashes: root.markUnits / root.brandStroke
|
|
22
|
+
readonly property bool settled: !draw.running && stroke.dashOffset === 0 && root.opacity === 1
|
|
23
|
+
|
|
24
|
+
// Repaints the mark from blank. EmptyState calls this off the caption's own timer so the two run
|
|
25
|
+
// on one beat; a second timer in here would drift against that one and read as sloppy.
|
|
26
|
+
function replay() {
|
|
27
|
+
if (Theme.reducedMotion) {
|
|
28
|
+
draw.stop()
|
|
29
|
+
stroke.dashOffset = 0
|
|
30
|
+
root.opacity = 1
|
|
31
|
+
} else draw.restart()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// A data-held folder lands whole, the settled frame the picture hold revealed.
|
|
35
|
+
function settle() { draw.stop(); stroke.dashOffset = 0; root.opacity = 1 }
|
|
36
|
+
|
|
37
|
+
Shape {
|
|
38
|
+
width: root.grid
|
|
39
|
+
height: root.grid
|
|
40
|
+
x: (root.width - root.grid * root.markScale) / 2
|
|
41
|
+
y: (root.height - root.grid * root.markScale) / 2
|
|
42
|
+
preferredRendererType: Shape.CurveRenderer
|
|
43
|
+
transform: Scale { xScale: root.markScale; yScale: root.markScale }
|
|
44
|
+
|
|
45
|
+
ShapePath {
|
|
46
|
+
id: stroke
|
|
47
|
+
strokeColor: root.color
|
|
48
|
+
fillColor: "transparent"
|
|
49
|
+
strokeWidth: root.brandStroke
|
|
50
|
+
capStyle: ShapePath.SquareCap
|
|
51
|
+
joinStyle: ShapePath.MiterJoin
|
|
52
|
+
strokeStyle: ShapePath.DashLine
|
|
53
|
+
// One dash and one gap, each the whole mark, so only ever one dash can sit on the path.
|
|
54
|
+
dashPattern: [root.markDashes, root.markDashes]
|
|
55
|
+
// A whole mark of offset draws nothing; the animation walks that back to zero.
|
|
56
|
+
dashOffset: root.markDashes
|
|
57
|
+
PathSvg { path: "M21 21H3V3h18v14H7V7h10v6h-6" }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// BrandMoments.dc.html's draw timing, 0.2s delay then 1.8s; OutCubic replaces its cubic-bezier(0.4, 0, 0.2, 1), the motion choice of 2026-09-25.
|
|
62
|
+
SequentialAnimation {
|
|
63
|
+
id: draw
|
|
64
|
+
// The caption's own fade-out, so a repeat dissolves the finished mark rather than cutting it.
|
|
65
|
+
NumberAnimation { target: root; property: "opacity"; to: 0.0; duration: Motion.durMs.close; easing.type: Easing.OutCubic }
|
|
66
|
+
// Blank before opacity comes back, never after: an offset of a whole mark is what hides the seam.
|
|
67
|
+
PropertyAction { target: stroke; property: "dashOffset"; value: root.markDashes }
|
|
68
|
+
PropertyAction { target: root; property: "opacity"; value: 1.0 }
|
|
69
|
+
PauseAnimation { duration: 200 }
|
|
70
|
+
NumberAnimation {
|
|
71
|
+
target: stroke
|
|
72
|
+
property: "dashOffset"
|
|
73
|
+
from: root.markDashes
|
|
74
|
+
to: 0
|
|
75
|
+
duration: 1800
|
|
76
|
+
easing.type: Easing.OutCubic
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// The draw is the entrance as well as the loop, so it runs on every appearance; Item.visible reads effective visibility, so a hidden ancestor holds it back too.
|
|
81
|
+
onVisibleChanged: if (root.visible) root.replay(); else draw.stop()
|
|
82
|
+
// visible can already be true at creation, and onVisibleChanged never fires for that.
|
|
83
|
+
Component.onCompleted: if (root.visible) root.replay()
|
|
84
|
+
Connections {
|
|
85
|
+
target: Theme
|
|
86
|
+
function onReducedMotionChanged() { if (Theme.reducedMotion) root.replay() }
|
|
87
|
+
}
|
|
88
|
+
}
|