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.
Files changed (637) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +511 -2
  3. package/THIRD-PARTY-NOTICES.md +29 -0
  4. package/demos/App.java +5 -0
  5. package/demos/Dockerfile +4 -0
  6. package/demos/Main.kt +3 -0
  7. package/demos/Program.cs +1 -0
  8. package/demos/README.md +12 -0
  9. package/demos/app.dart +3 -0
  10. package/demos/app.deb +0 -0
  11. package/demos/app.js +1 -0
  12. package/demos/backup.tar +0 -0
  13. package/demos/budget.xlsx +0 -0
  14. package/demos/build.sh +2 -0
  15. package/demos/bundle.zip +0 -0
  16. package/demos/clip.mp4 +0 -0
  17. package/demos/data.sqlite +0 -0
  18. package/demos/disk.iso +0 -0
  19. package/demos/engine.cpp +5 -0
  20. package/demos/firmware.bin +0 -0
  21. package/demos/flake.nix +4 -0
  22. package/demos/folder/inside.txt +1 -0
  23. package/demos/font.ttf +0 -0
  24. package/demos/index.html +5 -0
  25. package/demos/index.php +2 -0
  26. package/demos/init.lua +1 -0
  27. package/demos/letter.docx +0 -0
  28. package/demos/lib.rs +3 -0
  29. package/demos/main.c +6 -0
  30. package/demos/main.h +3 -0
  31. package/demos/math-and-diagrams.md +200 -0
  32. package/demos/notes.tar.gz +0 -0
  33. package/demos/notes.txt +3 -0
  34. package/demos/photo.png +0 -0
  35. package/demos/program +2 -0
  36. package/demos/report.pdf +32 -0
  37. package/demos/script.py +1 -0
  38. package/demos/server.go +7 -0
  39. package/demos/settings.json +4 -0
  40. package/demos/slides.pptx +0 -0
  41. package/demos/song.mp3 +0 -0
  42. package/demos/style.css +4 -0
  43. package/demos/tool.rb +1 -0
  44. package/demos/types.ts +2 -0
  45. package/docs/pele.md +23 -0
  46. package/docs/protocol.md +3420 -0
  47. package/docs/temml.md +63 -0
  48. package/index.js +107 -0
  49. package/package.json +34 -4
  50. package/src/archive.js +407 -0
  51. package/src/archiveops.js +728 -0
  52. package/src/backend.js +369 -0
  53. package/src/bulkrename.js +95 -0
  54. package/src/clip-host.js +76 -0
  55. package/src/clip.js +462 -0
  56. package/src/code.js +168 -0
  57. package/src/compare.js +74 -0
  58. package/src/create.js +128 -0
  59. package/src/dirsize.js +147 -0
  60. package/src/figure-svg.js +530 -0
  61. package/src/figure-thread.js +23 -0
  62. package/src/figure.js +132 -0
  63. package/src/find.js +55 -0
  64. package/src/flea.js +39 -0
  65. package/src/fsinfo.js +39 -0
  66. package/src/highlight.js +141 -0
  67. package/src/html.js +52 -0
  68. package/src/kinds.js +89 -0
  69. package/src/listing.js +130 -0
  70. package/src/markdown-html.js +317 -0
  71. package/src/mathml.js +186 -0
  72. package/src/menu.js +180 -0
  73. package/src/meta.js +135 -0
  74. package/src/office.js +810 -0
  75. package/src/order.js +100 -0
  76. package/src/peek.js +49 -0
  77. package/src/pele-wrapper.js +695 -0
  78. package/src/permissions.js +180 -0
  79. package/src/places.js +313 -0
  80. package/src/preview-language.js +10 -0
  81. package/src/terminal-server.js +95 -0
  82. package/src/terminal-shell.js +26 -0
  83. package/src/transfer.js +669 -0
  84. package/src/trash-record.js +41 -0
  85. package/src/trash.js +210 -0
  86. package/src/trashbrowse.js +327 -0
  87. package/src/uistate.js +393 -0
  88. package/src/uistore.js +168 -0
  89. package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
  90. package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
  91. package/src/vendor/LICENSES/MIT-katex.txt +21 -0
  92. package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
  93. package/src/vendor/LICENSES/MIT-pele.txt +40 -0
  94. package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
  95. package/src/vendor/LICENSES/MIT-temml.txt +21 -0
  96. package/src/vendor/pele.js +145 -0
  97. package/src/vendor/temml.mjs +14708 -0
  98. package/src/watch.js +98 -0
  99. package/src/wayland/client.js +109 -0
  100. package/src/wayland/protocol.js +55 -0
  101. package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
  102. package/src/wayland/protocols/wayland.xml +3248 -0
  103. package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
  104. package/src/wayland/resource-io.js +6 -0
  105. package/src/wayland/socket-discovery.js +26 -0
  106. package/src/wayland/transport-posix.js +120 -0
  107. package/src/wayland/transport-win32.js +11 -0
  108. package/src/wayland/transport.js +3 -0
  109. package/src/wayland/win32-resources.js +80 -0
  110. package/src/wayland/win32-wire.js +62 -0
  111. package/test/archive.test.js +80 -0
  112. package/test/bench-markdown-scroll.mjs +190 -0
  113. package/test/clip-host.test.js +113 -0
  114. package/test/code-preview.test.js +35 -0
  115. package/test/compare-ui-paths.test.js +24 -0
  116. package/test/compare.test.js +54 -0
  117. package/test/delete-trash.test.js +67 -0
  118. package/test/dirsize.test.js +138 -0
  119. package/test/file-ops.test.js +307 -0
  120. package/test/file-url.test.js +24 -0
  121. package/test/find-contents.test.js +161 -0
  122. package/test/find-input.test.js +66 -0
  123. package/test/fixtures/pele-parity.json +1006 -0
  124. package/test/highlight-launcher.test.js +35 -0
  125. package/test/html-preview.test.js +22 -0
  126. package/test/input.test.js +15 -0
  127. package/test/keymap.test.js +26 -0
  128. package/test/language-icons.test.js +36 -0
  129. package/test/launcher.test.js +51 -0
  130. package/test/manual-archive-here-ui.mjs +47 -0
  131. package/test/manual-code-scroll.mjs +28 -0
  132. package/test/manual-column-scroll.mjs +24 -0
  133. package/test/manual-compare-ui.mjs +20 -0
  134. package/test/manual-find-status.mjs +37 -0
  135. package/test/manual-folder-focus.mjs +63 -0
  136. package/test/manual-html-security.mjs +23 -0
  137. package/test/manual-html-ui.mjs +30 -0
  138. package/test/manual-syntax-preview.mjs +26 -0
  139. package/test/manual-terminal-lifecycle.mjs +42 -0
  140. package/test/manual-terminal-navigation.mjs +48 -0
  141. package/test/manual-terminal-ui.mjs +47 -0
  142. package/test/manual-trash-ui.mjs +86 -0
  143. package/test/markdown-diagrams.test.js +93 -0
  144. package/test/markdown-html.test.js +105 -0
  145. package/test/mathml.test.js +92 -0
  146. package/test/menu-transfer.test.js +57 -0
  147. package/test/office-preview.test.js +154 -0
  148. package/test/pele-parity.test.js +28 -0
  149. package/test/places.test.js +134 -0
  150. package/test/preview-keys.test.js +60 -0
  151. package/test/preview-language.test.js +22 -0
  152. package/test/status-filename.test.js +20 -0
  153. package/test/transfer-replace-merge.test.js +187 -0
  154. package/test/trash-address.test.js +23 -0
  155. package/test/trash-view.test.js +37 -0
  156. package/test/trashbrowse.test.js +135 -0
  157. package/ui/AboutFacts.qml +78 -0
  158. package/ui/ArchiveCards.qml +95 -0
  159. package/ui/ArchiveCompressDialog.qml +378 -0
  160. package/ui/ArchiveHereConfirm.qml +127 -0
  161. package/ui/ArchivePasswordDialog.qml +257 -0
  162. package/ui/Backend.qml +775 -0
  163. package/ui/BulkOldNames.qml +47 -0
  164. package/ui/BulkRenameDialog.qml +380 -0
  165. package/ui/CardFrame.qml +67 -0
  166. package/ui/CardScroll.qml +79 -0
  167. package/ui/CheckBox.qml +73 -0
  168. package/ui/ChromeBar.qml +360 -0
  169. package/ui/ChromeButton.qml +131 -0
  170. package/ui/ChromeModes.qml +43 -0
  171. package/ui/CodeLines.qml +256 -0
  172. package/ui/CodeRefusal.qml +52 -0
  173. package/ui/CollideConfirm.qml +147 -0
  174. package/ui/CollideHost.qml +167 -0
  175. package/ui/ColumnPane.qml +525 -0
  176. package/ui/ColumnRow.qml +380 -0
  177. package/ui/ColumnsArea.qml +594 -0
  178. package/ui/ColumnsLanding.qml +147 -0
  179. package/ui/CompareView.qml +321 -0
  180. package/ui/ContextMenu.qml +743 -0
  181. package/ui/ConvertDialog.qml +456 -0
  182. package/ui/CountedWorker.qml +7 -0
  183. package/ui/Crumb.qml +64 -0
  184. package/ui/CrumbDrop.qml +25 -0
  185. package/ui/CsvTable.qml +394 -0
  186. package/ui/CursorMark.qml +41 -0
  187. package/ui/DefaultClaim.qml +130 -0
  188. package/ui/DeviceLock.qml +47 -0
  189. package/ui/DeviceMounts.qml +540 -0
  190. package/ui/DialogButton.qml +150 -0
  191. package/ui/DialogField.qml +147 -0
  192. package/ui/DialogHeader.qml +31 -0
  193. package/ui/DialogScrim.qml +20 -0
  194. package/ui/DialogTitle.qml +37 -0
  195. package/ui/Divider.qml +9 -0
  196. package/ui/DropInto.qml +126 -0
  197. package/ui/DropTarget.qml +35 -0
  198. package/ui/DropboxMark.qml +60 -0
  199. package/ui/EmptyState.qml +150 -0
  200. package/ui/EscapeHint.qml +11 -0
  201. package/ui/FactsTable.qml +54 -0
  202. package/ui/FastScrollHandler.qml +476 -0
  203. package/ui/FatNamesConfirm.qml +157 -0
  204. package/ui/Favourites.qml +143 -0
  205. package/ui/FigureService.qml +120 -0
  206. package/ui/FileDrag.qml +267 -0
  207. package/ui/FilterStrip.qml +133 -0
  208. package/ui/FitMetrics.qml +22 -0
  209. package/ui/FlashDriveRows.qml +137 -0
  210. package/ui/FlashHost.qml +72 -0
  211. package/ui/FlashImageRow.qml +104 -0
  212. package/ui/FlashRunner.qml +119 -0
  213. package/ui/FlashStepRow.qml +172 -0
  214. package/ui/FlashStrip.qml +38 -0
  215. package/ui/FlashView.qml +397 -0
  216. package/ui/FleaMark.qml +88 -0
  217. package/ui/FlyoutFade.qml +23 -0
  218. package/ui/FontPane.qml +170 -0
  219. package/ui/Glass.qml +114 -0
  220. package/ui/GlassTagger.qml +59 -0
  221. package/ui/Glyph.qml +64 -0
  222. package/ui/GlyphSolid.qml +22 -0
  223. package/ui/GridArea.qml +664 -0
  224. package/ui/GridTile.qml +325 -0
  225. package/ui/GvfsBridge.qml +164 -0
  226. package/ui/Header.qml +433 -0
  227. package/ui/HoverTimers.qml +39 -0
  228. package/ui/HtmlClip.qml +30 -0
  229. package/ui/HtmlPane.qml +63 -0
  230. package/ui/HyprlandMark.qml +45 -0
  231. package/ui/Ipc.qml +1005 -0
  232. package/ui/IpcControls.qml +7 -0
  233. package/ui/IpcMenuState.qml +48 -0
  234. package/ui/IpcPreviewState.qml +185 -0
  235. package/ui/JumpPath.qml +51 -0
  236. package/ui/KeymapSheet.qml +561 -0
  237. package/ui/KeymapSheetResult.qml +89 -0
  238. package/ui/KindStack.qml +40 -0
  239. package/ui/LangMark.qml +51 -0
  240. package/ui/LangMarkLoader.qml +26 -0
  241. package/ui/List.qml +480 -0
  242. package/ui/LoadingState.qml +54 -0
  243. package/ui/LocalSend.qml +56 -0
  244. package/ui/LocalSendMark.qml +73 -0
  245. package/ui/MarkdownBlockView.qml +311 -0
  246. package/ui/MarkdownBlocks.qml +35 -0
  247. package/ui/MarkdownFigure.qml +254 -0
  248. package/ui/MarkdownImages.qml +72 -0
  249. package/ui/MarkdownList.qml +81 -0
  250. package/ui/MarkdownMathsText.qml +97 -0
  251. package/ui/MarkdownPane.qml +83 -0
  252. package/ui/MarkdownPictures.qml +41 -0
  253. package/ui/MarkdownQuote.qml +52 -0
  254. package/ui/MarkdownRemote.qml +82 -0
  255. package/ui/MarkdownSource.qml +155 -0
  256. package/ui/MarkdownTable.qml +222 -0
  257. package/ui/MarkdownTableScroll.qml +64 -0
  258. package/ui/MarkdownTableWheel.qml +126 -0
  259. package/ui/MarkdownText.qml +87 -0
  260. package/ui/MarkdownWorker.js +132 -0
  261. package/ui/MatchText.qml +99 -0
  262. package/ui/MediaSession.qml +38 -0
  263. package/ui/MediaSound.qml +26 -0
  264. package/ui/MediaStrip.qml +191 -0
  265. package/ui/MediaTrack.qml +36 -0
  266. package/ui/MediaVolume.qml +54 -0
  267. package/ui/MenuActionDialog.qml +396 -0
  268. package/ui/MenuEdgeFade.qml +24 -0
  269. package/ui/MenuHost.qml +227 -0
  270. package/ui/MenuRow.qml +351 -0
  271. package/ui/MountListing.qml +100 -0
  272. package/ui/NetworkDialog.qml +435 -0
  273. package/ui/NetworkForm.qml +426 -0
  274. package/ui/NetworkMounts.qml +913 -0
  275. package/ui/NetworkPlaces.qml +127 -0
  276. package/ui/OpenWithDialog.qml +613 -0
  277. package/ui/Opener.qml +95 -0
  278. package/ui/Pane.qml +1320 -0
  279. package/ui/PaneMenuActions.qml +527 -0
  280. package/ui/PanePath.qml +90 -0
  281. package/ui/PaneRail.qml +268 -0
  282. package/ui/PaneStates.qml +88 -0
  283. package/ui/PaneSwap.qml +339 -0
  284. package/ui/PaneWire.qml +601 -0
  285. package/ui/ParkedWait.qml +9 -0
  286. package/ui/PathEntry.qml +186 -0
  287. package/ui/PathJump.qml +400 -0
  288. package/ui/PdfViewer.qml +297 -0
  289. package/ui/PermissionsDialog.qml +658 -0
  290. package/ui/PermissionsHeadings.qml +31 -0
  291. package/ui/PhoneMounts.qml +67 -0
  292. package/ui/PickerAnswers.qml +75 -0
  293. package/ui/PickerBox.qml +26 -0
  294. package/ui/PickerChrome.qml +295 -0
  295. package/ui/PickerFilter.qml +97 -0
  296. package/ui/PickerGrid.qml +308 -0
  297. package/ui/PickerHeader.qml +28 -0
  298. package/ui/PickerLifecycle.qml +27 -0
  299. package/ui/PickerList.qml +218 -0
  300. package/ui/PickerListing.qml +149 -0
  301. package/ui/PickerPathBar.qml +127 -0
  302. package/ui/PickerPlaces.qml +189 -0
  303. package/ui/PickerRecent.qml +92 -0
  304. package/ui/PickerSave.qml +101 -0
  305. package/ui/PickerSelection.qml +155 -0
  306. package/ui/PickerWindow.qml +846 -0
  307. package/ui/PowerSectorsReader.qml +10 -0
  308. package/ui/PrebuildDriver.qml +146 -0
  309. package/ui/Preview.qml +1005 -0
  310. package/ui/PreviewAnimation.qml +24 -0
  311. package/ui/PreviewArchive.qml +91 -0
  312. package/ui/PreviewColumn.qml +553 -0
  313. package/ui/PreviewEdge.qml +63 -0
  314. package/ui/PreviewFacts.qml +30 -0
  315. package/ui/PreviewFactsLine.qml +34 -0
  316. package/ui/PreviewHtml.qml +233 -0
  317. package/ui/PreviewImage.qml +253 -0
  318. package/ui/PreviewImagePan.qml +13 -0
  319. package/ui/PreviewImageSharp.qml +32 -0
  320. package/ui/PreviewLines.qml +106 -0
  321. package/ui/PreviewMarkdown.qml +706 -0
  322. package/ui/PreviewMedia.qml +250 -0
  323. package/ui/PreviewPdf.qml +482 -0
  324. package/ui/PreviewScroll.qml +201 -0
  325. package/ui/PreviewSwap.qml +335 -0
  326. package/ui/PreviewText.qml +149 -0
  327. package/ui/ProtocolChip.qml +18 -0
  328. package/ui/QuickLookArchive.qml +41 -0
  329. package/ui/QuickLookBar.qml +103 -0
  330. package/ui/QuickLookPrepare.qml +355 -0
  331. package/ui/QuickLookSwap.qml +10 -0
  332. package/ui/QuickLookWarm.qml +65 -0
  333. package/ui/RailDrop.qml +155 -0
  334. package/ui/RailHeading.qml +19 -0
  335. package/ui/RailPlaces.qml +38 -0
  336. package/ui/RailTrashRow.qml +67 -0
  337. package/ui/RenameField.qml +353 -0
  338. package/ui/RendererRetry.qml +11 -0
  339. package/ui/ResizeHandle.qml +52 -0
  340. package/ui/Reveal.qml +54 -0
  341. package/ui/Row.qml +476 -0
  342. package/ui/RowDrag.qml +213 -0
  343. package/ui/RowDropTarget.qml +27 -0
  344. package/ui/RunCard.qml +286 -0
  345. package/ui/Scripts.qml +65 -0
  346. package/ui/SearchStrip.qml +232 -0
  347. package/ui/SelectionBand.qml +140 -0
  348. package/ui/SelectionPreview.qml +370 -0
  349. package/ui/SettingsFavourite.qml +122 -0
  350. package/ui/SettingsGroup.qml +96 -0
  351. package/ui/SettingsHint.qml +12 -0
  352. package/ui/SettingsMetrics.qml +29 -0
  353. package/ui/SettingsPane.qml +178 -0
  354. package/ui/SettingsPanel.qml +547 -0
  355. package/ui/SettingsRail.qml +128 -0
  356. package/ui/SettingsRow.qml +409 -0
  357. package/ui/SettingsRuler.qml +85 -0
  358. package/ui/SettingsSegment.qml +85 -0
  359. package/ui/ShareBrowser.qml +113 -0
  360. package/ui/ShareLink.qml +67 -0
  361. package/ui/ShelfPins.qml +101 -0
  362. package/ui/Sidebar.qml +728 -0
  363. package/ui/SidebarRow.qml +358 -0
  364. package/ui/Spinner.qml +60 -0
  365. package/ui/StableModel.qml +89 -0
  366. package/ui/StateMessage.qml +84 -0
  367. package/ui/StatusBar.qml +512 -0
  368. package/ui/StatusFileName.qml +27 -0
  369. package/ui/TabBar.qml +673 -0
  370. package/ui/TabDragGeometry.qml +60 -0
  371. package/ui/TagMenuMark.qml +52 -0
  372. package/ui/TagRailSection.qml +53 -0
  373. package/ui/TagSlot.qml +40 -0
  374. package/ui/TagState.qml +150 -0
  375. package/ui/TagSwatch.qml +28 -0
  376. package/ui/Taildrop.qml +86 -0
  377. package/ui/TailscaleMark.qml +50 -0
  378. package/ui/TerminalService.qml +69 -0
  379. package/ui/TerminalTab.qml +48 -0
  380. package/ui/TerminalTabs.qml +27 -0
  381. package/ui/Theme.qml +460 -0
  382. package/ui/ThemeColors.qml +43 -0
  383. package/ui/TransferCard.qml +239 -0
  384. package/ui/TrashConfirm.qml +129 -0
  385. package/ui/TrashDropHandler.qml +11 -0
  386. package/ui/TrashHost.qml +202 -0
  387. package/ui/TrashMonitor.qml +30 -0
  388. package/ui/TrashToolbar.qml +19 -0
  389. package/ui/TrashView.qml +492 -0
  390. package/ui/UnlockDialog.qml +450 -0
  391. package/ui/UnlockHost.qml +206 -0
  392. package/ui/UpdateCheck.qml +97 -0
  393. package/ui/UserDirs.qml +25 -0
  394. package/ui/ViewState.qml +565 -0
  395. package/ui/ViewportScrollBar.qml +195 -0
  396. package/ui/ViewportScrollBars.qml +25 -0
  397. package/ui/WebPreview.qml +33 -0
  398. package/ui/WebPreviewView.qml +26 -0
  399. package/ui/WindowBody.qml +829 -0
  400. package/ui/WindowDrag.qml +35 -0
  401. package/ui/boot/Commons/AudioNodes.qml +50 -0
  402. package/ui/boot/Commons/AudioNodesModel.js +96 -0
  403. package/ui/boot/Commons/Border.qml +243 -0
  404. package/ui/boot/Commons/BorderGeometry.js +373 -0
  405. package/ui/boot/Commons/Color.qml +258 -0
  406. package/ui/boot/Commons/I18n.qml +118 -0
  407. package/ui/boot/Commons/InputDevices.qml +112 -0
  408. package/ui/boot/Commons/InputMethodState.qml +38 -0
  409. package/ui/boot/Commons/IpcRegistry.qml +77 -0
  410. package/ui/boot/Commons/Numbers.js +19 -0
  411. package/ui/boot/Commons/Plural.js +91 -0
  412. package/ui/boot/Commons/ShellIpc.qml +12 -0
  413. package/ui/boot/Commons/Style.qml +561 -0
  414. package/ui/boot/Commons/Translations.qml +100 -0
  415. package/ui/boot/Commons/UntypedInput.qml +152 -0
  416. package/ui/boot/Commons/Util.qml +188 -0
  417. package/ui/boot/Commons/qmldir +13 -0
  418. package/ui/boot/LICENSE-omarchy +20 -0
  419. package/ui/boot/Ui/BackgroundMedia.qml +49 -0
  420. package/ui/boot/Ui/BarIconButton.qml +106 -0
  421. package/ui/boot/Ui/BarIconContent.qml +38 -0
  422. package/ui/boot/Ui/BarIndicator.qml +53 -0
  423. package/ui/boot/Ui/BarWidget.qml +50 -0
  424. package/ui/boot/Ui/BorderOverlay.qml +54 -0
  425. package/ui/boot/Ui/BorderSurface.qml +40 -0
  426. package/ui/boot/Ui/Button.qml +224 -0
  427. package/ui/boot/Ui/ButtonGroup.qml +131 -0
  428. package/ui/boot/Ui/ConfirmDialog.qml +134 -0
  429. package/ui/boot/Ui/CursorSurface.qml +42 -0
  430. package/ui/boot/Ui/Dropdown.qml +245 -0
  431. package/ui/boot/Ui/FilterInput.qml +26 -0
  432. package/ui/boot/Ui/IconContentBounds.qml +141 -0
  433. package/ui/boot/Ui/KeyboardPanel.qml +453 -0
  434. package/ui/boot/Ui/MultiSelect.qml +624 -0
  435. package/ui/boot/Ui/NumberField.qml +86 -0
  436. package/ui/boot/Ui/OpticalGlyph.qml +68 -0
  437. package/ui/boot/Ui/OverlayWindow.qml +102 -0
  438. package/ui/boot/Ui/Panel.qml +60 -0
  439. package/ui/boot/Ui/PanelActionButton.qml +105 -0
  440. package/ui/boot/Ui/PanelController.qml +16 -0
  441. package/ui/boot/Ui/PanelHero.qml +112 -0
  442. package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
  443. package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
  444. package/ui/boot/Ui/PanelSeparator.qml +19 -0
  445. package/ui/boot/Ui/PanelSlider.qml +156 -0
  446. package/ui/boot/Ui/PanelToolTip.qml +50 -0
  447. package/ui/boot/Ui/PluginBarApi.qml +89 -0
  448. package/ui/boot/Ui/PointerMoveGate.qml +54 -0
  449. package/ui/boot/Ui/PopupCard.qml +181 -0
  450. package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
  451. package/ui/boot/Ui/SearchableDropdown.qml +354 -0
  452. package/ui/boot/Ui/SizedImage.qml +125 -0
  453. package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
  454. package/ui/boot/Ui/TextField.qml +58 -0
  455. package/ui/boot/Ui/Toggle.qml +118 -0
  456. package/ui/boot/Ui/ToggleSwitch.qml +115 -0
  457. package/ui/boot/Ui/WidgetButton.qml +172 -0
  458. package/ui/boot/Ui/qmldir +41 -0
  459. package/ui/boot/fleatab.qml +50 -0
  460. package/ui/boot/picker.qml +39 -0
  461. package/ui/boot/shell.qml +131 -0
  462. package/ui/boot/tabtearoff.qml +51 -0
  463. package/ui/js/Anchor.js +379 -0
  464. package/ui/js/AnchorHold.js +162 -0
  465. package/ui/js/Archive.js +157 -0
  466. package/ui/js/ArchiveCard.js +44 -0
  467. package/ui/js/ArchiveOps.js +44 -0
  468. package/ui/js/BackReturn.js +118 -0
  469. package/ui/js/BulkRename.js +100 -0
  470. package/ui/js/Buttons.js +54 -0
  471. package/ui/js/ChromeKeys.js +116 -0
  472. package/ui/js/ClipMarks.js +73 -0
  473. package/ui/js/ClipSelection.js +67 -0
  474. package/ui/js/Clipboard.js +179 -0
  475. package/ui/js/Cloud.js +97 -0
  476. package/ui/js/CodeRuns.js +72 -0
  477. package/ui/js/Collide.js +212 -0
  478. package/ui/js/ColumnFit.js +28 -0
  479. package/ui/js/ColumnMenu.js +111 -0
  480. package/ui/js/Columns.js +298 -0
  481. package/ui/js/ColumnsCarry.js +103 -0
  482. package/ui/js/Compare.js +74 -0
  483. package/ui/js/Contrast.js +157 -0
  484. package/ui/js/ControlReader.js +42 -0
  485. package/ui/js/Convert.js +52 -0
  486. package/ui/js/CopyAs.js +52 -0
  487. package/ui/js/Crumbs.js +178 -0
  488. package/ui/js/Csv.js +231 -0
  489. package/ui/js/Density.js +44 -0
  490. package/ui/js/Devices.js +440 -0
  491. package/ui/js/DirSizes.js +180 -0
  492. package/ui/js/Drag.js +360 -0
  493. package/ui/js/DragOut.js +166 -0
  494. package/ui/js/DropDev.js +52 -0
  495. package/ui/js/Dropbox.js +41 -0
  496. package/ui/js/Eject.js +217 -0
  497. package/ui/js/Errors.js +188 -0
  498. package/ui/js/ExtThumbs.js +115 -0
  499. package/ui/js/Facts.js +402 -0
  500. package/ui/js/FigureDate.js +14 -0
  501. package/ui/js/Filter.js +285 -0
  502. package/ui/js/Find.js +46 -0
  503. package/ui/js/Flash.js +184 -0
  504. package/ui/js/FlashCard.js +79 -0
  505. package/ui/js/FlashEndings.js +125 -0
  506. package/ui/js/FlashPane.js +116 -0
  507. package/ui/js/FleaBin.js +12 -0
  508. package/ui/js/Focus.js +504 -0
  509. package/ui/js/FolderSorts.js +108 -0
  510. package/ui/js/FolderViews.js +44 -0
  511. package/ui/js/Format.js +314 -0
  512. package/ui/js/Fuzzy.js +141 -0
  513. package/ui/js/GlassTag.js +72 -0
  514. package/ui/js/Grid.js +33 -0
  515. package/ui/js/GridGeometry.js +90 -0
  516. package/ui/js/GridNames.js +153 -0
  517. package/ui/js/GvfsBridge.js +200 -0
  518. package/ui/js/HostClipboard.js +29 -0
  519. package/ui/js/Icons.js +218 -0
  520. package/ui/js/Input.js +50 -0
  521. package/ui/js/Jump.js +200 -0
  522. package/ui/js/KeyName.js +64 -0
  523. package/ui/js/Keymap.js +401 -0
  524. package/ui/js/Kinds.js +164 -0
  525. package/ui/js/LICENSES/ISC-lucide.txt +43 -0
  526. package/ui/js/LangMarkPaths.js +47 -0
  527. package/ui/js/LangMarks.js +120 -0
  528. package/ui/js/Lists.js +11 -0
  529. package/ui/js/LocalSend.js +39 -0
  530. package/ui/js/LockedMenu.js +63 -0
  531. package/ui/js/MakeDefault.js +186 -0
  532. package/ui/js/MarkBox.js +7 -0
  533. package/ui/js/Markdown.js +119 -0
  534. package/ui/js/MarkdownLists.js +86 -0
  535. package/ui/js/MarkdownMaths.js +58 -0
  536. package/ui/js/MarkdownPictures.js +32 -0
  537. package/ui/js/MarkdownPrepared.js +139 -0
  538. package/ui/js/MarkdownTableFit.js +34 -0
  539. package/ui/js/Marks.js +148 -0
  540. package/ui/js/Marquee.js +96 -0
  541. package/ui/js/Match.js +93 -0
  542. package/ui/js/Material.js +109 -0
  543. package/ui/js/MdBlocks.js +437 -0
  544. package/ui/js/MdBreak.js +71 -0
  545. package/ui/js/MdChunks.js +70 -0
  546. package/ui/js/MdContainer.js +137 -0
  547. package/ui/js/MdDocument.js +337 -0
  548. package/ui/js/MdEmph.js +97 -0
  549. package/ui/js/MdEntity.js +108 -0
  550. package/ui/js/MdEntityTable.js +223 -0
  551. package/ui/js/MdEscape.js +59 -0
  552. package/ui/js/MdFront.js +37 -0
  553. package/ui/js/MdHold.js +32 -0
  554. package/ui/js/MdHtml.js +307 -0
  555. package/ui/js/MdHtmlBlock.js +290 -0
  556. package/ui/js/MdHtmlHeading.js +53 -0
  557. package/ui/js/MdHtmlImage.js +179 -0
  558. package/ui/js/MdInline.js +154 -0
  559. package/ui/js/MdItems.js +212 -0
  560. package/ui/js/MdLeaf.js +309 -0
  561. package/ui/js/MdLink.js +196 -0
  562. package/ui/js/MdMath.js +67 -0
  563. package/ui/js/MdParagraphs.js +138 -0
  564. package/ui/js/MdRefs.js +232 -0
  565. package/ui/js/MdResolve.js +226 -0
  566. package/ui/js/MdRun.js +300 -0
  567. package/ui/js/MdUrl.js +226 -0
  568. package/ui/js/Menu.js +514 -0
  569. package/ui/js/MenuContext.js +85 -0
  570. package/ui/js/MenuFit.js +13 -0
  571. package/ui/js/MenuRefresh.js +74 -0
  572. package/ui/js/MenuWheel.js +35 -0
  573. package/ui/js/Messages.js +186 -0
  574. package/ui/js/Motion.js +16 -0
  575. package/ui/js/Mounts.js +320 -0
  576. package/ui/js/MouseNav.js +13 -0
  577. package/ui/js/Nav.js +329 -0
  578. package/ui/js/NetFs.js +26 -0
  579. package/ui/js/OpenWith.js +83 -0
  580. package/ui/js/Ops.js +585 -0
  581. package/ui/js/Palette.js +33 -0
  582. package/ui/js/PathBar.js +260 -0
  583. package/ui/js/Permissions.js +179 -0
  584. package/ui/js/Phones.js +112 -0
  585. package/ui/js/Picker.js +353 -0
  586. package/ui/js/PlaceMenu.js +96 -0
  587. package/ui/js/Places.js +265 -0
  588. package/ui/js/PreviewAsk.js +21 -0
  589. package/ui/js/PreviewKeys.js +155 -0
  590. package/ui/js/PreviewSettle.js +29 -0
  591. package/ui/js/PreviewSwap.js +101 -0
  592. package/ui/js/PropertyFacts.js +144 -0
  593. package/ui/js/Protocols.js +296 -0
  594. package/ui/js/QuickLookKinds.js +27 -0
  595. package/ui/js/QuickLookRect.js +24 -0
  596. package/ui/js/RailDrop.js +51 -0
  597. package/ui/js/RailKeys.js +87 -0
  598. package/ui/js/RailMenu.js +133 -0
  599. package/ui/js/Recent.js +135 -0
  600. package/ui/js/RecentMode.js +156 -0
  601. package/ui/js/Reload.js +60 -0
  602. package/ui/js/Renderer.js +9 -0
  603. package/ui/js/RunFile.js +143 -0
  604. package/ui/js/Scripts.js +28 -0
  605. package/ui/js/Scroll.js +304 -0
  606. package/ui/js/ScrollOff.js +69 -0
  607. package/ui/js/Search.js +478 -0
  608. package/ui/js/Selection.js +97 -0
  609. package/ui/js/Settings.js +476 -0
  610. package/ui/js/SettingsAbout.js +97 -0
  611. package/ui/js/SettingsShelf.js +52 -0
  612. package/ui/js/SheetKeys.js +42 -0
  613. package/ui/js/SheetQuery.js +281 -0
  614. package/ui/js/ShelfPile.js +27 -0
  615. package/ui/js/SlowClick.js +53 -0
  616. package/ui/js/SlowOp.js +6 -0
  617. package/ui/js/Sort.js +134 -0
  618. package/ui/js/Startup.js +63 -0
  619. package/ui/js/StateWords.js +17 -0
  620. package/ui/js/Status.js +238 -0
  621. package/ui/js/Swap.js +166 -0
  622. package/ui/js/TabMove.js +39 -0
  623. package/ui/js/Tabs.js +751 -0
  624. package/ui/js/Tags.js +134 -0
  625. package/ui/js/Taildrop.js +128 -0
  626. package/ui/js/Tap.js +180 -0
  627. package/ui/js/TextSize.js +107 -0
  628. package/ui/js/Thumbs.js +158 -0
  629. package/ui/js/Transfer.js +172 -0
  630. package/ui/js/Trash.js +84 -0
  631. package/ui/js/TrashDates.js +47 -0
  632. package/ui/js/TrashDrop.js +64 -0
  633. package/ui/js/UiState.js +438 -0
  634. package/ui/js/Unlock.js +152 -0
  635. package/ui/js/Update.js +130 -0
  636. package/ui/js/UserDirs.js +56 -0
  637. 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
+ }
@@ -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
+ }
@@ -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
+ }
@@ -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
+ }