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,39 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
.import "Format.js" as Format
|
|
4
|
+
.import "Ops.js" as Ops
|
|
5
|
+
|
|
6
|
+
// The sentences that carry a name or a reason, each filled by Format.fill.
|
|
7
|
+
var WORDS = {
|
|
8
|
+
sending: "Sending %1 to %2 with LocalSend",
|
|
9
|
+
reason: "LocalSend · %1"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Directive 71's three sentences, kept out of the QML so the wording is tested rather than read off
|
|
13
|
+
// a screenshot. The dispatch, the verdict the CLI came back with, and the one refusal Flea itself
|
|
14
|
+
// can hit: a row whose binary left between the menu opening and the peer being chosen.
|
|
15
|
+
// The one call ui/Pane.qml makes: the service either took the send or the CLI is gone.
|
|
16
|
+
function send(pane, service, provider, peer, paths) {
|
|
17
|
+
// A refusal is one of two things and they are not the same sentence: nothing to send, or no CLI
|
|
18
|
+
// to send it with. Blaming the CLI for an empty pick told the user a binary was gone while it sat on PATH.
|
|
19
|
+
if (paths.length === 0) { pane.message("There is nothing to send.", true); return }
|
|
20
|
+
if (!service.send(peer, paths)) { pane.message(missing(provider), true); return }
|
|
21
|
+
pane.message(sending(peer, paths), false)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function sending(peer, paths) {
|
|
25
|
+
if (paths.length === 1)
|
|
26
|
+
return Format.fill(WORDS.sending, Ops.leaf(paths[0]), peer)
|
|
27
|
+
return Format.fill(WORDS.sending, Ops.items(paths.length), peer)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// The CLI ends its own run when the transfer does, so this is the only result Flea ever knows.
|
|
31
|
+
function verdict(ok, reason) {
|
|
32
|
+
if (ok) return "LocalSend finished the transfer."
|
|
33
|
+
return reason && reason.length > 0 ? Format.fill(WORDS.reason, reason) : "LocalSend could not finish the transfer."
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function missing(provider) {
|
|
37
|
+
return provider && provider.reason ? Format.fill(WORDS.reason, provider.reason)
|
|
38
|
+
: "localsend-cli is no longer installed."
|
|
39
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
.import "Menu.js" as Menu
|
|
4
|
+
.import "Errors.js" as Errors
|
|
5
|
+
.import "StateWords.js" as StateWords
|
|
6
|
+
|
|
7
|
+
// The Locked tile's own menu, issue 193 follow-up (2026-09-24). A right click on the
|
|
8
|
+
// tile names the locked folder itself, never the parent behind it, so only rows that act
|
|
9
|
+
// on that folder without listing it are offered: terminal, permissions and path. Kept in
|
|
10
|
+
// ui/js/Menu.js INVENTORY order, one group, so the menu never reorders under its caller.
|
|
11
|
+
// For 0.3.8: the tile keeps its single Copy path row, acting as before,
|
|
12
|
+
// while its visibility follows the Copy as switch that replaced Copy path in Settings > Menus.
|
|
13
|
+
// A Places row's menu keeps the flat row the same way (ui/js/Menu.js availableEntry).
|
|
14
|
+
var LOCKED_IDS = ["openTerminal", "permissions", "copyAs"]
|
|
15
|
+
|
|
16
|
+
// The bar's sentence when every locked id is hidden, naming the switch that brings them back.
|
|
17
|
+
var LOCKED_REFUSAL = "Open in terminal, Permissions and Copy as are hidden in Settings > Menus."
|
|
18
|
+
|
|
19
|
+
// Sample input: { lockedMode: 0o040700, hiddenActions: [] }
|
|
20
|
+
function lockedEntries(p) {
|
|
21
|
+
var out = [], group = ""
|
|
22
|
+
var scoped = { rowMode: p.lockedMode, selectionCount: 1, hiddenActions: p.hiddenActions }
|
|
23
|
+
for (var i = 0; i < Menu.INVENTORY.length; i++) {
|
|
24
|
+
var spec = Menu.INVENTORY[i]
|
|
25
|
+
if (LOCKED_IDS.indexOf(spec[0]) < 0 || Menu.isHidden(p.hiddenActions, spec[0])) continue
|
|
26
|
+
// The Copy as spec lends its inventory slot and its hidden switch; the row it draws
|
|
27
|
+
// is still the flat Copy path row, which ui/Pane.qml performLocked answers with copyText.
|
|
28
|
+
var id = spec[0] === "copyAs" ? "copypath" : spec[0]
|
|
29
|
+
var entry = { id: id, action: id, label: spec[0] === "copyAs" ? "Copy path" : spec[1], glyph: spec[2] }
|
|
30
|
+
if (!Menu.availableEntry(entry, scoped, "F")) continue
|
|
31
|
+
if (entry.action === "permissions") {
|
|
32
|
+
var permission = lockedPermissions(p.lockedMode)
|
|
33
|
+
entry.disabled = permission.disabled
|
|
34
|
+
if (permission.errored) { entry.errored = true; if (permission.hint) entry.hint = permission.hint }
|
|
35
|
+
else { delete entry.errored; delete entry.hint }
|
|
36
|
+
}
|
|
37
|
+
if (out.length && group !== spec[4]) out.push({ separator: true })
|
|
38
|
+
group = spec[4]
|
|
39
|
+
out.push(entry)
|
|
40
|
+
}
|
|
41
|
+
return out
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Sample input: { lockedMode: 0o040700, hiddenActions: ["openTerminal", "permissions", "copyAs"] }
|
|
45
|
+
function lockedRefusal(p) {
|
|
46
|
+
return lockedEntries(p).length === 0 ? LOCKED_REFUSAL : ""
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// The mode is the locked directory's own, so ownership decides: a denial on owner-readable
|
|
50
|
+
// owner-executable proves somebody else owns it, and nobody but the owner can chmod it back,
|
|
51
|
+
// which reads red with its state word, the way a provider that cannot answer does. An owner
|
|
52
|
+
// locked out too may still be the owner, so that row stays plain: it is the way back in.
|
|
53
|
+
function lockedPermissions(mode) {
|
|
54
|
+
var kind = (Number(mode) || 0) & 0o170000
|
|
55
|
+
if (kind !== 0o100000 && kind !== 0o040000) {
|
|
56
|
+
var bad = { disabled: true, errored: true }
|
|
57
|
+
var word = StateWords.permissions(mode)
|
|
58
|
+
if (word) bad.hint = word
|
|
59
|
+
return bad
|
|
60
|
+
}
|
|
61
|
+
if (Errors.notYours(mode)) return { disabled: true, errored: true, hint: StateWords.WORDS.permissionsNotYours }
|
|
62
|
+
return { disabled: false }
|
|
63
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// Settings > About's Make Flea the default: which state the row is in, the note under it and what a press runs; ui/DefaultClaim.qml runs the processes.
|
|
4
|
+
|
|
5
|
+
.import "Format.js" as Format
|
|
6
|
+
|
|
7
|
+
// Whole sentences with "%1" for the program that never started, its name and not its command line.
|
|
8
|
+
var WORDS = {
|
|
9
|
+
unstarted: "%1 could not start"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// The row's id, which ui/SettingsPanel.qml routes to the run instead of writing it into ui.json.
|
|
13
|
+
var ROW_ID = "makeDefault"
|
|
14
|
+
// The entry flea --default points the desktop at; the box is ticked exactly when xdg-mime answers it.
|
|
15
|
+
var DESKTOP_ID = "com.thisisgm.flea.desktop"
|
|
16
|
+
// src/main.rs claim_both() says this and still exits 0 when a build has no flea.portal to route file dialogs to.
|
|
17
|
+
var SKIPPED = "no file chooser service is installed, so Flea could not become the file chooser"
|
|
18
|
+
// src/defaults.rs EXIT_UNINSTALLED: the status claim() exits with when the running binary has no desktop entry to point at.
|
|
19
|
+
var UNINSTALLED_STATUS = 3
|
|
20
|
+
// The portal reads its routing once, at startup; try-restart leaves a portal that is not running alone.
|
|
21
|
+
var RESTART = ["systemctl", "--user", "try-restart", "xdg-desktop-portal.service"]
|
|
22
|
+
// flea's own stderr lines start with its name, which the note drops.
|
|
23
|
+
var OWN_PREFIX = "flea: "
|
|
24
|
+
|
|
25
|
+
// Nothing run in this process yet; an entry is assumed until the probe or a refusal says otherwise.
|
|
26
|
+
function idle() {
|
|
27
|
+
return { running: false, claiming: false, reading: false, readFrom: 0, restarting: false, outcome: "", error: "", packaged: true }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// A run in flight, or a build with no entry, takes no press.
|
|
31
|
+
function inert(claim) {
|
|
32
|
+
return claim.running || claim.packaged === false
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// flea's arguments for a press, or null while the row is inert.
|
|
36
|
+
function press(handler, claim) {
|
|
37
|
+
if (inert(claim))
|
|
38
|
+
return null
|
|
39
|
+
return handler === DESKTOP_ID ? ["--default", "off"] : ["--default"]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// A new run drops the last one's outcome; which way it goes picks the working note.
|
|
43
|
+
function started(claim, args) {
|
|
44
|
+
return { running: true, claiming: args.length === 1, reading: false, readFrom: 0, restarting: false, outcome: "", error: "",
|
|
45
|
+
packaged: claim.packaged }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Still running until a handler read numbered nextRead or later lands and a switch that went through has restarted the portal.
|
|
49
|
+
// Sample stderr: "flea: no file chooser service is installed, so Flea could not become the file chooser\n"
|
|
50
|
+
function finished(claim, code, stderr, nextRead) {
|
|
51
|
+
var text = stderr || ""
|
|
52
|
+
var next = Object.assign({}, claim, { reading: true, readFrom: nextRead, restarting: code === 0 })
|
|
53
|
+
if (code === 0) {
|
|
54
|
+
next.outcome = text.indexOf(SKIPPED) >= 0 ? "partly" : ""
|
|
55
|
+
return next
|
|
56
|
+
}
|
|
57
|
+
if (code === UNINSTALLED_STATUS) {
|
|
58
|
+
next.packaged = false
|
|
59
|
+
return next
|
|
60
|
+
}
|
|
61
|
+
next.outcome = "failed"
|
|
62
|
+
next.error = errorLine(text, code, claim.claiming)
|
|
63
|
+
return next
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// xdg-mime's stderr reaches flea's own, so flea's line is the one that starts with its name.
|
|
67
|
+
// Sample stderr: "xdg-mime: no method available\nflea: xdg-mime default exited 3\n"
|
|
68
|
+
function errorLine(stderr, code, claiming) {
|
|
69
|
+
var lines = stderr.split("\n").map(function (line) { return line.trim() })
|
|
70
|
+
var own = lines.filter(function (line) { return line.indexOf(OWN_PREFIX) === 0 })[0]
|
|
71
|
+
if (own !== undefined)
|
|
72
|
+
return own.substring(OWN_PREFIX.length)
|
|
73
|
+
var first = lines.filter(function (line) { return line.length > 0 })[0]
|
|
74
|
+
return first !== undefined ? first : (claiming ? "flea --default" : "flea --default off") + " exited " + code
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// The handler read numbered read has landed; only one begun after the run exited ends it, and only once the portal restart has answered too.
|
|
78
|
+
function settled(claim, read) {
|
|
79
|
+
if (!claim.reading || read < claim.readFrom)
|
|
80
|
+
return claim
|
|
81
|
+
return Object.assign({}, claim, { reading: false, running: claim.restarting })
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// A Process's exit and its collector's text land in either order (AGENTS.md "The state file"), so an answer is read once it holds both.
|
|
85
|
+
// Sample: landed(landed({}, { code: 0 }), { text: "com.thisisgm.flea.desktop\n" }) is { code: 0, text: "com.thisisgm.flea.desktop\n" }
|
|
86
|
+
function landed(answer, half) {
|
|
87
|
+
return Object.assign({}, answer, half)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// An empty text is an answer too: a run that says nothing has still finished saying it.
|
|
91
|
+
function whole(answer) {
|
|
92
|
+
return answer.code !== undefined && answer.text !== undefined
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// The whole answer a program that never started is given: no real exit status is negative.
|
|
96
|
+
var NEVER_RAN = { code: -1, text: "" }
|
|
97
|
+
|
|
98
|
+
// ui/ViewState.qml's writer rule, measured on Quickshell 0.3.1: a program that cannot start raises no exited, only running going false, and a real exit lands its status before that false.
|
|
99
|
+
function neverRan(answer, running) {
|
|
100
|
+
return !running && answer.code === undefined
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// The handler an answer states; any other status, a read that never ran among them, states none, which About shows as Not reported.
|
|
104
|
+
function handlerOf(answer) {
|
|
105
|
+
return answer.code === 0 ? answer.text.trim() : ""
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// A run whose program never started wrote nothing, so it is over at once, failed, naming what could not start.
|
|
109
|
+
// Sample command: ["/usr/bin/flea", "--default"]
|
|
110
|
+
function unstarted(claim, command) {
|
|
111
|
+
return Object.assign({}, claim, { running: false, reading: false, restarting: false, outcome: "failed",
|
|
112
|
+
error: Format.fill(WORDS.unstarted, String(command[0]).split("/").pop()) })
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// A portal that would not restart keeps the switch as it went; partly keeps its own note, whose dialogs never follow.
|
|
116
|
+
function restarted(claim, ok) {
|
|
117
|
+
var outcome = !ok && claim.outcome === "" ? "portal" : claim.outcome
|
|
118
|
+
return Object.assign({}, claim, { restarting: false, running: claim.reading, outcome: outcome })
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// restarted() clears restarting on a real exit before running goes false, so a stop that finds it still set is a systemctl that never ran.
|
|
122
|
+
function restartStopped(claim, running) {
|
|
123
|
+
return !running && claim.restarting ? restarted(claim, false) : claim
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function probed(claim, found) {
|
|
127
|
+
return Object.assign({}, claim, { packaged: found })
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// One of off, on, working, partly, portal, failed, unpackaged.
|
|
131
|
+
function state(handler, claim) {
|
|
132
|
+
if (claim.packaged === false)
|
|
133
|
+
return "unpackaged"
|
|
134
|
+
if (claim.running)
|
|
135
|
+
return "working"
|
|
136
|
+
if (claim.outcome === "failed")
|
|
137
|
+
return "failed"
|
|
138
|
+
if (handler === DESKTOP_ID && claim.outcome === "partly")
|
|
139
|
+
return "partly"
|
|
140
|
+
if (claim.outcome === "portal")
|
|
141
|
+
return "portal"
|
|
142
|
+
return handler === DESKTOP_ID ? "on" : "off"
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// [words, role] for the one line under the row, or null when off says nothing.
|
|
146
|
+
function note(handler, claim) {
|
|
147
|
+
var now = state(handler, claim)
|
|
148
|
+
if (now === "on")
|
|
149
|
+
return ["Folders, Show in folder and file dialogs open Flea.", "foreground"]
|
|
150
|
+
if (now === "working")
|
|
151
|
+
return [claim.claiming ? "Making Flea the default" : "Handing folders back", "muted"]
|
|
152
|
+
if (now === "partly")
|
|
153
|
+
return ["File dialogs need the flea package's portal files.", "foreground"]
|
|
154
|
+
if (now === "portal")
|
|
155
|
+
return ["File dialogs follow after xdg-desktop-portal restarts.", "foreground"]
|
|
156
|
+
if (now === "failed")
|
|
157
|
+
return [claim.error, "error"]
|
|
158
|
+
if (now === "unpackaged")
|
|
159
|
+
return ["Install a Flea package to make it the default.", "foreground"]
|
|
160
|
+
return null
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// The check row and its note for About's This box group; the note elides on one line rather than wrapping.
|
|
164
|
+
function rows(handler, claim) {
|
|
165
|
+
var live = claim || idle()
|
|
166
|
+
var out = [{ kind: "check", id: ROW_ID, label: "Make Flea the default", on: handler === DESKTOP_ID, inert: inert(live) }]
|
|
167
|
+
var line = note(handler, live)
|
|
168
|
+
if (line !== null)
|
|
169
|
+
out.push({ kind: "hint", label: line[0], role: line[1], elide: "right" })
|
|
170
|
+
return out
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/userfile.rs data_file()'s ladder: the data home, then every data dir, an empty variable read as unset.
|
|
174
|
+
// Sample env: { HOME: "/home/gm", XDG_DATA_HOME: "", XDG_DATA_DIRS: "/usr/local/share:/usr/share" }
|
|
175
|
+
function entryPaths(env) {
|
|
176
|
+
var home = env.XDG_DATA_HOME || (env.HOME ? env.HOME + "/.local/share" : "")
|
|
177
|
+
var dirs = (env.XDG_DATA_DIRS || "/usr/local/share:/usr/share").split(":")
|
|
178
|
+
return [home].concat(dirs)
|
|
179
|
+
.filter(function (dir) { return dir.length > 0 })
|
|
180
|
+
.map(function (dir) { return dir + "/applications/" + DESKTOP_ID })
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// data_file()'s regular-file test; each path is an argument, so no path reaches the shell as code.
|
|
184
|
+
function probeCommand(paths) {
|
|
185
|
+
return ["sh", "-c", "for f; do [ -f \"$f\" ] && exit 0; done; exit 1", "sh"].concat(paths)
|
|
186
|
+
}
|
package/ui/js/MarkBox.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// The picker's mark box: bodySmall plus a hairline inside a two-hairline border, which a Rectangle's size includes.
|
|
4
|
+
// Sample input: outer(13, 1) === 18.
|
|
5
|
+
function inner(bodySmall, hairline) { return bodySmall + hairline }
|
|
6
|
+
function border(hairline) { return 2 * hairline }
|
|
7
|
+
function outer(bodySmall, hairline) { return inner(bodySmall, hairline) + 2 * border(hairline) }
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
.import "Format.js" as Format
|
|
4
|
+
.import "MdUrl.js" as MdUrl
|
|
5
|
+
.import "MdHtml.js" as MdHtml
|
|
6
|
+
.import "MdResolve.js" as Resolve
|
|
7
|
+
.import "MdBlocks.js" as Blocks
|
|
8
|
+
|
|
9
|
+
// Markdown's stable API: remote images become a placeholder, only files inside the document folder load.
|
|
10
|
+
|
|
11
|
+
// Whole sentences with "%1" for a value, filled by fill so each translates as one.
|
|
12
|
+
var WORDS = {
|
|
13
|
+
deepNotice: "This file nests deeper than %1 levels, so Flea shows its source."
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
var RENDERED = "rendered"
|
|
17
|
+
var SOURCE = "source"
|
|
18
|
+
|
|
19
|
+
// Deeper nesting than this shows the source behind one notice.
|
|
20
|
+
var NESTING_LIMIT = Blocks.NESTING_LIMIT
|
|
21
|
+
|
|
22
|
+
function deepNotice() {
|
|
23
|
+
return Format.fill(WORDS.deepNotice, NESTING_LIMIT)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Only these three schemes open in the default application; relative links, anchors and every other scheme open nothing.
|
|
27
|
+
function isExternalLink(url) {
|
|
28
|
+
return Resolve.isExternalLink(url)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function dirOf(path) {
|
|
32
|
+
return MdUrl.dirOf(path)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function placeholder(host) {
|
|
36
|
+
return MdUrl.placeholder(host)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function lineCount(text) {
|
|
40
|
+
var body = String(text)
|
|
41
|
+
// Match src/backend/linecount.rs: a trailing LF ends a line; only an unterminated tail adds one.
|
|
42
|
+
return body.length === 0 ? 0 : body.split("\n").length - (body.endsWith("\n") ? 1 : 0)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function countLine(n) {
|
|
46
|
+
return n === 1 ? "1 line" : Format.count(n) + " lines"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// A big document's first screen draws from this many blocks, which the worker sends ahead of the rest.
|
|
50
|
+
var HEAD_BLOCKS = 96
|
|
51
|
+
|
|
52
|
+
function blocks(source, dir, chrome, ink) {
|
|
53
|
+
return Blocks.blocks(source, dir, chrome, ink)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// The deep verdict reads this many bytes of the head at most: the pass is forward only, so a head that nests too deep is deep in the whole text.
|
|
57
|
+
var DEEP_HEAD_BYTES = 16384
|
|
58
|
+
|
|
59
|
+
// Sample: "> ".repeat(400) + "x" answers { deep: true, scanned: 801 }; a head that never nests too deep answers deep false.
|
|
60
|
+
function deepHead(source) {
|
|
61
|
+
var head = String(source)
|
|
62
|
+
if (head.length > DEEP_HEAD_BYTES)
|
|
63
|
+
head = head.slice(0, Math.max(0, head.lastIndexOf("\n", DEEP_HEAD_BYTES)))
|
|
64
|
+
var state = Blocks.referenceState()
|
|
65
|
+
Blocks.blockPass(MdHtml.documentText(head).split("\n"), state, undefined, true)
|
|
66
|
+
return { deep: state.deep === true, scanned: head.length }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// The one block a document nested too deep parses to, so a deep head lands it with no parse of the text.
|
|
70
|
+
function deepBlocks() {
|
|
71
|
+
return [{ type: "deep", limit: NESTING_LIMIT }]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// The Source view lays out chunks of whole lines about this many characters long, so a screenful of a large file costs a few chunks.
|
|
75
|
+
var SOURCE_CHUNK_CHARS = 4096
|
|
76
|
+
// No chunk is longer than this: a line that runs past it is cut at its last space past SOURCE_CHUNK_CHARS, or at the limit when it has none.
|
|
77
|
+
var SOURCE_CHUNK_MAX = 2 * SOURCE_CHUNK_CHARS
|
|
78
|
+
|
|
79
|
+
// A high surrogate that ends a hard cut steps the cut back one unit, so no chunk splits an astral pair.
|
|
80
|
+
var HIGH_FIRST = 0xD800
|
|
81
|
+
var HIGH_LAST = 0xDBFF
|
|
82
|
+
|
|
83
|
+
// Sample: 20000 chars in lines of 100 answers [0, 4100, 8200, 12300]; a short line straddling the window ends before it, an 8192-char line ends at its newline, a spaceless astral run steps back off a split pair.
|
|
84
|
+
function sourceChunkStarts(text) {
|
|
85
|
+
var starts = [0]
|
|
86
|
+
var from = 0
|
|
87
|
+
while (text.length - from > SOURCE_CHUNK_MAX) {
|
|
88
|
+
var cut = text.indexOf("\n", from + SOURCE_CHUNK_CHARS)
|
|
89
|
+
var next
|
|
90
|
+
if (cut >= 0 && cut <= from + SOURCE_CHUNK_MAX) {
|
|
91
|
+
next = cut + 1
|
|
92
|
+
} else {
|
|
93
|
+
var back = text.lastIndexOf("\n", from + SOURCE_CHUNK_CHARS - 1)
|
|
94
|
+
if (back > from) {
|
|
95
|
+
next = back + 1
|
|
96
|
+
} else {
|
|
97
|
+
var space = text.lastIndexOf(" ", from + SOURCE_CHUNK_MAX - 1)
|
|
98
|
+
next = space >= from + SOURCE_CHUNK_CHARS ? space + 1 : from + SOURCE_CHUNK_MAX
|
|
99
|
+
if (next === from + SOURCE_CHUNK_MAX) {
|
|
100
|
+
var unit = text.charCodeAt(next - 1)
|
|
101
|
+
if (unit >= HIGH_FIRST && unit <= HIGH_LAST) {
|
|
102
|
+
next--
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
starts.push(next)
|
|
108
|
+
from = next
|
|
109
|
+
}
|
|
110
|
+
return starts
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Chunk i without the newline that ends it, if one does; a cut inside a line drops nothing, so the chunks are the text again.
|
|
114
|
+
function sourceChunk(text, starts, i) {
|
|
115
|
+
var end = i + 1 < starts.length ? starts[i + 1] : text.length
|
|
116
|
+
if (i + 1 < starts.length && text.charAt(end - 1) === "\n")
|
|
117
|
+
end--
|
|
118
|
+
return text.slice(starts[i], end)
|
|
119
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// MarkdownLists: where each entry of a list block draws, from the parser's depths, markers and gaps.
|
|
4
|
+
|
|
5
|
+
// Unordered markers by depth are disc, circle, square (U+2022, U+25E6, U+25AA), then square for deeper levels.
|
|
6
|
+
var BULLETS = ["•", "◦", "▪"]
|
|
7
|
+
var ORDERED_START = /^\d/
|
|
8
|
+
|
|
9
|
+
function bulletAt(depth) {
|
|
10
|
+
return BULLETS[Math.min(depth, BULLETS.length - 1)]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Sample input: a "-" entry at depth 0 under an open ordered run changes the marker kind, so fresh(false, 0) opens the run it joins.
|
|
14
|
+
// The answer is the run the entry joins, stored at open[depth] with open cut to that depth; fresh builds each caller's own run record.
|
|
15
|
+
function runStep(open, previous, depth, given, listOrdered, fresh) {
|
|
16
|
+
var run = open[depth]
|
|
17
|
+
var ordered = given === "" ? (run !== undefined ? run.ordered : listOrdered) : ORDERED_START.test(given)
|
|
18
|
+
// A deeper entry opens a list under the item above, and a changed marker kind starts a list beside the old one.
|
|
19
|
+
if (run === undefined || depth > previous || ordered !== run.ordered)
|
|
20
|
+
run = fresh(ordered, depth)
|
|
21
|
+
open.length = depth
|
|
22
|
+
open[depth] = run
|
|
23
|
+
return run
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Sample input: items a (depth 0) and b (depth 1) answer cells at x 0 and at a's marker width plus spacing.
|
|
27
|
+
// advance(text) is the marker font's advance width; spacing is the gap between a marker and its text.
|
|
28
|
+
function layout(block, advance, spacing) {
|
|
29
|
+
var count = block.items.length
|
|
30
|
+
var out = []
|
|
31
|
+
var runs = []
|
|
32
|
+
var open = []
|
|
33
|
+
var previous = -1
|
|
34
|
+
var bullet = advance(BULLETS[0])
|
|
35
|
+
// The marker a run's column is sized by: the parser's own for an ordered run, the depth's bullet for the rest.
|
|
36
|
+
function widest(held, depth) {
|
|
37
|
+
return held.ordered ? held.marker : bulletAt(depth)
|
|
38
|
+
}
|
|
39
|
+
// A run opens under the run one depth up, and is listed so the column pass below can place it.
|
|
40
|
+
function opened(ordered, depth) {
|
|
41
|
+
var run = { depth: depth, ordered: ordered, width: 0, parent: depth > 0 ? open[depth - 1] : undefined, x: 0 }
|
|
42
|
+
runs.push(run)
|
|
43
|
+
return run
|
|
44
|
+
}
|
|
45
|
+
// A chunk opens under the runs the list had open before it, each at the column the whole list gives it.
|
|
46
|
+
var carry = block.carry !== undefined ? block.carry : []
|
|
47
|
+
for (var c = 0; c < carry.length; c++) {
|
|
48
|
+
var held = { depth: c, ordered: carry[c].ordered, width: advance(widest(carry[c], c)), parent: c > 0 ? open[c - 1] : undefined, x: 0 }
|
|
49
|
+
runs.push(held)
|
|
50
|
+
open[c] = held
|
|
51
|
+
previous = c
|
|
52
|
+
}
|
|
53
|
+
for (var k = 0; k < count; k++) {
|
|
54
|
+
var depth = block.depths !== undefined ? block.depths[k] : 0
|
|
55
|
+
var given = block.markers !== undefined ? block.markers[k] : block.ordered ? (block.start + k) + "." : BULLETS[0]
|
|
56
|
+
var run = runStep(open, previous, depth, given, block.ordered, opened)
|
|
57
|
+
var ordered = run.ordered
|
|
58
|
+
var marker = given === "" ? "" : ordered ? given : bulletAt(depth)
|
|
59
|
+
run.width = Math.max(run.width, advance(marker))
|
|
60
|
+
// A long list's later chunks keep the first chunk's marker column width, so a chunk's text stays in line with its neighbours.
|
|
61
|
+
if (depth === 0 && ordered && block.last !== undefined)
|
|
62
|
+
run.width = Math.max(run.width, advance(block.last + "."))
|
|
63
|
+
// A joined chunk lies flush under its predecessor, so its first entry keeps the gap the whole list gave it.
|
|
64
|
+
var gap = (k > 0 || block.joined === true) && block.gaps !== undefined && (block.gaps[k] || (k > 0 && depth > previous && block.gaps[k - 1]))
|
|
65
|
+
out.push({ x: 0, w: 0, marker: marker, gap: gap === true, run: run })
|
|
66
|
+
previous = depth
|
|
67
|
+
}
|
|
68
|
+
// The runs still open at the chunk's end take the column the whole list gives them, which a later entry may widen.
|
|
69
|
+
var tail = block.tail !== undefined ? block.tail : []
|
|
70
|
+
for (var t = 0; t < tail.length; t++) {
|
|
71
|
+
if (open[t] !== undefined && open[t].ordered === tail[t].ordered)
|
|
72
|
+
open[t].width = Math.max(open[t].width, advance(widest(tail[t], t)))
|
|
73
|
+
}
|
|
74
|
+
// Parents come before their children in runs, so a run's own column is known when its children read it.
|
|
75
|
+
for (var r = 0; r < runs.length; r++) {
|
|
76
|
+
var at = runs[r]
|
|
77
|
+
// A chunk that opens inside a nested list with nothing carried has no parent here, so each missing level counts one disc column.
|
|
78
|
+
at.x = at.parent !== undefined ? at.parent.x + at.parent.width + spacing : at.depth * (bullet + spacing)
|
|
79
|
+
}
|
|
80
|
+
for (var e = 0; e < out.length; e++) {
|
|
81
|
+
out[e].x = out[e].run.x
|
|
82
|
+
out[e].w = out[e].run.width
|
|
83
|
+
delete out[e].run
|
|
84
|
+
}
|
|
85
|
+
return out
|
|
86
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// MarkdownMaths: an inline formula's SVG as a picture inside a line of Qt rich text, and the code span it replaces.
|
|
4
|
+
var SPAN = /<code data-math="inline"[^>]*>[\s\S]*?<\/code>/g
|
|
5
|
+
var ROOT = /<svg\b[^>]*>/
|
|
6
|
+
// Marks encodeURIComponent leaves bare that break an attribute or a Markdown destination, so they are percent-encoded too.
|
|
7
|
+
var URL_MARKS = /[()'!*~]/g
|
|
8
|
+
var HEX_RADIX = 16
|
|
9
|
+
// A transparent 1 by 1 PNG, and the height a calibration picture of it is laid out at.
|
|
10
|
+
var CLEAR = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
|
|
11
|
+
var CALIBRATION_HEIGHT = 100
|
|
12
|
+
|
|
13
|
+
// Sample input: 'a <code data-math="inline" style="background-color:#222">x^2</code> b' holds one span.
|
|
14
|
+
function spans(html) {
|
|
15
|
+
return String(html).match(SPAN) || []
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Sample input: ('a <code data-math="inline">x</code> b', ['<img src="p">']) answers 'a <img src="p"> b'; an empty picture keeps its code span.
|
|
19
|
+
function compose(html, pictures) {
|
|
20
|
+
var at = 0
|
|
21
|
+
return String(html).replace(SPAN, function (span) {
|
|
22
|
+
var picture = pictures[at++]
|
|
23
|
+
return picture !== undefined && picture !== "" ? picture : span
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function attr(root, name) {
|
|
28
|
+
var m = new RegExp("\\s" + name + "=\"([^\"]*)\"").exec(root)
|
|
29
|
+
return m === null ? null : m[1]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function percent(c) {
|
|
33
|
+
return "%" + c.charCodeAt(0).toString(HEX_RADIX).toUpperCase()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Sample input: svg '<svg width="30px" height="20px" viewBox="0 -15 60 20">' answers an <img> that sits that formula's baseline on the text's, or "" when the root carries no size or svg is "".
|
|
37
|
+
// anchor is how far above the baseline Qt centres a middle-aligned picture in this font; a picture shorter than minTall is padded to it, since a short one is placed otherwise.
|
|
38
|
+
function picture(svg, anchor, minTall) {
|
|
39
|
+
var root = ROOT.exec(svg)
|
|
40
|
+
if (root === null)
|
|
41
|
+
return ""
|
|
42
|
+
var width = parseFloat(attr(root[0], "width"))
|
|
43
|
+
var height = parseFloat(attr(root[0], "height"))
|
|
44
|
+
var box = (attr(root[0], "viewBox") || "").trim().split(/\s+/).map(Number)
|
|
45
|
+
if (!(width > 0) || !(height > 0) || box.length !== 4 || box.some(isNaN) || !(box[3] > 0))
|
|
46
|
+
return ""
|
|
47
|
+
var unit = height / box[3]
|
|
48
|
+
var above = -box[1] * unit
|
|
49
|
+
var below = (box[1] + box[3]) * unit
|
|
50
|
+
var tall = Math.ceil(Math.max(2 * Math.max(above - anchor, below + anchor, 0), minTall))
|
|
51
|
+
// The formula's baseline sits at the picture's centre plus the anchor, whatever its depth.
|
|
52
|
+
var top = tall / 2 + anchor
|
|
53
|
+
var padded = svg.replace(ROOT, root[0]
|
|
54
|
+
.replace(/\sheight="[^"]*"/, " height=\"" + tall + "px\"")
|
|
55
|
+
.replace(/\sviewBox="[^"]*"/, " viewBox=\"" + box[0] + " " + (-top / unit) + " " + box[2] + " " + (tall / unit) + "\""))
|
|
56
|
+
var url = "data:image/svg+xml," + encodeURIComponent(padded).replace(URL_MARKS, percent)
|
|
57
|
+
return "<img src=\"" + url + "\" width=\"" + width + "\" height=\"" + tall + "\" style=\"vertical-align: middle\" />"
|
|
58
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// MarkdownPictures: a Markdown text's inline pictures, read for their addresses and capped at the width the text has.
|
|
4
|
+
var PICTURE = /!\[[^\]]*\]\(([^)\s]*)[^)]*\)/g
|
|
5
|
+
|
|
6
|
+
// Sample input: "`` and " answers ["file:///d/p.png"].
|
|
7
|
+
// Only file: addresses load (the parser leaves every other picture as a placeholder), so a remote address never reaches an Image.
|
|
8
|
+
function urls(source) {
|
|
9
|
+
var found = []
|
|
10
|
+
String(source).replace(PICTURE, function (whole, url) {
|
|
11
|
+
if (/^file:/i.test(url))
|
|
12
|
+
found.push(url)
|
|
13
|
+
return whole
|
|
14
|
+
})
|
|
15
|
+
return found
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Sample input: ("a  b", { "file:///p.png": { w: 160, h: 40 } }, 100) answers text 'a <img src="file:///p.png" width="100" height="25" /> b' and tallest 25.
|
|
19
|
+
// A picture wider than the limit is written as an img tag scaled to it with its ratio kept, and one that fits (or is not decoded yet) stays as it is.
|
|
20
|
+
function fit(source, sizes, limit) {
|
|
21
|
+
var tallest = 0
|
|
22
|
+
var text = String(source).replace(PICTURE, function (whole, url) {
|
|
23
|
+
var size = sizes[url]
|
|
24
|
+
if (size === undefined || size.w <= 0)
|
|
25
|
+
return whole
|
|
26
|
+
var capped = limit > 0 && size.w > limit
|
|
27
|
+
var tall = capped ? Math.max(1, Math.round(size.h * limit / size.w)) : size.h
|
|
28
|
+
tallest = Math.max(tallest, tall)
|
|
29
|
+
return capped ? '<img src="' + url.replace(/"/g, "%22").replace(/&/g, "&") + '" width="' + limit + '" height="' + tall + '" />' : whole
|
|
30
|
+
})
|
|
31
|
+
return { text: text, tallest: tallest }
|
|
32
|
+
}
|