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
package/ui/js/Drag.js
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
.import "DragOut.js" as DragOut
|
|
4
|
+
.import "Search.js" as Search
|
|
5
|
+
.import "Ops.js" as Ops
|
|
6
|
+
.import "Format.js" as Format
|
|
7
|
+
.import "Swap.js" as Swap
|
|
8
|
+
|
|
9
|
+
// A drop is a gesture that calls the transfer request Ops.moveToDropbox already sends, with the folder
|
|
10
|
+
// row under the pointer as its destination, so there is no second copy path here. States.dc.html
|
|
11
|
+
// "Drop target": the hovered folder takes the accent frame and reads "move here", and copy versus
|
|
12
|
+
// move reads in the status bar. ui/List.qml wires the handlers; this file decides.
|
|
13
|
+
|
|
14
|
+
// The rows a drag carries: the whole selection when the pressed row is in it, that row alone when it
|
|
15
|
+
// is not. One file dropped when five were selected is a data surprise; five moved when the operator
|
|
16
|
+
// grabbed one is a worse one, so the pressed row decides which the drag means.
|
|
17
|
+
function carried(pane, index) {
|
|
18
|
+
var picked = pane.selectedIndices()
|
|
19
|
+
for (var i = 0; i < picked.length; i++) {
|
|
20
|
+
if (picked[i] === index) {
|
|
21
|
+
return picked
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return [index]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Ctrl copies, Shift moves, Ctrl with Shift links, read at the lift and again at the drop from the key events DragOut.keys tracks during the drag.
|
|
28
|
+
function copying(modifiers) {
|
|
29
|
+
return (modifiers & Qt.ControlModifier) !== 0
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function shifting(modifiers) {
|
|
33
|
+
return (modifiers & Qt.ShiftModifier) !== 0
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function linking(modifiers) {
|
|
37
|
+
return copying(modifiers) && shifting(modifiers)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// A seen value of 1 is held at the drop, 0 is released before it, and -1 keeps the lift bit.
|
|
41
|
+
function dropHeld(lift, seen) {
|
|
42
|
+
if (seen === 1) return true
|
|
43
|
+
if (seen === 0) return false
|
|
44
|
+
return lift
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Only a directory row takes a drop, and never one the drag itself carries: a folder cannot move into
|
|
48
|
+
// itself, and a selection holding the target is refused whole rather than moved in part.
|
|
49
|
+
function canDrop(rows, index, row) {
|
|
50
|
+
if (!row || row.d !== true) {
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
53
|
+
return rows.indexOf(index) < 0
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Whole sentences with "%1" for the item count and "%2" for the folder name; the keys held at the drop decide copy or move (dropHeld, ui/RowDrag.qml verbAt).
|
|
57
|
+
var WORDS = {
|
|
58
|
+
linkTo: "Link %1 to %2",
|
|
59
|
+
linkToFolder: "Link %1 to a folder",
|
|
60
|
+
copyTo: "Copy %1 to %2",
|
|
61
|
+
copyToFolder: "Copy %1 to a folder",
|
|
62
|
+
moveTo: "Move %1 to %2 · Ctrl copies, Shift moves",
|
|
63
|
+
moveToFolder: "Move %1 to a folder · Ctrl copies, Shift moves"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// The board's own words on the hovered folder.
|
|
67
|
+
function label(copy, link) {
|
|
68
|
+
if (link === true) return "link here"
|
|
69
|
+
return copy ? "copy here" : "move here"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// The hint names the keys held at the drop, so a key pressed after the lift counts once DragOut.keys saw it.
|
|
73
|
+
function line(n, name, copy, link) {
|
|
74
|
+
var named = name.length > 0
|
|
75
|
+
var template = link === true ? (named ? WORDS.linkTo : WORDS.linkToFolder)
|
|
76
|
+
: copy ? (named ? WORDS.copyTo : WORDS.copyToFolder)
|
|
77
|
+
: (named ? WORDS.moveTo : WORDS.moveToFolder)
|
|
78
|
+
return Format.fill(template, Ops.items(n), name)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// The by-index drop is the only path a too-wide selection takes, onto its own listing, with links through the Paste-as-links card.
|
|
82
|
+
function dropByIndex(pane, rows, index, verb, listing) {
|
|
83
|
+
var row = pane.rowFor(index)
|
|
84
|
+
if (!canDrop(rows, index, row)) {
|
|
85
|
+
return false
|
|
86
|
+
}
|
|
87
|
+
var dest = pane.join(Search.baseOf(pane), row.n)
|
|
88
|
+
if (verb === "link") {
|
|
89
|
+
return pane.asks().ask(Swap.named({ c: "link", op: "relative", rows: rows, dest: dest }, listing))
|
|
90
|
+
}
|
|
91
|
+
return pane.asks().ask(Swap.named({ c: "transfer", op: verb, rows: rows, dest: dest }, listing))
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// The type Flea's own drag carries alongside the uri-list. The compositor hands a window's own
|
|
95
|
+
// platform drag back to that window's own DropAreas, so without a marker an internal move would be
|
|
96
|
+
// indistinguishable from a foreign drop, take the always-copy path below, and leave the source behind
|
|
97
|
+
// while still looking like it worked.
|
|
98
|
+
var ROWS_MIME = "application/x-flea-rows"
|
|
99
|
+
|
|
100
|
+
// DragOut rule 4: Flea is the one named receiver of a shelf drag. The payload is the single-use
|
|
101
|
+
// token the shelf minted and the intent it fixed at the lift, in that order, one per line. The token
|
|
102
|
+
// is the authority: the backend reads the entries and the intent out of its own record, and this
|
|
103
|
+
// second line is only so the receiver can say the right word before the drop lands.
|
|
104
|
+
var SHELF_MIME = "application/x-flea-shelf"
|
|
105
|
+
|
|
106
|
+
function shelfToken(payload) {
|
|
107
|
+
return String(payload || "").split("\n")[0]
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function shelfCopying(payload) {
|
|
111
|
+
return String(payload || "").split("\n")[1] === "copy"
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// A value unique to this running Flea. ROWS_MIME names the application, and two Flea windows are two
|
|
115
|
+
// processes: a drag from the other one carries row indices that mean nothing in this listing, so the
|
|
116
|
+
// instance has to be identifiable on its own or the receiver takes the internal path against a
|
|
117
|
+
// selection it never made and the drop does nothing at all.
|
|
118
|
+
var INSTANCE = String(Date.now()) + "-" + String(Math.floor(Math.random() * 1000000000))
|
|
119
|
+
var lifted = { marker: "", backend: null }
|
|
120
|
+
|
|
121
|
+
// False only when the listed directory cannot be written, which makes a same-device drag copy.
|
|
122
|
+
function listingDeletable(pane) {
|
|
123
|
+
return !(pane && pane.backend && pane.backend.dirWritable === false)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// One marker, not two mime types, carrying sender, rows and lift bits (fields: 0 sender, 1 rows, 2 ctrl, 3 source, 4 device, 5 deletable, 6 shift, 7 listing).
|
|
127
|
+
function markerPayload(rows, copy, source, dev, deletable, shift, listing) {
|
|
128
|
+
return INSTANCE + "\n" + rows.join(",") + "\n" + (copy ? "copy" : "move") + "\n" + encodeURIComponent(String(source || "")) + "\n" + String(dev || 0) + "\n" + (deletable === false ? "0" : "1") + "\n" + (shift === true ? "1" : "0") + "\n" + String(listing || 0)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
var MARKER_FIELDS = 8
|
|
132
|
+
var SHIFT_MARKER_FIELDS = 7
|
|
133
|
+
var LEGACY_MARKER_FIELDS = 5
|
|
134
|
+
var DELETABLE_MARKER_FIELDS = 6
|
|
135
|
+
|
|
136
|
+
// Five- and six-field legacy markers have raw paths; current markers percent-encode the path field.
|
|
137
|
+
// Sample input: "foreign\n2\nmove\n%2Ftmp%2Fsource\n56\n1\n1\n7".
|
|
138
|
+
function markerFields(payload) {
|
|
139
|
+
var fields = String(payload).split("\n")
|
|
140
|
+
if ([LEGACY_MARKER_FIELDS, DELETABLE_MARKER_FIELDS, SHIFT_MARKER_FIELDS, MARKER_FIELDS].indexOf(fields.length) < 0)
|
|
141
|
+
return null
|
|
142
|
+
if (!/^-?[0-9]+$/.test(fields[4]) || (fields[2] !== "copy" && fields[2] !== "move")) return null
|
|
143
|
+
if (fields.length >= DELETABLE_MARKER_FIELDS && fields[5] !== "0" && fields[5] !== "1") return null
|
|
144
|
+
if (fields.length >= SHIFT_MARKER_FIELDS) {
|
|
145
|
+
if (fields[6] !== "0" && fields[6] !== "1") return null
|
|
146
|
+
try { decodeURIComponent(fields[3]) } catch (error) { return null }
|
|
147
|
+
}
|
|
148
|
+
if (fields.length === MARKER_FIELDS && !/^[0-9]+$/.test(fields[7])) return null
|
|
149
|
+
return fields
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// The directory the rows were lifted from, and its filesystem, both baked at the lift: a drop that
|
|
153
|
+
// lands after the listing changed under the drag, which hovering a tab now does, cannot use the row
|
|
154
|
+
// indices any more and resolves by path against these instead.
|
|
155
|
+
function markerSource(payload) {
|
|
156
|
+
var fields = markerFields(payload)
|
|
157
|
+
return fields ? (fields.length >= SHIFT_MARKER_FIELDS ? decodeURIComponent(fields[3]) : fields[3]) : ""
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function markerDev(payload) {
|
|
161
|
+
var fields = markerFields(payload)
|
|
162
|
+
return fields ? Number(fields[4]) || 0 : 0
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Legacy markers carry no listing generation and cannot authorize a Trash drop by index.
|
|
166
|
+
function markerListing(payload) {
|
|
167
|
+
var fields = markerFields(payload)
|
|
168
|
+
return fields && fields.length === MARKER_FIELDS ? Number(fields[7]) || 0 : 0
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function markerShift(payload) {
|
|
172
|
+
var fields = markerFields(payload)
|
|
173
|
+
return !!fields && fields[6] === "1"
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Missing means the source can be deleted. Only an explicit 0 copies a same-device drag.
|
|
177
|
+
function markerDeletable(payload) {
|
|
178
|
+
var fields = markerFields(payload)
|
|
179
|
+
return !!fields && fields[5] !== "0"
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Whether the listing under the drop is still the one the rows were lifted from, which is the only
|
|
183
|
+
// case the by-index transfer is safe in.
|
|
184
|
+
function sameListing(payload, path) {
|
|
185
|
+
return isOwnDrag(payload) && markerSource(payload) === path
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Equal listing generations in two pane backends still number different rows.
|
|
189
|
+
function liftedBy(marker, backend) {
|
|
190
|
+
return !!backend && backend === lifted.backend && marker === lifted.marker
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Whether a drag carries at least one local path, which is what decides a drop resolves by path.
|
|
194
|
+
function hasPaths(urls) {
|
|
195
|
+
return DragOut.filePaths(urls).length > 0
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// The by-index drop's gate: only a selection too wide to carry paths takes it, only onto its own
|
|
199
|
+
// listing, and never onto a folder it carries itself.
|
|
200
|
+
function canDropByIndex(marker, path, rows, index) {
|
|
201
|
+
return rows.length > 0 && sameListing(marker, path) && rows.indexOf(index) < 0
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Whether the marked drag was lifted with ctrl down. No marker answers false.
|
|
205
|
+
function markerCopying(payload) {
|
|
206
|
+
var fields = markerFields(payload)
|
|
207
|
+
return !!fields && fields[2] === "copy"
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Whether a marked drag began in this very window. An unmarked drag has no payload and answers false,
|
|
211
|
+
// which is the right answer: something that is not Flea is not this Flea.
|
|
212
|
+
function isOwnDrag(payload) {
|
|
213
|
+
var fields = markerFields(payload)
|
|
214
|
+
return !!fields && fields[0] === INSTANCE
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// A path as a file:// URI. Each component is encoded on its own: encodeURIComponent would escape the
|
|
218
|
+
// separators too, and encodeURI would leave a "#" or a "?" in a filename unescaped.
|
|
219
|
+
function uriFor(path) {
|
|
220
|
+
return Format.fileUri(path)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// What the drag puts on the wire: the marker naming this drag as Flea's own, which the backend
|
|
224
|
+
// resolves by index and which therefore always carries the whole selection, plus a CRLF-separated
|
|
225
|
+
// uri-list for every other application.
|
|
226
|
+
//
|
|
227
|
+
// The uri-list is offered only when every carried row resolves. A selection reaches past the window
|
|
228
|
+
// the client holds and pane.rowFor answers null outside it, so a wide selection cannot be turned into
|
|
229
|
+
// paths here at all; pushing only the rows that happen to be realised is the defect Ops.js records as
|
|
230
|
+
// "a wide move relocated a few files and abandoned the rest", and here it would hand another
|
|
231
|
+
// application a subset while the bar named the whole count. No list at all is refusable and visible.
|
|
232
|
+
// Whether the key is present is also what tells the bar the drag cannot leave Flea.
|
|
233
|
+
function mimeFor(pane, rows, copy, shift) {
|
|
234
|
+
var mime = {}
|
|
235
|
+
mime[ROWS_MIME] = markerPayload(rows, copy, Search.baseOf(pane), pane.backend ? pane.backend.dirDev : 0, listingDeletable(pane), shift === true, pane.backend ? pane.backend.heldListing : 0)
|
|
236
|
+
lifted = { marker: mime[ROWS_MIME], backend: pane.backend || null }
|
|
237
|
+
var uris = []
|
|
238
|
+
var paths = []
|
|
239
|
+
for (var i = 0; i < rows.length; i++) {
|
|
240
|
+
var row = pane.rowFor(rows[i])
|
|
241
|
+
if (!row) {
|
|
242
|
+
return mime
|
|
243
|
+
}
|
|
244
|
+
paths.push(pane.join(Search.baseOf(pane), row.n))
|
|
245
|
+
uris.push(uriFor(paths[paths.length - 1]))
|
|
246
|
+
}
|
|
247
|
+
if (uris.length > 0) {
|
|
248
|
+
mime["text/uri-list"] = uris.join("\r\n") + "\r\n"
|
|
249
|
+
// The rule: a terminal or a text field that takes plain text gets the absolute paths, one a line.
|
|
250
|
+
mime["text/plain"] = paths.join("\n")
|
|
251
|
+
}
|
|
252
|
+
return mime
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// A path drop lands on another directory only, and only with paths to send; same-directory and pathless drops refuse.
|
|
256
|
+
function canDropInto(marker, urls, dest, plain) {
|
|
257
|
+
if (marker && !markerFields(marker)) return false
|
|
258
|
+
// No destination is no drop: a tab with no path for its row and the history's base, which
|
|
259
|
+
// names no folder of its own, both refuse rather than landing wherever "" resolves.
|
|
260
|
+
if (!dest) return false
|
|
261
|
+
// Each path's own folder decides, never the marker's source: a search or Recent row is not a child of its listing's base.
|
|
262
|
+
var paths = DragOut.sources(urls, plain, marker, "")
|
|
263
|
+
return paths.length > 0 && DragOut.refusal(paths, dest, marker, "") === ""
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Path drops transfer through dropVerb, the only verb decision, which reads the drop-time keys over the lift bits for a Flea marker.
|
|
267
|
+
function dropInto(pane, marker, urls, dest, destDev, shelf, plain, proposed, seenCopy, seenShift) {
|
|
268
|
+
// No destination is no drop, even for a shelf drag whose token would otherwise redeem.
|
|
269
|
+
if (!dest) return false
|
|
270
|
+
if (marker && !markerFields(marker)) return false
|
|
271
|
+
var paths = DragOut.sources(urls, plain, marker, shelf)
|
|
272
|
+
if (!canDropInto(marker, urls, dest, plain) && shelfToken(shelf).length === 0) return false
|
|
273
|
+
// Rule 4: a shelf drag is redeemed rather than re-read as a list of URIs, because a fallback to
|
|
274
|
+
// a URI copy after the shelf promised a move is the silent wrong answer it forbids; its URIs only ask first.
|
|
275
|
+
if (shelfToken(shelf).length > 0) {
|
|
276
|
+
return pane.asks().ask({ c: "transfer", op: "", paths: [], dest: dest, shelf: shelfToken(shelf) }, DragOut.filePaths(urls))
|
|
277
|
+
}
|
|
278
|
+
var verb = dropVerb(marker, proposed, destDev, seenCopy, seenShift)
|
|
279
|
+
if (verb === "link") {
|
|
280
|
+
return pane.asks().ask({ c: "link", op: "relative", paths: paths, dest: dest })
|
|
281
|
+
}
|
|
282
|
+
return pane.asks().ask({ c: "transfer", op: verb, paths: paths, dest: dest })
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Marker-less platform action, read here only: move-only shifts, copy-only copies, link-only links, both bits set, or neither, stays plain.
|
|
286
|
+
function foreignHeld(proposed) {
|
|
287
|
+
var moveBit = (proposed & Qt.MoveAction) !== 0
|
|
288
|
+
var copyBit = (proposed & Qt.CopyAction) !== 0
|
|
289
|
+
var linkBit = (proposed & Qt.LinkAction) !== 0
|
|
290
|
+
if (linkBit && !moveBit && !copyBit) return { copy: true, shift: true }
|
|
291
|
+
if (moveBit && !copyBit) return { copy: false, shift: true }
|
|
292
|
+
if (copyBit && !moveBit) return { copy: true, shift: false }
|
|
293
|
+
return { copy: false, shift: false }
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Verb from marker plus drop-time keys: a Flea marker carries the lift's own bits as the baseline and the seen keys override them, a foreign drag follows foreignHeld.
|
|
297
|
+
function dropVerb(marker, proposed, destDev, seenCopy, seenShift) {
|
|
298
|
+
if (marker) {
|
|
299
|
+
return verbFor(isOwnDrag(marker), dropHeld(markerCopying(marker), seenCopy),
|
|
300
|
+
dropHeld(markerShift(marker), seenShift), markerDev(marker), destDev, markerDeletable(marker))
|
|
301
|
+
}
|
|
302
|
+
var held = foreignHeld(proposed)
|
|
303
|
+
return verbFor(false, held.copy, held.shift, 0, destDev, true)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Only verb decision: Ctrl with Shift links and needs no device, Ctrl copies, Shift moves; else same-device moves and unknown-device or undeletable copies.
|
|
307
|
+
function verbFor(own, ctrlHeld, shiftHeld, srcDev, destDev, deletable) {
|
|
308
|
+
void own
|
|
309
|
+
if (ctrlHeld && shiftHeld) return "link"
|
|
310
|
+
if (ctrlHeld) return "copy"
|
|
311
|
+
if (shiftHeld) return "move"
|
|
312
|
+
if (!srcDev || !destDev || deletable === false) return "copy"
|
|
313
|
+
return srcDev === destDev ? "move" : "copy"
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Said beside the drag line when the selection cannot be handed to another application. The internal
|
|
317
|
+
// drop is still whole, so the count stands; this only tells the operator the drag will not leave,
|
|
318
|
+
// which beats a drop that silently does nothing over another window.
|
|
319
|
+
function reachNote(canLeave) {
|
|
320
|
+
return canLeave ? "" : " · too wide to drag out"
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Sample marker "<instance>\n1,3\nmove\n%2Fsource\n42\n1\n0\n7"; feedback never becomes destination row indices.
|
|
324
|
+
function feedbackFor(marker, urls, shelf, proposed) {
|
|
325
|
+
var fields = markerFields(marker) || []
|
|
326
|
+
var own = fields[0] === INSTANCE
|
|
327
|
+
var paths = DragOut.filePaths(urls)
|
|
328
|
+
if (shelfToken(shelf).length > 0) {
|
|
329
|
+
return { own: true, copy: shelfCopying(shelf), dev: 0, fixed: shelfCopying(shelf),
|
|
330
|
+
count: paths.length, canLeave: paths.length > 0 }
|
|
331
|
+
}
|
|
332
|
+
var copy = fields[2] === "copy"
|
|
333
|
+
var shift = fields[6] === "1"
|
|
334
|
+
if (!marker) {
|
|
335
|
+
var held = foreignHeld(proposed)
|
|
336
|
+
copy = held.copy
|
|
337
|
+
shift = held.shift
|
|
338
|
+
}
|
|
339
|
+
return { own: own, copy: copy, shift: shift,
|
|
340
|
+
dev: Number(fields[4]) || 0, deletable: fields[5] !== "0",
|
|
341
|
+
count: own && fields[1] ? fields[1].split(",").length : paths.length,
|
|
342
|
+
canLeave: paths.length > 0 }
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function copyingFor(feedback, destDev) {
|
|
346
|
+
if (!feedback) return true
|
|
347
|
+
return feedback.fixed !== undefined ? feedback.fixed === true
|
|
348
|
+
: verbFor(feedback.own, feedback.copy, feedback.shift, feedback.dev, destDev, feedback.deletable) === "copy"
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function linkingFor(feedback, destDev) {
|
|
352
|
+
if (!feedback || feedback.fixed !== undefined) return false
|
|
353
|
+
return verbFor(feedback.own, feedback.copy, feedback.shift, feedback.dev, destDev, feedback.deletable) === "link"
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function feedbackLine(feedback, name, destDev) {
|
|
357
|
+
if (!feedback || feedback.count === 0) return ""
|
|
358
|
+
var link = linkingFor(feedback, destDev)
|
|
359
|
+
return line(feedback.count, name, !link && copyingFor(feedback, destDev), link) + reachNote(feedback.canLeave)
|
|
360
|
+
}
|
package/ui/js/DragOut.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// Foreign-drop paths and its one refusal sentence; own drags keep their marker and never re-read text/plain.
|
|
4
|
+
function usePlain(marker, shelf) {
|
|
5
|
+
return !marker && !shelf
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Sample input "file:///d/a%20b.txt" answers "/d/a b.txt"; anything else answers null.
|
|
9
|
+
function filePath(url) {
|
|
10
|
+
var text = String(url)
|
|
11
|
+
if (text.indexOf("file://") !== 0) return null
|
|
12
|
+
var rest = text.substring(7)
|
|
13
|
+
var path
|
|
14
|
+
if (rest.charAt(0) === "/") {
|
|
15
|
+
path = rest
|
|
16
|
+
} else {
|
|
17
|
+
var slash = rest.indexOf("/")
|
|
18
|
+
if (slash < 0 || rest.substring(0, slash) !== "localhost") return null
|
|
19
|
+
path = rest.substring(slash)
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
return decodeURIComponent(path)
|
|
23
|
+
} catch (error) {
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function filePaths(urls) {
|
|
29
|
+
var paths = []
|
|
30
|
+
if (!urls) return paths
|
|
31
|
+
for (var i = 0; i < urls.length; i++) {
|
|
32
|
+
var path = filePath(urls[i])
|
|
33
|
+
if (path) paths.push(path)
|
|
34
|
+
}
|
|
35
|
+
return paths
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Sample input "/a/x.txt\nhttp://e/y\n" answers ["/a/x.txt"]; a line not starting with "/" is left behind.
|
|
39
|
+
function plainPaths(plain) {
|
|
40
|
+
var paths = []
|
|
41
|
+
if (!plain) return paths
|
|
42
|
+
var lines = String(plain).split("\n")
|
|
43
|
+
for (var i = 0; i < lines.length; i++) {
|
|
44
|
+
var line = lines[i]
|
|
45
|
+
if (line.charAt(line.length - 1) === "\r") line = line.substring(0, line.length - 1)
|
|
46
|
+
if (line.charAt(0) === "/") paths.push(line)
|
|
47
|
+
}
|
|
48
|
+
return paths
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function sources(urls, plain, marker, shelf) {
|
|
52
|
+
var paths = filePaths(urls)
|
|
53
|
+
if (!usePlain(marker, shelf)) return paths
|
|
54
|
+
var extra = plainPaths(plain)
|
|
55
|
+
for (var i = 0; i < extra.length; i++) {
|
|
56
|
+
if (paths.indexOf(extra[i]) < 0) paths.push(extra[i])
|
|
57
|
+
}
|
|
58
|
+
return paths
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Checked in this order: a folder inside the drag, a file already in the destination, then nothing local.
|
|
62
|
+
function refusal(paths, dest, marker, shelf) {
|
|
63
|
+
var i
|
|
64
|
+
for (i = 0; i < paths.length; i++) {
|
|
65
|
+
if (dest === paths[i] || dest.indexOf(paths[i] + "/") === 0)
|
|
66
|
+
return "That folder is inside the drag."
|
|
67
|
+
}
|
|
68
|
+
for (i = 0; i < paths.length; i++) {
|
|
69
|
+
var slash = paths[i].lastIndexOf("/")
|
|
70
|
+
var parent = slash <= 0 ? "/" : paths[i].substring(0, slash)
|
|
71
|
+
if (parent === dest) return "Already in this folder."
|
|
72
|
+
}
|
|
73
|
+
if (paths.length === 0 && usePlain(marker, shelf)) return "That drag has no local files."
|
|
74
|
+
return ""
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function askAllowed(pathsPending, clipPending) {
|
|
78
|
+
return !pathsPending && clipPending === null
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Floor refuses while a listing is out; a hovered tab keeps its stored folder, an unlanded one refuses with the floor.
|
|
82
|
+
function refuseLoading(listInFlight, hoverTab, currentTab) {
|
|
83
|
+
if (listInFlight !== true) return false
|
|
84
|
+
if (hoverTab !== true) return true
|
|
85
|
+
return currentTab === true
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function searchTabEnabled(searchMode, current) {
|
|
89
|
+
return !(searchMode && current)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// The top (-1) or bottom (1) band of a listing, which scrolls it with the hover-open setting on or off; 0 elsewhere.
|
|
93
|
+
var BAND_PX = 37
|
|
94
|
+
function band(y, height) {
|
|
95
|
+
if (height < BAND_PX * 2)
|
|
96
|
+
return 0
|
|
97
|
+
if (y < BAND_PX)
|
|
98
|
+
return -1
|
|
99
|
+
if (y > height - BAND_PX)
|
|
100
|
+
return 1
|
|
101
|
+
return 0
|
|
102
|
+
}
|
|
103
|
+
// Resting on a folder this long opens it when the setting is on; a move restarts the rest.
|
|
104
|
+
var OPEN_MS = 700
|
|
105
|
+
function shouldOpen(hoverMs, settingOn, moved) {
|
|
106
|
+
return settingOn && !moved && hoverMs >= OPEN_MS
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// #259: the drag's modifier transitions, kept here so a launch builds no store; each key is 1 held, 0 released, -1 unseen.
|
|
110
|
+
var keys = {
|
|
111
|
+
liftMime: "application/x-flea-lift",
|
|
112
|
+
lifts: 0,
|
|
113
|
+
marker: "",
|
|
114
|
+
lift: "",
|
|
115
|
+
ctrl: -1,
|
|
116
|
+
shift: -1,
|
|
117
|
+
leaving: false,
|
|
118
|
+
|
|
119
|
+
// Every drag this window starts carries its own lift number, so two drags of the same rows are never one drag here.
|
|
120
|
+
stamped: function (mime) {
|
|
121
|
+
var out = {}
|
|
122
|
+
for (var key in mime) out[key] = mime[key]
|
|
123
|
+
keys.lifts += 1
|
|
124
|
+
out[keys.liftMime] = String(keys.lifts)
|
|
125
|
+
return out
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
// Another drag resets the pair; the same drag keeps what was seen, and an own lift keeps it across gaps between targets.
|
|
129
|
+
enter: function (seen, lifted) {
|
|
130
|
+
var number = lifted || ""
|
|
131
|
+
keys.leaving = false
|
|
132
|
+
if (keys.marker !== seen || keys.lift !== number) {
|
|
133
|
+
keys.marker = seen
|
|
134
|
+
keys.lift = number
|
|
135
|
+
keys.ctrl = -1
|
|
136
|
+
keys.shift = -1
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
// A drag with no lift, another app's or an older Flea's, ends at a leave that no enter follows in the same turn.
|
|
141
|
+
leave: function () {
|
|
142
|
+
if (keys.lift !== "") return
|
|
143
|
+
keys.leaving = true
|
|
144
|
+
Qt.callLater(keys.settle)
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
settle: function () {
|
|
148
|
+
if (keys.leaving) keys.clear()
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
// A drop consumes the drag; taps before any drag never arm tracking because it gates on a marker.
|
|
152
|
+
clear: function () {
|
|
153
|
+
keys.leaving = false
|
|
154
|
+
keys.marker = ""
|
|
155
|
+
keys.lift = ""
|
|
156
|
+
keys.ctrl = -1
|
|
157
|
+
keys.shift = -1
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
// The pane funnels its press and release here; the lift bits stay the baseline, so a key held since the lift still counts.
|
|
161
|
+
track: function (event, pressed) {
|
|
162
|
+
if (keys.marker === "") return
|
|
163
|
+
if (event.key === Qt.Key_Control) keys.ctrl = pressed ? 1 : 0
|
|
164
|
+
else if (event.key === Qt.Key_Shift) keys.shift = pressed ? 1 : 0
|
|
165
|
+
}
|
|
166
|
+
}
|
package/ui/js/DropDev.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
.import "Mounts.js" as Mounts
|
|
4
|
+
|
|
5
|
+
// A drop target's device is the backend's stat of it, symlinks followed; this keeps the answers and runs no stat.
|
|
6
|
+
|
|
7
|
+
// Sample input: normalize("/run/media/gm/USB/") is "/run/media/gm/USB".
|
|
8
|
+
function normalize(path) {
|
|
9
|
+
var p = String(path || "").replace(/\/+$/, "")
|
|
10
|
+
return p.length > 0 ? p : (String(path || "").charAt(0) === "/" ? "/" : "")
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Sample input: askPaths("/home/u/docs") is ["/", "/home", "/home/u"]; a listing under a gvfs mount asks nothing, so its crumbs copy.
|
|
14
|
+
function askPaths(listing) {
|
|
15
|
+
var p = normalize(listing)
|
|
16
|
+
if (p.charAt(0) !== "/" || p === "/" || Mounts.underGvfs(p)) return []
|
|
17
|
+
var out = ["/"]
|
|
18
|
+
for (var at = p.indexOf("/", 1); at > 0; at = p.indexOf("/", at + 1)) out.push(p.substring(0, at))
|
|
19
|
+
return out
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Sample input: merged({"/": 5}, {"/home": 6}) is {"/": 5, "/home": 6}; past 256 paths the older answers go whole.
|
|
23
|
+
function merged(known, answered) {
|
|
24
|
+
var out = {}
|
|
25
|
+
var old = known || {}
|
|
26
|
+
if (Object.keys(old).length <= 256) for (var path in old) out[path] = old[path]
|
|
27
|
+
for (var key in (answered || {})) out[key] = answered[key]
|
|
28
|
+
return out
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Sample input: without({"/": 5, "/home": 6}, ["/home"]) is {"/": 5}; an asked path reads unknown, and so copies, until its new answer lands.
|
|
32
|
+
function without(known, paths) {
|
|
33
|
+
var out = {}
|
|
34
|
+
var old = known || {}
|
|
35
|
+
for (var path in old) out[path] = old[path]
|
|
36
|
+
for (var i = 0; i < (paths || []).length; i++) delete out[normalize(paths[i])]
|
|
37
|
+
return out
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Sample input: devFor({"/home": 66306}, "/home/") is 66306, and 0 for a path nobody answered, which makes the plain drop copy.
|
|
41
|
+
function devFor(known, path) {
|
|
42
|
+
var dev = known ? Number(known[normalize(path)]) : 0
|
|
43
|
+
return dev > 0 ? dev : 0
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Sample input: folderAsks([{n: "deep", d: true}, {n: "a.txt", d: false}, {n: "big", d: true, v: 5}], "/home/u", 0, 2, pane) is ["/home/u/deep"]; a file, a row with its own device and a row out of view ask nothing.
|
|
47
|
+
function folderAsks(rows, dir, first, last, pane) {
|
|
48
|
+
var out = []
|
|
49
|
+
for (var i = Math.max(0, first); i <= last && i < (rows || []).length; i++)
|
|
50
|
+
if (rows[i].d === true && !rows[i].v) out.push(pane.join(dir, rows[i].n))
|
|
51
|
+
return out
|
|
52
|
+
}
|
package/ui/js/Dropbox.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
.pragma library
|
|
2
|
+
|
|
3
|
+
// The code names the state for logic (readFailed, signedOut, invalid, or "" when ready); the reason is for people.
|
|
4
|
+
// Sample input: {"personal":{"path":"/home/gm/Dropbox"}}; personal precedes business in the OEM helper.
|
|
5
|
+
function account(raw, error) {
|
|
6
|
+
if (error) return { path: "", reason: error, code: "readFailed" }
|
|
7
|
+
if (!raw) return { path: "", reason: "Dropbox is signed out", code: "signedOut" }
|
|
8
|
+
var data
|
|
9
|
+
try { data = JSON.parse(raw) } catch (e) { return { path: "", reason: "Dropbox account details could not be read", code: "invalid" } }
|
|
10
|
+
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
11
|
+
return { path: "", reason: "Dropbox account details could not be read", code: "invalid" }
|
|
12
|
+
for (var i = 0, keys = ["personal", "business"]; i < keys.length; i++) {
|
|
13
|
+
var value = data[keys[i]]
|
|
14
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) continue
|
|
15
|
+
var path = value.path
|
|
16
|
+
if (typeof path !== "string" || path.charAt(0) !== "/" || path === "/" || path.indexOf("\u0000") >= 0)
|
|
17
|
+
return { path: "", reason: "The Dropbox folder could not be found", code: "invalid" }
|
|
18
|
+
return { path: path.replace(/\/+$/, ""), reason: "", code: "" }
|
|
19
|
+
}
|
|
20
|
+
return { path: "", reason: "Dropbox is signed out", code: "signedOut" }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function contains(root, path) {
|
|
24
|
+
return typeof root === "string" && root.length > 1 && root.charAt(0) === "/"
|
|
25
|
+
&& typeof path === "string" && (path === root || path.indexOf(root + "/") === 0)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// The code names the state for logic (statusFailed, notRunning, or "" when ready); the reason is for people.
|
|
29
|
+
// Sample output: dropbox-cli status prints "Up to date" or "Dropbox isn't running!" even with exit status zero.
|
|
30
|
+
function status(output, exitCode, error) {
|
|
31
|
+
var text = String(output || "").trim(), detail = String(error || "").trim()
|
|
32
|
+
if (exitCode !== 0) return { reason: detail || text || "Dropbox could not be checked", code: "statusFailed" }
|
|
33
|
+
if (!text) return { reason: detail || "Dropbox did not report its status", code: "statusFailed" }
|
|
34
|
+
if (detail) return { reason: detail, code: "statusFailed" }
|
|
35
|
+
var lower = text.toLowerCase()
|
|
36
|
+
if (lower.indexOf("not running") >= 0 || lower.indexOf("isn't running") >= 0 || lower === "stopped"
|
|
37
|
+
|| text.indexOf("Couldn't get status:") === 0 || text === "Dropbox isn't responding!"
|
|
38
|
+
|| text === "Dropbox daemon stopped.")
|
|
39
|
+
return { reason: text, code: "notRunning" }
|
|
40
|
+
return { reason: "", code: "" }
|
|
41
|
+
}
|