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
@@ -0,0 +1,527 @@
1
+ import QtQuick
2
+ import Quickshell
3
+ import Quickshell.Io
4
+ import "." as Flea
5
+ import "js/LocalSend.js" as LocalSendJs
6
+ import "js/CopyAs.js" as CopyAs
7
+ import "js/Archive.js" as Archive
8
+ import "js/Menu.js" as Menu
9
+ import "js/Format.js" as Format
10
+ import "js/Ops.js" as Ops
11
+ import "js/Search.js" as Search
12
+
13
+ Loader {
14
+ id: root
15
+ required property var pane
16
+
17
+ // Directive 71: the only thing that knows about LocalSend, the way ui/Taildrop.qml is for the
18
+ // other one. The work is the backend's, which drives localsend-cli on a pty of its own.
19
+ readonly property alias localSend: localSend
20
+
21
+ Flea.LocalSend {
22
+ id: localSend
23
+ backend: root.pane.backend
24
+ }
25
+
26
+ Connections {
27
+ target: root.pane.backend
28
+ function onLocalSendPeers(peers, reason) {
29
+ localSend.answered(peers, reason)
30
+ root.pane.contextMenu().refreshProviderRows()
31
+ }
32
+ function onLocalSendSent(ok, reason) { root.pane.message(LocalSendJs.verdict(ok, reason), !ok) }
33
+ }
34
+
35
+ // A menu opened without a selection carries no paths, so a row action means the row under the
36
+ // cursor, joined against the listing's base: on a search the scope or the folder, never the pane's path.
37
+ function targets(paths) {
38
+ if (paths && paths.length) return paths
39
+ return root.pane.cursorRow ? [root.pane.join(Search.baseOf(root.pane), root.pane.cursorRow.n)] : []
40
+ }
41
+
42
+ // Actions rule 1: every shelf action is a `flea shelf` call, so the menu row makes the same one
43
+ // a drop onto the card makes and nothing here knows the pile's shape.
44
+ function shelve(paths) {
45
+ if (paths.length === 0) { root.pane.message("There is nothing to put on the shelf.", true); return }
46
+ if (shelver.running) {
47
+ // A second add while one runs waits its turn, so each exit reports its own count.
48
+ shelver.pendingAdds = shelver.pendingAdds.concat([paths])
49
+ return
50
+ }
51
+ shelver.startAdd(paths)
52
+ }
53
+
54
+ Process {
55
+ id: shelver
56
+ property int count: 0
57
+ property var pendingAdds: []
58
+ stderr: StdioCollector { waitForEnd: true }
59
+ function startAdd(paths) {
60
+ shelver.count = paths.length
61
+ shelver.command = [Quickshell.env("FLEA_BIN") || "flea", "shelf", "add"].concat(paths)
62
+ shelver.running = true
63
+ }
64
+ onExited: function (code, status) {
65
+ if (code === 0) {
66
+ root.pane.message(shelver.count === 1 ? Ops.WORDS.shelfOne
67
+ : Format.fill(Ops.WORDS.shelfMany, shelver.count), false)
68
+ } else {
69
+ var said = shelver.stderr.text.trim().split("\n").pop().replace(/^flea: /, "")
70
+ root.pane.message(said.length > 0 ? said : "The shelf did not take that.", true)
71
+ }
72
+ if (shelver.pendingAdds.length > 0) {
73
+ var next = shelver.pendingAdds[0]
74
+ shelver.pendingAdds = shelver.pendingAdds.slice(1)
75
+ shelver.startAdd(next)
76
+ }
77
+ }
78
+ }
79
+
80
+ // Copy as covers the whole selection, one path per line, as plain text; the leaves read the snapshot, whose paths a window cannot hold.
81
+ property var copyKinds: ({ copyPath: "path", copyName: "name", copyStem: "stem",
82
+ copydirpath: "dirpath", copyUri: "uri", copyQuoted: "quoted" })
83
+ function copyVariant(action, paths) {
84
+ var leaf = action.indexOf("copyAs:") === 0 ? action.substring("copyAs:".length) : action
85
+ var kind = copyKinds[leaf]
86
+ if (kind === undefined) return false
87
+ var taken = root.targets(paths)
88
+ if (taken.length === 0) return true
89
+ root.pane.opener.copyText(CopyAs.lines(taken, kind))
90
+ return true
91
+ }
92
+
93
+ function perform(action, menuId, paths) {
94
+ if (action.indexOf("runScript:") === 0) { Flea.Scripts.run(action.substring("runScript:".length), paths || []); return }
95
+ if (action.indexOf("localsend:") === 0) { LocalSendJs.send(root.pane, localSend, root.pane.backend.providers.localsend, action.substring("localsend:".length), root.targets(paths)); return }
96
+ if (action.indexOf("taildrop:") === 0) { root.pane.sendTaildrop(action.substring("taildrop:".length), root.targets(paths).length === 1 ? root.targets(paths)[0] : ""); return }
97
+ if (action === "addToShelf") { root.shelve(root.targets(paths)); return }
98
+ if (action === "sharelink") { root.pane.copyShareLink(paths && paths.length === 1 ? paths[0] : ""); return }
99
+ // The Places and Locked menus still send the Copy path alias.
100
+ if (action === "copypath") { root.pane.opener.copyText(paths && paths.length ? paths[0] : root.pane.join(Search.baseOf(root.pane), root.pane.cursorRow.n)); return }
101
+ if (copyVariant(action, paths)) return
102
+ // Show original reveals the link target in its own folder.
103
+ if (action === "showOriginal") {
104
+ var taken = root.targets(paths)
105
+ if (taken.length > 0) root.pane.requestLinkTarget(taken[0])
106
+ return
107
+ }
108
+ // Paste as links through the collision card; the source is the file clipboard, never the menu snapshot.
109
+ if (action.indexOf("pasteAs:") === 0) {
110
+ var leaf = action.substring("pasteAs:".length)
111
+ var kind = leaf === "pasteAbsoluteLink" ? "absolute" : leaf === "pasteHardLink" ? "hard" : "relative"
112
+ root.pane.pasteLink(kind, null)
113
+ return
114
+ }
115
+ if (action === "invertSelection") { root.pane.invertSelection(); return }
116
+ if (action.indexOf("col:") === 0) { ViewState.toggleColumn(action.substring("col:".length)); return }
117
+ root.pane.act(action, menuId, paths)
118
+ }
119
+ // A script's own non-zero exit is its last stderr line, said once in the status centre.
120
+ Connections {
121
+ target: Flea.Scripts
122
+ function onSaid(text, isError) { root.pane.message(text, isError) }
123
+ }
124
+ anchors.fill: parent
125
+ z: 2
126
+ active: false
127
+ // OpenWith.html rule 4: Open with owns its own card, so the shared dialog is not asked to be one.
128
+ property string dialogFor: ""
129
+ source: root.dialogFor === "openWith" ? "OpenWithDialog.qml" : "MenuActionDialog.qml"
130
+ readonly property bool opened: item !== null && item.opened
131
+ readonly property bool deleting: item !== null && item.deletionActive
132
+ property int requestId: 0
133
+ property string identity: ""
134
+ property string folder: ""
135
+ property bool ready: false
136
+ property var selectedKinds: []
137
+ property string pendingAction: ""
138
+ property bool pendingActivation: false
139
+ // Tag toggles chosen while the first still awaits its snapshot, kept in press order; any other pending action drops them.
140
+ property var queuedTags: []
141
+ // A tag activate sent and not yet answered; the backend's menu slot holds one job, so the next queued tag waits for this reply.
142
+ property bool tagInFlight: false
143
+ property bool activationUsed: false
144
+ // The request a keymap sheet activation runs under, which lists hidden rows; the next snapshot moves requestId past it.
145
+ property int sheetRequest: 0
146
+ // Which row a keyboard rename was asked for, so its reply cannot open the editor over another.
147
+ property int pendingRenameIndex: -1
148
+ // The pointer rename's own reveal context beside it, so a slow click never scrolls; false keeps the keyboard's.
149
+ property bool pendingRenameStill: false
150
+ property int launchingId: 0
151
+ // OpenWith.html's flyout: the registry for the cursor row, asked for as the menu opens so the
152
+ // submenu is populated by the time the row is reached. The flyout writes nothing; the dialog
153
+ // stays the only place a default is written, which is Douglas de Moura's architecture kept whole.
154
+ property var openWithApps: []
155
+ property bool openWithLoaded: false
156
+ property var survivors: []
157
+ property int survivorId: 0
158
+ property string survivorFolder: ""
159
+ property string survivorListing: ""
160
+ property string backgroundFolder: ""
161
+ property bool providersRefreshing: false
162
+ property int providerFormatsId: 0
163
+ property bool providerQueriesStarted: false
164
+ property bool providerDestinationPending: false
165
+ property bool providerValidated: false
166
+ property var providerFacts: ({})
167
+ property bool taildropRefreshWaiting: false
168
+ property bool dropboxRefreshWaiting: false
169
+ property bool refreshingTaildrop: false
170
+ property bool refreshingDropbox: false
171
+
172
+ function providerAction(action) {
173
+ return action.indexOf("taildrop:") === 0 || action === "dropbox" || action === "sharelink"
174
+ }
175
+ function refreshProviders(action) {
176
+ providersRefreshing = true
177
+ refreshingTaildrop = !action || action.indexOf("taildrop:") === 0
178
+ refreshingDropbox = !action || action === "dropbox" || action === "sharelink"
179
+ providerQueriesStarted = false
180
+ providerDestinationPending = false
181
+ taildropRefreshWaiting = false
182
+ dropboxRefreshWaiting = false
183
+ providerFormatsId = pane.backend.askFormats()
184
+ pane.contextMenu().refreshProviderRows()
185
+ }
186
+ function finishProviders() {
187
+ if (!providersRefreshing || !providerQueriesStarted || providerDestinationPending || !ready
188
+ || taildropRefreshWaiting || dropboxRefreshWaiting
189
+ || (refreshingTaildrop && pane.taildropService.checking)
190
+ || (refreshingDropbox && pane.dropboxService && pane.dropboxService.dropboxChecking)) return
191
+ if (!pendingActivation && pane.dropboxService && pane.dropboxService.dropboxReady) {
192
+ providerDestinationPending = true
193
+ pane.backend.send({c: "menuaction", op: "providerDestination", id: requestId, dest: pane.dropboxService.dropboxPath})
194
+ return
195
+ }
196
+ providersFinished()
197
+ }
198
+ function providersFinished() {
199
+ providersRefreshing = false
200
+ pane.contextMenu().providersSettled()
201
+ if (pendingActivation && providerAction(pendingAction)) {
202
+ providerValidated = true
203
+ validateActivation()
204
+ }
205
+ }
206
+
207
+ // rows, when the caller has one: a keyboard rename acts on the cursor, and Ops.targetIndices
208
+ // answers with the selection whenever there is one, so the snapshot covered rows the rename was
209
+ // never going to touch and the backend refused the cursor's own path as "not in the selection".
210
+ function snapshot(rows) {
211
+ if (deleting || survivorId) return
212
+ requestId++
213
+ ready = false
214
+ selectedKinds = []
215
+ pendingAction = ""
216
+ pendingActivation = false
217
+ queuedTags = []
218
+ tagInFlight = false
219
+ activationUsed = false
220
+ identity = pane.menuSelectionIdentity()
221
+ folder = pane.path
222
+ // The registry belongs to the row that was snapshotted. Carrying the last row's answer over
223
+ // offered one file's applications for another, and kept the self-hide rule from ever firing.
224
+ openWithApps = []
225
+ openWithLoaded = false
226
+ pane.backend.send({c: "menuaction", op: "snapshot", id: requestId,
227
+ rows: rows !== undefined ? rows : Ops.targetIndices(pane), cursor: pane.cursorIndex})
228
+ }
229
+ // A ready snapshot over the same selection opens the editor at once, one still in flight takes the F2 route, and a moved selection refuses as activate does.
230
+ function openRenameFromMenu() {
231
+ if (pane.renamePending) { pane.message("Rename is still finishing.", false); return }
232
+ if (deleting || survivorId) { pane.message("The deletion is still finishing.", false); return }
233
+ var route = Ops.menuRenameRoute(ready, identity, pane.menuSelectionIdentity())
234
+ if (route === "stale") { pane.message("Selected items changed; reopen the menu.", true); return }
235
+ if (route === "now" && pane.contextMenu().validateChoice("rename", "")) {
236
+ show("rename")
237
+ return
238
+ }
239
+ open("rename")
240
+ }
241
+ function open(action, menuId, context) {
242
+ if (opened) return
243
+ if (action === "rename" && pane.renamePending) { pane.message("Rename is still finishing.", false); return }
244
+ if (deleting || survivorId) { pane.message("The deletion is still finishing.", false); return }
245
+ if (action === "newFile") {
246
+ requestId++
247
+ folder = pane.path
248
+ show(action)
249
+ return
250
+ }
251
+ // The row the editor will open over, captured now: the cursor can move between this request
252
+ // and its reply, and the editor used to open over wherever it had got to by then.
253
+ if (action === "rename" && !menuId) {
254
+ pendingRenameIndex = pane.cursorIndex
255
+ pendingRenameStill = context === 0
256
+ }
257
+ if (!requestId || identity !== pane.menuSelectionIdentity() || (action === "rename" && !menuId))
258
+ snapshot(action === "rename" && !menuId ? [pane.cursorIndex] : undefined)
259
+ pendingAction = action
260
+ pendingActivation = false
261
+ if (ready) show(action)
262
+ }
263
+ function activate(action, selected) {
264
+ // Flash to drive re-reads what the menu showed: the snapshot already proved the selection names it.
265
+ if (action === "flashDrive") {
266
+ var flashIdx = Ops.targetIndices(pane)
267
+ var flashRow = flashIdx.length === 1 ? pane.rowFor(flashIdx[0]) : null
268
+ if (!requestId || identity !== pane.menuSelectionIdentity() || !flashRow
269
+ || !Archive.isDiskImage(flashRow.n, pane.flashZipMember)) {
270
+ pane.message("Selected items changed; reopen the menu.", true)
271
+ return
272
+ }
273
+ activationUsed = true
274
+ pane.openFlashImage(pane.join(Search.baseOf(pane), flashRow.n))
275
+ return
276
+ }
277
+ if (!selected) {
278
+ if (action === "addFavourite") {
279
+ if (backgroundFolder !== pane.path) { pane.message("Folder changed; reopen the menu.", true); return }
280
+ addFavourite(backgroundFolder)
281
+ } else pane.performMenu(action, 0, null)
282
+ return
283
+ }
284
+ if (activationUsed) return
285
+ if (deleting || survivorId) { pane.message("The deletion is still finishing.", false); return }
286
+ if (!requestId || identity !== pane.menuSelectionIdentity()) {
287
+ pane.message("Selected items changed; reopen the menu.", true)
288
+ return
289
+ }
290
+ // A tag toggle repeats inside one open menu; every other choice closes it, so one activation is all it gets.
291
+ if (action.indexOf("tags:") === 0 && (tagInFlight || (pendingActivation && pendingAction.indexOf("tags:") === 0))) {
292
+ queuedTags = queuedTags.concat([action])
293
+ return
294
+ }
295
+ queuedTags = []
296
+ activationUsed = action.indexOf("tags:") !== 0
297
+ providerValidated = false
298
+ pendingAction = action
299
+ pendingActivation = true
300
+ if (ready) validateActivation()
301
+ }
302
+ function validateActivation() {
303
+ if (providerAction(pendingAction) && !providerValidated) { refreshProviders(pendingAction); return }
304
+ var action = pendingAction
305
+ pendingAction = ""
306
+ pendingActivation = false
307
+ var split = action.indexOf(":")
308
+ if (providerAction(action) && !pane.contextMenu().validateChoice(split < 0 ? action : action.substring(0, split),
309
+ split < 0 ? "" : action.substring(split + 1), sheetRequest === requestId)) return
310
+ // OpenWith.html rule 2: the flyout is a one-off override that writes nothing, so a chosen
311
+ // application launches through the same registry op the dialog submits, and the tail row is
312
+ // the only way into the dialog, which stays the one place a default is written.
313
+ if (action.indexOf("openWith:") === 0) {
314
+ var chosen = action.substring("openWith:".length)
315
+ if (chosen === Menu.OPEN_WITH_OTHER) { root.show("openWith"); return }
316
+ root.launchingId = requestId
317
+ pane.backend.send({c: "menuaction", op: "openWith", id: requestId, application: chosen})
318
+ return
319
+ }
320
+ pane.backend.send({c: "menuaction", op: "activate", id: requestId, action: action,
321
+ dest: pane.dropboxService ? pane.dropboxService.dropboxPath : ""})
322
+ tagInFlight = action.indexOf("tags:") === 0
323
+ }
324
+ // The answer to a tag activate frees the menu slot, so the next queued tag goes out now.
325
+ function sendNextTag() {
326
+ tagInFlight = false
327
+ if (queuedTags.length === 0) return
328
+ pendingAction = queuedTags[0]
329
+ queuedTags = queuedTags.slice(1)
330
+ pendingActivation = true
331
+ validateActivation()
332
+ }
333
+ function show(action) {
334
+ pendingAction = ""
335
+ if (action === "rename") {
336
+ Ops.startRename(pane, requestId, pendingRenameIndex, pendingRenameStill ? 0 : undefined)
337
+ pendingRenameIndex = -1
338
+ pendingRenameStill = false
339
+ return
340
+ }
341
+ dialogFor = action
342
+ active = true
343
+ item.open(action, requestId, folder, pane.listArea)
344
+ }
345
+ function addFavourite(path) {
346
+ Favourites.add(path, path.split("/").filter(function (part) { return part.length > 0 }).pop() || "/")
347
+ }
348
+ function locateSurvivors() {
349
+ if (!survivorId || pane.listInFlight) return
350
+ if (pane.path !== survivorFolder) { survivorId = 0; survivors = []; return }
351
+ survivorListing = pane.menuSelectionIdentity()
352
+ pane.backend.send({c: "locate", paths: survivors, id: survivorId, menuId: survivorId})
353
+ }
354
+ Connections {
355
+ target: root.pane.contextMenu()
356
+ function onOpenedChanged() {
357
+ var menu = root.pane.contextMenu()
358
+ if (menu.opened && !menu.hasRow && !menu.forRail && !menu.forHeader)
359
+ root.backgroundFolder = root.pane.path
360
+ if (menu.opened && menu.hasRow && !menu.forRail && !menu.forHeader) root.refreshProviders()
361
+ }
362
+ }
363
+ Connections {
364
+ target: root.pane.taildropService
365
+ function onRefreshed() {
366
+ if (root.providersRefreshing && root.taildropRefreshWaiting) root.taildropRefreshWaiting = !root.pane.taildropService.refresh(root.providerFacts)
367
+ root.finishProviders()
368
+ }
369
+ }
370
+ Connections {
371
+ target: root.pane.dropboxService
372
+ function onDropboxRefreshed() {
373
+ if (root.providersRefreshing && root.dropboxRefreshWaiting) root.dropboxRefreshWaiting = !root.pane.dropboxService.refreshDropbox(root.providerFacts)
374
+ root.finishProviders()
375
+ }
376
+ }
377
+ Connections {
378
+ target: root.pane
379
+ function onListInFlightChanged() { if (!root.pane.listInFlight) root.locateSurvivors() }
380
+ }
381
+ Connections {
382
+ target: root.pane.backend
383
+ function onFormatsResult(message) {
384
+ if (!root.providersRefreshing || message.id !== root.providerFormatsId) return
385
+ root.providerFacts = message.providers || {}
386
+ root.taildropRefreshWaiting = root.refreshingTaildrop && !root.pane.taildropService.refresh(root.providerFacts)
387
+ root.dropboxRefreshWaiting = root.refreshingDropbox && root.pane.dropboxService
388
+ ? !root.pane.dropboxService.refreshDropbox(root.providerFacts) : false
389
+ root.providerQueriesStarted = true
390
+ root.localSend.refresh((root.providerFacts.localsend || {}).installed === true)
391
+ root.finishProviders()
392
+ }
393
+ function onChanged(path) { if (path === root.folder && root.item) root.item.sourceChanged() }
394
+ function onLocated(message) {
395
+ if (!root.survivorId || message.id !== root.survivorId) return
396
+ root.survivorId = 0
397
+ root.survivors = []
398
+ if (message.directory !== root.pane.path || root.pane.path !== root.survivorFolder
399
+ || root.survivorListing !== root.pane.menuSelectionIdentity()) return
400
+ if (!message.ok) { root.pane.message(message.error, true); return }
401
+ var matches = message.matches || []
402
+ root.pane.selection.clear()
403
+ for (var i = 0; i < matches.length; i++) root.pane.selection.toggle(matches[i].index)
404
+ root.pane.selectionVersion++
405
+ if (matches.length) root.pane.setCursor(matches[0].index)
406
+ }
407
+ function onMenuResult(message) {
408
+ if (message.op === "openWith" && message.id === root.launchingId) {
409
+ root.launchingId = 0
410
+ if (!root.opened || message.id !== root.requestId) {
411
+ if (!message.ok && !message.cancelled) root.pane.message(message.error || "The application could not be opened.", true)
412
+ return
413
+ }
414
+ }
415
+ if (message.id !== root.requestId) return
416
+ if (message.op === "applications") {
417
+ // Both readers want it: the flyout's registry, and an open dialog that asked for it.
418
+ if (root.item) root.item.receive(message)
419
+ root.openWithApps = message.applications || []
420
+ root.openWithLoaded = true
421
+ root.pane.contextMenu().refreshProviderRows()
422
+ return
423
+ }
424
+ if (message.op === "providerDestination") {
425
+ root.providerDestinationPending = false
426
+ if (!message.ok && root.pane.dropboxService) {
427
+ root.pane.dropboxService.dropboxReason = message.error
428
+ root.pane.dropboxService.dropboxCode = ""
429
+ }
430
+ root.providersFinished()
431
+ return
432
+ }
433
+ if (message.op === "snapshot") {
434
+ root.selectedKinds = message.kinds || []
435
+ root.ready = message.ok === true && root.identity === root.pane.menuSelectionIdentity()
436
+ if (!root.ready) {
437
+ // A late snapshot answers no dismissed menu with nothing awaiting it; an open one keeps its refusal.
438
+ var retired = message.ok === true && !root.pane.contextMenu().opened && !root.opened
439
+ && !root.pendingAction && !root.pendingActivation
440
+ root.pendingAction = ""
441
+ root.pendingActivation = false
442
+ root.queuedTags = []
443
+ root.tagInFlight = false
444
+ root.providersRefreshing = false
445
+ root.identity = ""
446
+ if (!retired)
447
+ root.pane.message(message.error || "Selected items changed; reopen the menu.", true)
448
+ } else if (root.pendingAction) {
449
+ if (root.pendingActivation) root.validateActivation()
450
+ else root.show(root.pendingAction)
451
+ }
452
+ // Multi-selection has no registry: the backend refuses it, so discovery stays single-item.
453
+ if (root.ready && message.count === 1 && root.pane.contextMenu().opened && root.pane.contextMenu().hasRow)
454
+ // No installed flag: the flyout draws the registry alone, and asking for the
455
+ // whole catalogue here walked every applications directory on every right-click.
456
+ root.pane.backend.send({c: "menuaction", op: "applications", id: root.requestId})
457
+ root.pane.contextMenu().refreshProviderRows()
458
+ root.finishProviders()
459
+ return
460
+ }
461
+ if (message.op === "activate") {
462
+ if (!message.ok || root.identity !== root.pane.menuSelectionIdentity()) {
463
+ root.queuedTags = []
464
+ root.tagInFlight = false
465
+ root.pane.message(message.error || "Selected items changed; reopen the menu.", true)
466
+ return
467
+ }
468
+ var split = message.action.indexOf(":")
469
+ var action = split < 0 ? message.action : message.action.substring(0, split)
470
+ var subId = split < 0 ? "" : message.action.substring(split + 1)
471
+ if (root.pane.contextMenu().validateChoice(action, subId, root.sheetRequest === message.id)) {
472
+ if (action === "addFavourite") {
473
+ if (!message.paths || message.paths.length !== 1) { root.pane.message("The selected folder could not be read.", true); return }
474
+ root.addFavourite(message.paths[0])
475
+ } else root.pane.performMenu(message.action, message.id, message.paths)
476
+ }
477
+ if (action === "tags") root.sendNextTag()
478
+ return
479
+ }
480
+ if (root.item) root.item.receive(message)
481
+ }
482
+ function onFailed(where, input, message, mode) {
483
+ if (where !== "backend") return
484
+ root.survivorId = 0
485
+ root.survivors = []
486
+ root.ready = false
487
+ root.identity = ""
488
+ root.pendingAction = ""
489
+ root.pendingActivation = false
490
+ root.queuedTags = []
491
+ root.tagInFlight = false
492
+ root.providersRefreshing = false
493
+ if (root.opened || root.deleting) root.item.receive({id: root.requestId, op: root.deleting ? "delete" : "", ok: false, error: message})
494
+ }
495
+ }
496
+ Connections {
497
+ target: root.item
498
+ // Two dialogs load here and only one of them creates files or deletes them, so the handlers
499
+ // the other never raises are absent by design rather than misspelled.
500
+ ignoreUnknownSignals: true
501
+ function onRequested(message) {
502
+ if (message.op === "openWith") root.launchingId = message.id
503
+ root.pane.backend.send(message)
504
+ }
505
+ function onApproved(message) {
506
+ root.pane.asks().ask({c: "transfer", op: message.action === "moveTo" ? "move" : "copy",
507
+ menuId: message.id, dest: message.dest})
508
+ }
509
+ function onCreated(path) { root.pane.refresh(path); root.pane.message(Ops.createdLine(path), false) }
510
+ function onDeleted(message) {
511
+ var text = Ops.deletedLine(message)
512
+ root.pane.operationResult(text, message.error || "", message.failed > 0)
513
+ if (root.pane.path !== root.folder) return
514
+ root.survivors = message.remaining || []
515
+ root.survivorId = root.survivors.length ? message.id : 0
516
+ root.survivorFolder = root.folder
517
+ root.pane.refresh()
518
+ }
519
+ function onClosed() {
520
+ root.ready = false
521
+ root.identity = ""
522
+ // The close op kills the launcher this id was waiting on, so its error is the cancellation
523
+ // the user asked for and not something to raise at them.
524
+ root.launchingId = 0
525
+ }
526
+ }
527
+ }
@@ -0,0 +1,90 @@
1
+ import QtQuick
2
+ import "." as Flea
3
+ import "js/Crumbs.js" as Crumbs
4
+
5
+ // A dual pane's own path, drawn with the chrome's crumbs so issue 45's one tap on a parent reaches either pane.
6
+ Rectangle {
7
+ id: root
8
+
9
+ property string path: ""
10
+ property string home: ""
11
+ property var pathAlias: null
12
+ property bool focused: false
13
+ // ui/ChromeBar.qml's inputLive: false while Quick Look covers the strip, so a press on it stays Quick Look's.
14
+ property bool inputLive: true
15
+ // Drops callout 4: the pane whose collide sends a drop on a crumb.
16
+ property var pane: null
17
+ readonly property alias crumbItems: crumbs
18
+ readonly property alias crumbSlot: slot
19
+
20
+ signal chosen(string path)
21
+ signal editRequested()
22
+
23
+ color: root.focused ? Glass.surface : Glass.background
24
+
25
+ // Where no crumb is, the strip keeps the one gesture it had before issue 45: a double click types the path.
26
+ component TypeArea: Item {
27
+ HoverHandler {
28
+ enabled: root.inputLive
29
+ cursorShape: Qt.IBeamCursor
30
+ }
31
+ TapHandler {
32
+ enabled: root.inputLive
33
+ acceptedButtons: Qt.LeftButton
34
+ onDoubleTapped: root.editRequested()
35
+ }
36
+ }
37
+
38
+ // One glyph's advance is every glyph's advance in this face, the same fit ui/ChromeBar.qml makes.
39
+ TextMetrics {
40
+ id: metrics
41
+ font.family: Theme.font.family
42
+ font.pixelSize: Theme.font.caption
43
+ text: "0"
44
+ }
45
+
46
+ Item {
47
+ id: slot
48
+ anchors.fill: parent
49
+ clip: true
50
+
51
+ Row {
52
+ id: row
53
+ x: Theme.spacing.rowPaddingX
54
+ height: slot.height
55
+
56
+ Repeater {
57
+ id: crumbs
58
+ // Empty while the strip is hidden, because the single view keeps it at height 0 and would rebuild its crumbs on every move.
59
+ model: root.visible
60
+ ? Crumbs.fitCrumbs(Crumbs.crumbs(root.path, root.home, root.pathAlias),
61
+ Math.floor((slot.width - 2 * Theme.spacing.rowPaddingX) / metrics.advanceWidth))
62
+ : []
63
+
64
+ delegate: Flea.Crumb {
65
+ height: slot.height
66
+ restColor: Theme.color.foreground
67
+ inputLive: root.inputLive
68
+ dropPane: root.pane
69
+ onChosen: function (path) { root.chosen(path) }
70
+ onEditRequested: root.editRequested()
71
+ }
72
+ }
73
+ }
74
+
75
+ TypeArea {
76
+ anchors { left: parent.left; top: parent.top; bottom: parent.bottom }
77
+ width: Theme.spacing.rowPaddingX
78
+ }
79
+
80
+ TypeArea {
81
+ anchors { left: row.right; right: parent.right; top: parent.top; bottom: parent.bottom }
82
+ }
83
+ }
84
+
85
+ Rectangle {
86
+ anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
87
+ height: Theme.spacing.hairline
88
+ color: Theme.color.mutedFrame
89
+ }
90
+ }