flea-qml 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (625) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +478 -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 +402 -0
  51. package/src/archiveops.js +697 -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 +129 -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/transfer.js +669 -0
  82. package/src/trash-record.js +41 -0
  83. package/src/trash.js +210 -0
  84. package/src/trashbrowse.js +326 -0
  85. package/src/uistate.js +393 -0
  86. package/src/uistore.js +168 -0
  87. package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
  88. package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
  89. package/src/vendor/LICENSES/MIT-katex.txt +21 -0
  90. package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
  91. package/src/vendor/LICENSES/MIT-pele.txt +40 -0
  92. package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
  93. package/src/vendor/LICENSES/MIT-temml.txt +21 -0
  94. package/src/vendor/pele.js +145 -0
  95. package/src/vendor/temml.mjs +14708 -0
  96. package/src/watch.js +98 -0
  97. package/src/wayland/client.js +109 -0
  98. package/src/wayland/protocol.js +55 -0
  99. package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
  100. package/src/wayland/protocols/wayland.xml +3248 -0
  101. package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
  102. package/src/wayland/resource-io.js +6 -0
  103. package/src/wayland/socket-discovery.js +26 -0
  104. package/src/wayland/transport-posix.js +120 -0
  105. package/src/wayland/transport-win32.js +11 -0
  106. package/src/wayland/transport.js +3 -0
  107. package/src/wayland/win32-resources.js +80 -0
  108. package/src/wayland/win32-wire.js +62 -0
  109. package/test/archive.test.js +80 -0
  110. package/test/bench-markdown-scroll.mjs +190 -0
  111. package/test/clip-host.test.js +113 -0
  112. package/test/code-preview.test.js +35 -0
  113. package/test/compare-ui-paths.test.js +24 -0
  114. package/test/compare.test.js +54 -0
  115. package/test/delete-trash.test.js +67 -0
  116. package/test/dirsize.test.js +138 -0
  117. package/test/file-ops.test.js +241 -0
  118. package/test/find-contents.test.js +161 -0
  119. package/test/find-input.test.js +66 -0
  120. package/test/fixtures/pele-parity.json +1006 -0
  121. package/test/highlight-launcher.test.js +35 -0
  122. package/test/html-preview.test.js +22 -0
  123. package/test/input.test.js +15 -0
  124. package/test/keymap.test.js +26 -0
  125. package/test/language-icons.test.js +36 -0
  126. package/test/launcher.test.js +51 -0
  127. package/test/manual-code-scroll.mjs +28 -0
  128. package/test/manual-column-scroll.mjs +24 -0
  129. package/test/manual-compare-ui.mjs +20 -0
  130. package/test/manual-find-status.mjs +37 -0
  131. package/test/manual-html-security.mjs +23 -0
  132. package/test/manual-html-ui.mjs +30 -0
  133. package/test/manual-syntax-preview.mjs +26 -0
  134. package/test/manual-trash-ui.mjs +86 -0
  135. package/test/markdown-diagrams.test.js +93 -0
  136. package/test/markdown-html.test.js +105 -0
  137. package/test/mathml.test.js +92 -0
  138. package/test/menu-transfer.test.js +57 -0
  139. package/test/office-preview.test.js +154 -0
  140. package/test/pele-parity.test.js +28 -0
  141. package/test/places.test.js +134 -0
  142. package/test/preview-keys.test.js +60 -0
  143. package/test/preview-language.test.js +22 -0
  144. package/test/status-filename.test.js +20 -0
  145. package/test/transfer-replace-merge.test.js +187 -0
  146. package/test/trash-address.test.js +23 -0
  147. package/test/trash-view.test.js +37 -0
  148. package/test/trashbrowse.test.js +135 -0
  149. package/ui/AboutFacts.qml +78 -0
  150. package/ui/ArchiveCards.qml +68 -0
  151. package/ui/ArchiveCompressDialog.qml +378 -0
  152. package/ui/ArchivePasswordDialog.qml +257 -0
  153. package/ui/Backend.qml +771 -0
  154. package/ui/BulkOldNames.qml +47 -0
  155. package/ui/BulkRenameDialog.qml +380 -0
  156. package/ui/CardFrame.qml +67 -0
  157. package/ui/CardScroll.qml +79 -0
  158. package/ui/CheckBox.qml +73 -0
  159. package/ui/ChromeBar.qml +360 -0
  160. package/ui/ChromeButton.qml +131 -0
  161. package/ui/ChromeModes.qml +43 -0
  162. package/ui/CodeLines.qml +256 -0
  163. package/ui/CodeRefusal.qml +52 -0
  164. package/ui/CollideConfirm.qml +147 -0
  165. package/ui/CollideHost.qml +167 -0
  166. package/ui/ColumnPane.qml +523 -0
  167. package/ui/ColumnRow.qml +380 -0
  168. package/ui/ColumnsArea.qml +594 -0
  169. package/ui/ColumnsLanding.qml +147 -0
  170. package/ui/CompareView.qml +321 -0
  171. package/ui/ContextMenu.qml +743 -0
  172. package/ui/ConvertDialog.qml +456 -0
  173. package/ui/CountedWorker.qml +7 -0
  174. package/ui/Crumb.qml +64 -0
  175. package/ui/CrumbDrop.qml +25 -0
  176. package/ui/CsvTable.qml +394 -0
  177. package/ui/CursorMark.qml +41 -0
  178. package/ui/DefaultClaim.qml +130 -0
  179. package/ui/DeviceLock.qml +47 -0
  180. package/ui/DeviceMounts.qml +540 -0
  181. package/ui/DialogButton.qml +150 -0
  182. package/ui/DialogField.qml +147 -0
  183. package/ui/DialogHeader.qml +31 -0
  184. package/ui/DialogScrim.qml +20 -0
  185. package/ui/DialogTitle.qml +37 -0
  186. package/ui/Divider.qml +9 -0
  187. package/ui/DropInto.qml +126 -0
  188. package/ui/DropTarget.qml +35 -0
  189. package/ui/DropboxMark.qml +60 -0
  190. package/ui/EmptyState.qml +150 -0
  191. package/ui/EscapeHint.qml +11 -0
  192. package/ui/FactsTable.qml +54 -0
  193. package/ui/FastScrollHandler.qml +476 -0
  194. package/ui/FatNamesConfirm.qml +157 -0
  195. package/ui/Favourites.qml +143 -0
  196. package/ui/FigureService.qml +120 -0
  197. package/ui/FileDrag.qml +267 -0
  198. package/ui/FilterStrip.qml +133 -0
  199. package/ui/FitMetrics.qml +22 -0
  200. package/ui/FlashDriveRows.qml +137 -0
  201. package/ui/FlashHost.qml +72 -0
  202. package/ui/FlashImageRow.qml +104 -0
  203. package/ui/FlashRunner.qml +119 -0
  204. package/ui/FlashStepRow.qml +172 -0
  205. package/ui/FlashStrip.qml +38 -0
  206. package/ui/FlashView.qml +397 -0
  207. package/ui/FleaMark.qml +88 -0
  208. package/ui/FlyoutFade.qml +23 -0
  209. package/ui/FontPane.qml +170 -0
  210. package/ui/Glass.qml +114 -0
  211. package/ui/GlassTagger.qml +59 -0
  212. package/ui/Glyph.qml +64 -0
  213. package/ui/GlyphSolid.qml +22 -0
  214. package/ui/GridArea.qml +664 -0
  215. package/ui/GridTile.qml +325 -0
  216. package/ui/GvfsBridge.qml +164 -0
  217. package/ui/Header.qml +433 -0
  218. package/ui/HoverTimers.qml +39 -0
  219. package/ui/HtmlClip.qml +30 -0
  220. package/ui/HtmlPane.qml +63 -0
  221. package/ui/HyprlandMark.qml +45 -0
  222. package/ui/Ipc.qml +1005 -0
  223. package/ui/IpcControls.qml +7 -0
  224. package/ui/IpcMenuState.qml +48 -0
  225. package/ui/IpcPreviewState.qml +185 -0
  226. package/ui/JumpPath.qml +51 -0
  227. package/ui/KeymapSheet.qml +561 -0
  228. package/ui/KeymapSheetResult.qml +89 -0
  229. package/ui/KindStack.qml +40 -0
  230. package/ui/LangMark.qml +51 -0
  231. package/ui/LangMarkLoader.qml +26 -0
  232. package/ui/List.qml +480 -0
  233. package/ui/LoadingState.qml +54 -0
  234. package/ui/LocalSend.qml +56 -0
  235. package/ui/LocalSendMark.qml +73 -0
  236. package/ui/MarkdownBlockView.qml +311 -0
  237. package/ui/MarkdownBlocks.qml +35 -0
  238. package/ui/MarkdownFigure.qml +254 -0
  239. package/ui/MarkdownImages.qml +72 -0
  240. package/ui/MarkdownList.qml +81 -0
  241. package/ui/MarkdownMathsText.qml +97 -0
  242. package/ui/MarkdownPane.qml +83 -0
  243. package/ui/MarkdownPictures.qml +41 -0
  244. package/ui/MarkdownQuote.qml +52 -0
  245. package/ui/MarkdownRemote.qml +82 -0
  246. package/ui/MarkdownSource.qml +155 -0
  247. package/ui/MarkdownTable.qml +222 -0
  248. package/ui/MarkdownTableScroll.qml +64 -0
  249. package/ui/MarkdownTableWheel.qml +126 -0
  250. package/ui/MarkdownText.qml +87 -0
  251. package/ui/MarkdownWorker.js +132 -0
  252. package/ui/MatchText.qml +99 -0
  253. package/ui/MediaSession.qml +38 -0
  254. package/ui/MediaSound.qml +26 -0
  255. package/ui/MediaStrip.qml +191 -0
  256. package/ui/MediaTrack.qml +36 -0
  257. package/ui/MediaVolume.qml +54 -0
  258. package/ui/MenuActionDialog.qml +396 -0
  259. package/ui/MenuEdgeFade.qml +24 -0
  260. package/ui/MenuHost.qml +227 -0
  261. package/ui/MenuRow.qml +351 -0
  262. package/ui/MountListing.qml +100 -0
  263. package/ui/NetworkDialog.qml +435 -0
  264. package/ui/NetworkForm.qml +426 -0
  265. package/ui/NetworkMounts.qml +913 -0
  266. package/ui/NetworkPlaces.qml +127 -0
  267. package/ui/OpenWithDialog.qml +613 -0
  268. package/ui/Opener.qml +115 -0
  269. package/ui/Pane.qml +1296 -0
  270. package/ui/PaneMenuActions.qml +527 -0
  271. package/ui/PanePath.qml +90 -0
  272. package/ui/PaneRail.qml +239 -0
  273. package/ui/PaneStates.qml +88 -0
  274. package/ui/PaneSwap.qml +339 -0
  275. package/ui/PaneWire.qml +605 -0
  276. package/ui/ParkedWait.qml +9 -0
  277. package/ui/PathEntry.qml +186 -0
  278. package/ui/PathJump.qml +400 -0
  279. package/ui/PdfViewer.qml +297 -0
  280. package/ui/PermissionsDialog.qml +658 -0
  281. package/ui/PermissionsHeadings.qml +31 -0
  282. package/ui/PhoneMounts.qml +67 -0
  283. package/ui/PickerAnswers.qml +75 -0
  284. package/ui/PickerBox.qml +26 -0
  285. package/ui/PickerChrome.qml +295 -0
  286. package/ui/PickerFilter.qml +97 -0
  287. package/ui/PickerGrid.qml +308 -0
  288. package/ui/PickerHeader.qml +28 -0
  289. package/ui/PickerLifecycle.qml +27 -0
  290. package/ui/PickerList.qml +218 -0
  291. package/ui/PickerListing.qml +149 -0
  292. package/ui/PickerPathBar.qml +127 -0
  293. package/ui/PickerPlaces.qml +189 -0
  294. package/ui/PickerRecent.qml +92 -0
  295. package/ui/PickerSave.qml +101 -0
  296. package/ui/PickerSelection.qml +155 -0
  297. package/ui/PickerWindow.qml +846 -0
  298. package/ui/PowerSectorsReader.qml +10 -0
  299. package/ui/PrebuildDriver.qml +146 -0
  300. package/ui/Preview.qml +1004 -0
  301. package/ui/PreviewAnimation.qml +24 -0
  302. package/ui/PreviewArchive.qml +66 -0
  303. package/ui/PreviewColumn.qml +551 -0
  304. package/ui/PreviewEdge.qml +63 -0
  305. package/ui/PreviewFacts.qml +30 -0
  306. package/ui/PreviewFactsLine.qml +34 -0
  307. package/ui/PreviewHtml.qml +233 -0
  308. package/ui/PreviewImage.qml +253 -0
  309. package/ui/PreviewImagePan.qml +13 -0
  310. package/ui/PreviewImageSharp.qml +32 -0
  311. package/ui/PreviewLines.qml +106 -0
  312. package/ui/PreviewMarkdown.qml +706 -0
  313. package/ui/PreviewMedia.qml +250 -0
  314. package/ui/PreviewPdf.qml +482 -0
  315. package/ui/PreviewScroll.qml +201 -0
  316. package/ui/PreviewSwap.qml +335 -0
  317. package/ui/PreviewText.qml +149 -0
  318. package/ui/ProtocolChip.qml +18 -0
  319. package/ui/QuickLookArchive.qml +38 -0
  320. package/ui/QuickLookBar.qml +103 -0
  321. package/ui/QuickLookPrepare.qml +355 -0
  322. package/ui/QuickLookSwap.qml +10 -0
  323. package/ui/QuickLookWarm.qml +65 -0
  324. package/ui/RailDrop.qml +155 -0
  325. package/ui/RailHeading.qml +19 -0
  326. package/ui/RailPlaces.qml +38 -0
  327. package/ui/RailTrashRow.qml +67 -0
  328. package/ui/RenameField.qml +353 -0
  329. package/ui/RendererRetry.qml +11 -0
  330. package/ui/ResizeHandle.qml +52 -0
  331. package/ui/Reveal.qml +54 -0
  332. package/ui/Row.qml +476 -0
  333. package/ui/RowDrag.qml +213 -0
  334. package/ui/RowDropTarget.qml +27 -0
  335. package/ui/RunCard.qml +286 -0
  336. package/ui/Scripts.qml +65 -0
  337. package/ui/SearchStrip.qml +232 -0
  338. package/ui/SelectionBand.qml +140 -0
  339. package/ui/SelectionPreview.qml +370 -0
  340. package/ui/SettingsFavourite.qml +122 -0
  341. package/ui/SettingsGroup.qml +96 -0
  342. package/ui/SettingsHint.qml +12 -0
  343. package/ui/SettingsMetrics.qml +29 -0
  344. package/ui/SettingsPane.qml +178 -0
  345. package/ui/SettingsPanel.qml +547 -0
  346. package/ui/SettingsRail.qml +128 -0
  347. package/ui/SettingsRow.qml +409 -0
  348. package/ui/SettingsRuler.qml +85 -0
  349. package/ui/SettingsSegment.qml +85 -0
  350. package/ui/ShareBrowser.qml +113 -0
  351. package/ui/ShareLink.qml +67 -0
  352. package/ui/ShelfPins.qml +101 -0
  353. package/ui/Sidebar.qml +732 -0
  354. package/ui/SidebarRow.qml +358 -0
  355. package/ui/Spinner.qml +60 -0
  356. package/ui/StableModel.qml +89 -0
  357. package/ui/StateMessage.qml +84 -0
  358. package/ui/StatusBar.qml +512 -0
  359. package/ui/StatusFileName.qml +27 -0
  360. package/ui/TabBar.qml +673 -0
  361. package/ui/TabDragGeometry.qml +60 -0
  362. package/ui/TagMenuMark.qml +52 -0
  363. package/ui/TagRailSection.qml +53 -0
  364. package/ui/TagSlot.qml +40 -0
  365. package/ui/TagState.qml +150 -0
  366. package/ui/TagSwatch.qml +28 -0
  367. package/ui/Taildrop.qml +86 -0
  368. package/ui/TailscaleMark.qml +50 -0
  369. package/ui/Theme.qml +460 -0
  370. package/ui/ThemeColors.qml +43 -0
  371. package/ui/TransferCard.qml +239 -0
  372. package/ui/TrashConfirm.qml +129 -0
  373. package/ui/TrashDropHandler.qml +11 -0
  374. package/ui/TrashHost.qml +202 -0
  375. package/ui/TrashMonitor.qml +30 -0
  376. package/ui/TrashToolbar.qml +19 -0
  377. package/ui/TrashView.qml +492 -0
  378. package/ui/UnlockDialog.qml +450 -0
  379. package/ui/UnlockHost.qml +206 -0
  380. package/ui/UpdateCheck.qml +97 -0
  381. package/ui/UserDirs.qml +25 -0
  382. package/ui/ViewState.qml +565 -0
  383. package/ui/ViewportScrollBar.qml +195 -0
  384. package/ui/ViewportScrollBars.qml +25 -0
  385. package/ui/WebPreview.qml +33 -0
  386. package/ui/WebPreviewView.qml +26 -0
  387. package/ui/WindowBody.qml +827 -0
  388. package/ui/WindowDrag.qml +35 -0
  389. package/ui/boot/Commons/AudioNodes.qml +50 -0
  390. package/ui/boot/Commons/AudioNodesModel.js +96 -0
  391. package/ui/boot/Commons/Border.qml +243 -0
  392. package/ui/boot/Commons/BorderGeometry.js +373 -0
  393. package/ui/boot/Commons/Color.qml +258 -0
  394. package/ui/boot/Commons/I18n.qml +118 -0
  395. package/ui/boot/Commons/InputDevices.qml +112 -0
  396. package/ui/boot/Commons/InputMethodState.qml +38 -0
  397. package/ui/boot/Commons/IpcRegistry.qml +77 -0
  398. package/ui/boot/Commons/Numbers.js +19 -0
  399. package/ui/boot/Commons/Plural.js +91 -0
  400. package/ui/boot/Commons/ShellIpc.qml +12 -0
  401. package/ui/boot/Commons/Style.qml +561 -0
  402. package/ui/boot/Commons/Translations.qml +100 -0
  403. package/ui/boot/Commons/UntypedInput.qml +152 -0
  404. package/ui/boot/Commons/Util.qml +188 -0
  405. package/ui/boot/Commons/qmldir +13 -0
  406. package/ui/boot/LICENSE-omarchy +20 -0
  407. package/ui/boot/Ui/BackgroundMedia.qml +49 -0
  408. package/ui/boot/Ui/BarIconButton.qml +106 -0
  409. package/ui/boot/Ui/BarIconContent.qml +38 -0
  410. package/ui/boot/Ui/BarIndicator.qml +53 -0
  411. package/ui/boot/Ui/BarWidget.qml +50 -0
  412. package/ui/boot/Ui/BorderOverlay.qml +54 -0
  413. package/ui/boot/Ui/BorderSurface.qml +40 -0
  414. package/ui/boot/Ui/Button.qml +224 -0
  415. package/ui/boot/Ui/ButtonGroup.qml +131 -0
  416. package/ui/boot/Ui/ConfirmDialog.qml +134 -0
  417. package/ui/boot/Ui/CursorSurface.qml +42 -0
  418. package/ui/boot/Ui/Dropdown.qml +245 -0
  419. package/ui/boot/Ui/FilterInput.qml +26 -0
  420. package/ui/boot/Ui/IconContentBounds.qml +141 -0
  421. package/ui/boot/Ui/KeyboardPanel.qml +453 -0
  422. package/ui/boot/Ui/MultiSelect.qml +624 -0
  423. package/ui/boot/Ui/NumberField.qml +86 -0
  424. package/ui/boot/Ui/OpticalGlyph.qml +68 -0
  425. package/ui/boot/Ui/OverlayWindow.qml +102 -0
  426. package/ui/boot/Ui/Panel.qml +60 -0
  427. package/ui/boot/Ui/PanelActionButton.qml +105 -0
  428. package/ui/boot/Ui/PanelController.qml +16 -0
  429. package/ui/boot/Ui/PanelHero.qml +112 -0
  430. package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
  431. package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
  432. package/ui/boot/Ui/PanelSeparator.qml +19 -0
  433. package/ui/boot/Ui/PanelSlider.qml +156 -0
  434. package/ui/boot/Ui/PanelToolTip.qml +50 -0
  435. package/ui/boot/Ui/PluginBarApi.qml +89 -0
  436. package/ui/boot/Ui/PointerMoveGate.qml +54 -0
  437. package/ui/boot/Ui/PopupCard.qml +181 -0
  438. package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
  439. package/ui/boot/Ui/SearchableDropdown.qml +354 -0
  440. package/ui/boot/Ui/SizedImage.qml +125 -0
  441. package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
  442. package/ui/boot/Ui/TextField.qml +58 -0
  443. package/ui/boot/Ui/Toggle.qml +118 -0
  444. package/ui/boot/Ui/ToggleSwitch.qml +115 -0
  445. package/ui/boot/Ui/WidgetButton.qml +172 -0
  446. package/ui/boot/Ui/qmldir +41 -0
  447. package/ui/boot/fleatab.qml +50 -0
  448. package/ui/boot/picker.qml +39 -0
  449. package/ui/boot/shell.qml +122 -0
  450. package/ui/boot/tabtearoff.qml +51 -0
  451. package/ui/js/Anchor.js +379 -0
  452. package/ui/js/AnchorHold.js +162 -0
  453. package/ui/js/Archive.js +157 -0
  454. package/ui/js/ArchiveCard.js +44 -0
  455. package/ui/js/ArchiveOps.js +44 -0
  456. package/ui/js/BackReturn.js +118 -0
  457. package/ui/js/BulkRename.js +100 -0
  458. package/ui/js/Buttons.js +54 -0
  459. package/ui/js/ChromeKeys.js +116 -0
  460. package/ui/js/ClipMarks.js +73 -0
  461. package/ui/js/ClipSelection.js +67 -0
  462. package/ui/js/Clipboard.js +179 -0
  463. package/ui/js/Cloud.js +97 -0
  464. package/ui/js/CodeRuns.js +72 -0
  465. package/ui/js/Collide.js +212 -0
  466. package/ui/js/ColumnFit.js +28 -0
  467. package/ui/js/ColumnMenu.js +111 -0
  468. package/ui/js/Columns.js +298 -0
  469. package/ui/js/ColumnsCarry.js +103 -0
  470. package/ui/js/Compare.js +74 -0
  471. package/ui/js/Contrast.js +157 -0
  472. package/ui/js/ControlReader.js +42 -0
  473. package/ui/js/Convert.js +52 -0
  474. package/ui/js/CopyAs.js +52 -0
  475. package/ui/js/Crumbs.js +178 -0
  476. package/ui/js/Csv.js +231 -0
  477. package/ui/js/Density.js +44 -0
  478. package/ui/js/Devices.js +440 -0
  479. package/ui/js/DirSizes.js +180 -0
  480. package/ui/js/Drag.js +364 -0
  481. package/ui/js/DragOut.js +166 -0
  482. package/ui/js/DropDev.js +52 -0
  483. package/ui/js/Dropbox.js +41 -0
  484. package/ui/js/Eject.js +217 -0
  485. package/ui/js/Errors.js +188 -0
  486. package/ui/js/ExtThumbs.js +115 -0
  487. package/ui/js/Facts.js +402 -0
  488. package/ui/js/FigureDate.js +14 -0
  489. package/ui/js/Filter.js +285 -0
  490. package/ui/js/Find.js +46 -0
  491. package/ui/js/Flash.js +184 -0
  492. package/ui/js/FlashCard.js +79 -0
  493. package/ui/js/FlashEndings.js +125 -0
  494. package/ui/js/FlashPane.js +116 -0
  495. package/ui/js/FleaBin.js +12 -0
  496. package/ui/js/Focus.js +502 -0
  497. package/ui/js/FolderSorts.js +108 -0
  498. package/ui/js/FolderViews.js +44 -0
  499. package/ui/js/Format.js +305 -0
  500. package/ui/js/Fuzzy.js +141 -0
  501. package/ui/js/GlassTag.js +72 -0
  502. package/ui/js/Grid.js +33 -0
  503. package/ui/js/GridGeometry.js +90 -0
  504. package/ui/js/GridNames.js +153 -0
  505. package/ui/js/GvfsBridge.js +200 -0
  506. package/ui/js/HostClipboard.js +29 -0
  507. package/ui/js/Icons.js +218 -0
  508. package/ui/js/Input.js +50 -0
  509. package/ui/js/Jump.js +200 -0
  510. package/ui/js/KeyName.js +64 -0
  511. package/ui/js/Keymap.js +401 -0
  512. package/ui/js/Kinds.js +164 -0
  513. package/ui/js/LICENSES/ISC-lucide.txt +43 -0
  514. package/ui/js/LangMarkPaths.js +47 -0
  515. package/ui/js/LangMarks.js +120 -0
  516. package/ui/js/Lists.js +11 -0
  517. package/ui/js/LocalSend.js +39 -0
  518. package/ui/js/LockedMenu.js +63 -0
  519. package/ui/js/MakeDefault.js +186 -0
  520. package/ui/js/MarkBox.js +7 -0
  521. package/ui/js/Markdown.js +119 -0
  522. package/ui/js/MarkdownLists.js +86 -0
  523. package/ui/js/MarkdownMaths.js +58 -0
  524. package/ui/js/MarkdownPictures.js +32 -0
  525. package/ui/js/MarkdownPrepared.js +139 -0
  526. package/ui/js/MarkdownTableFit.js +34 -0
  527. package/ui/js/Marks.js +148 -0
  528. package/ui/js/Marquee.js +96 -0
  529. package/ui/js/Match.js +93 -0
  530. package/ui/js/Material.js +109 -0
  531. package/ui/js/MdBlocks.js +437 -0
  532. package/ui/js/MdBreak.js +71 -0
  533. package/ui/js/MdChunks.js +70 -0
  534. package/ui/js/MdContainer.js +137 -0
  535. package/ui/js/MdDocument.js +337 -0
  536. package/ui/js/MdEmph.js +97 -0
  537. package/ui/js/MdEntity.js +108 -0
  538. package/ui/js/MdEntityTable.js +223 -0
  539. package/ui/js/MdEscape.js +59 -0
  540. package/ui/js/MdFront.js +37 -0
  541. package/ui/js/MdHold.js +32 -0
  542. package/ui/js/MdHtml.js +307 -0
  543. package/ui/js/MdHtmlBlock.js +290 -0
  544. package/ui/js/MdHtmlHeading.js +53 -0
  545. package/ui/js/MdHtmlImage.js +179 -0
  546. package/ui/js/MdInline.js +154 -0
  547. package/ui/js/MdItems.js +212 -0
  548. package/ui/js/MdLeaf.js +309 -0
  549. package/ui/js/MdLink.js +196 -0
  550. package/ui/js/MdMath.js +67 -0
  551. package/ui/js/MdParagraphs.js +138 -0
  552. package/ui/js/MdRefs.js +232 -0
  553. package/ui/js/MdResolve.js +226 -0
  554. package/ui/js/MdRun.js +300 -0
  555. package/ui/js/MdUrl.js +226 -0
  556. package/ui/js/Menu.js +514 -0
  557. package/ui/js/MenuContext.js +85 -0
  558. package/ui/js/MenuFit.js +13 -0
  559. package/ui/js/MenuRefresh.js +74 -0
  560. package/ui/js/MenuWheel.js +35 -0
  561. package/ui/js/Messages.js +186 -0
  562. package/ui/js/Motion.js +16 -0
  563. package/ui/js/Mounts.js +320 -0
  564. package/ui/js/MouseNav.js +13 -0
  565. package/ui/js/Nav.js +329 -0
  566. package/ui/js/NetFs.js +26 -0
  567. package/ui/js/OpenWith.js +83 -0
  568. package/ui/js/Ops.js +585 -0
  569. package/ui/js/Palette.js +33 -0
  570. package/ui/js/PathBar.js +260 -0
  571. package/ui/js/Permissions.js +179 -0
  572. package/ui/js/Phones.js +112 -0
  573. package/ui/js/Picker.js +353 -0
  574. package/ui/js/PlaceMenu.js +96 -0
  575. package/ui/js/Places.js +265 -0
  576. package/ui/js/PreviewAsk.js +21 -0
  577. package/ui/js/PreviewKeys.js +155 -0
  578. package/ui/js/PreviewSettle.js +29 -0
  579. package/ui/js/PreviewSwap.js +101 -0
  580. package/ui/js/PropertyFacts.js +144 -0
  581. package/ui/js/Protocols.js +296 -0
  582. package/ui/js/QuickLookKinds.js +27 -0
  583. package/ui/js/QuickLookRect.js +24 -0
  584. package/ui/js/RailDrop.js +51 -0
  585. package/ui/js/RailKeys.js +87 -0
  586. package/ui/js/RailMenu.js +133 -0
  587. package/ui/js/Recent.js +135 -0
  588. package/ui/js/RecentMode.js +156 -0
  589. package/ui/js/Reload.js +60 -0
  590. package/ui/js/Renderer.js +9 -0
  591. package/ui/js/RunFile.js +143 -0
  592. package/ui/js/Scripts.js +28 -0
  593. package/ui/js/Scroll.js +304 -0
  594. package/ui/js/ScrollOff.js +69 -0
  595. package/ui/js/Search.js +478 -0
  596. package/ui/js/Selection.js +97 -0
  597. package/ui/js/Settings.js +476 -0
  598. package/ui/js/SettingsAbout.js +97 -0
  599. package/ui/js/SettingsShelf.js +52 -0
  600. package/ui/js/SheetKeys.js +42 -0
  601. package/ui/js/SheetQuery.js +281 -0
  602. package/ui/js/ShelfPile.js +27 -0
  603. package/ui/js/SlowClick.js +53 -0
  604. package/ui/js/SlowOp.js +6 -0
  605. package/ui/js/Sort.js +134 -0
  606. package/ui/js/Startup.js +63 -0
  607. package/ui/js/StateWords.js +17 -0
  608. package/ui/js/Status.js +238 -0
  609. package/ui/js/Swap.js +166 -0
  610. package/ui/js/TabMove.js +39 -0
  611. package/ui/js/Tabs.js +736 -0
  612. package/ui/js/Tags.js +134 -0
  613. package/ui/js/Taildrop.js +128 -0
  614. package/ui/js/Tap.js +174 -0
  615. package/ui/js/TextSize.js +107 -0
  616. package/ui/js/Thumbs.js +158 -0
  617. package/ui/js/Transfer.js +172 -0
  618. package/ui/js/Trash.js +81 -0
  619. package/ui/js/TrashDates.js +47 -0
  620. package/ui/js/TrashDrop.js +64 -0
  621. package/ui/js/UiState.js +438 -0
  622. package/ui/js/Unlock.js +152 -0
  623. package/ui/js/Update.js +130 -0
  624. package/ui/js/UserDirs.js +56 -0
  625. package/ui/qmldir +228 -0
@@ -0,0 +1,605 @@
1
+ import QtQuick
2
+ import "." as Flea
3
+ import "js/DirSizes.js" as DirSizes
4
+ import "js/DragOut.js" as DragOut
5
+ import "js/Errors.js" as Errors
6
+ import "js/Anchor.js" as Anchor
7
+ import "js/Archive.js" as Archive
8
+ import "js/BackReturn.js" as BackReturn
9
+ import "js/Nav.js" as Nav
10
+ import "js/Format.js" as Format
11
+ import "js/Ops.js" as Ops
12
+ import "js/Clipboard.js" as Clipboard
13
+ import "js/Permissions.js" as Permissions
14
+ import "js/Status.js" as Status
15
+ import "js/Search.js" as Search
16
+ import "js/SlowOp.js" as SlowOp
17
+ import "js/Swap.js" as Swap
18
+ import "js/Tabs.js" as Tabs
19
+ import "js/ExtThumbs.js" as ExtThumbs
20
+ import "js/Transfer.js" as Transfer
21
+
22
+ // Every reply from outside the window lands here: the backend's, and those of the three foreign
23
+ // programs the pane runs (the opener, the Dropbox share link, Taildrop). Split out of ui/Pane.qml
24
+ // the way ui/List.qml was; it owns no state of its own and writes only through the pane handed in.
25
+ Item {
26
+ id: root
27
+
28
+ property var pane: null
29
+
30
+ // The listing's floor as a drop target, under the rows: a drop past the last row, or one a file
31
+ // row refused, lands in the directory being shown. Declared first in ui/Pane.qml, so it sits below.
32
+ // Columns owns its narrower active floor; a search listing's base is the walk scope.
33
+ // Recent stands on the root, so its floor takes no drop: a row's own folder still does.
34
+ Flea.DropInto {
35
+ x: root.pane ? root.pane.listSlot.x : 0
36
+ y: root.pane ? root.pane.listSlot.y : 0
37
+ width: root.pane ? root.pane.listSlot.width : 0
38
+ height: root.pane ? root.pane.listSlot.height : 0
39
+ enabled: root.pane !== null && !root.pane.trash.opened && !root.pane.flashActive && root.pane.searchMode === ""
40
+ && root.pane.recentMode === ""
41
+ && (root.pane.viewMode === "list" || root.pane.viewMode === "grid")
42
+ pane: root.pane
43
+ scrolls: true
44
+ dest: root.pane ? root.pane.dropPath : ""
45
+ refuseLoading: DragOut.refuseLoading(root.pane && root.pane.listInFlight, false, false)
46
+ // Unknown until the listed reply lands, because dirDev is still the directory being left.
47
+ destDev: root.pane && root.pane.backend && !root.pane.listInFlight ? root.pane.backend.dirDev : 0
48
+ }
49
+ // The new folder has no row until the refresh lands, so the editor is opened on the rows reply
50
+ // that carries it rather than on the made line that asked for it. Holds that folder's full path.
51
+ property string renameOnArrival: ""
52
+ // A watched change landed while one of the states below owned the rows, so the re-read is owed.
53
+ property bool stale: false
54
+ // What the cursor sat on across a re-read, or null; ui/js/Anchor.js owns both ends of it.
55
+ property var anchor: null
56
+ property int retryId: 0
57
+ property var retryPaths: []
58
+ property string retryFolder: ""
59
+ property string retryListing: ""
60
+ property string retrySelectionText: ""
61
+ // The selection identity the retry line was written for: the line goes when the identity moves off it.
62
+ property string retrySelectionIdentity: ""
63
+ // One burst of writes is one re-read: the timer absorbs later notifications instead of being
64
+ // restarted by them, so a directory under continuous change settles rather than never firing.
65
+ readonly property int watchMs: 400
66
+ // Interactions and unfinished anchors hold the re-read; bare selections carry across by file identity.
67
+ readonly property bool watchBusy: Anchor.busy(pane, root.anchor)
68
+ // ui/Pane.qml reaches the three through these: openCursor takes the opener, the menu reads the
69
+ // Taildrop peers, and the two share actions call the other two.
70
+ readonly property alias opener: opener
71
+ readonly property alias shareLink: shareLink
72
+ readonly property alias taildrop: taildrop
73
+ readonly property alias swap: swap
74
+
75
+ // The listed and rows replies land through the listing swap, see ui/PaneSwap.qml.
76
+ Flea.PaneSwap { id: swap; pane: root.pane; wire: root }
77
+
78
+ Flea.Opener {
79
+ id: opener
80
+ // A dropped request is the app being busy, not a failure, so it takes the plain role.
81
+ onBusy: function (path) { pane.message("Still opening the last file; try again in a moment.", false) }
82
+ // canonicalize proved the path before every failure src/open.rs and src/terminal.rs report under their one status, so neither sentence below names a cause.
83
+ onFailed: function (path) { pane.message("No application on this system opened that file.", true) }
84
+ onIsDirectory: function (path) { pane.open(path) }
85
+ onTerminalBusy: function (path) { pane.message("Still opening the last terminal; try again in a moment.", false) }
86
+ onTerminalFailed: function (path) { pane.message("No terminal on this system opened that folder.", true) }
87
+ // The run card's own answers: a program asks once on its raw ask line, and a file no application claims asks Open with.
88
+ onAskRunRaw: function (path, text) { pane.askRunCard({ path: path, raw: text }) }
89
+ onAskOpenWith: function (path) { pane.showOpenWith(path) }
90
+ }
91
+
92
+ Flea.ShareLink {
93
+ id: shareLink
94
+ onCopied: pane.message("Share link copied to the clipboard.", false)
95
+ onFailed: function(reason) { pane.message(reason, true) }
96
+ }
97
+
98
+ Flea.Taildrop {
99
+ id: taildrop
100
+ }
101
+
102
+ // The owed re-read, run when nothing is holding the rows. A refusal keeps the debt rather than
103
+ // dropping it, and watchBusy going false below is what pays it.
104
+ function reread() {
105
+ if (root.watchBusy)
106
+ return
107
+ root.stale = false
108
+ root.anchor = Anchor.watched(pane, false, Theme.fileRowHeight)
109
+ }
110
+
111
+ // The owed re-read goes through the timer rather than straight out of this handler: reading
112
+ // watchBusy back inside its own change notification re-enters the binding, which Qt reports as a
113
+ // binding loop, and reread() writes listInFlight, which watchBusy reads.
114
+ onWatchBusyChanged: if (root.stale && !watchSettle.running) watchSettle.start()
115
+
116
+ Timer {
117
+ id: watchSettle
118
+ interval: root.watchMs
119
+ repeat: false
120
+ onTriggered: root.reread()
121
+ }
122
+
123
+ // Ok item lines wait here and join the card at the next other line or this beat, so a run of small files writes it once; a failure never waits.
124
+ property var heldItems: []
125
+ readonly property int heldItemBeatMs: 100
126
+ Timer { id: heldItemBeat; interval: root.heldItemBeatMs; onTriggered: root.flushItems() }
127
+ function flushItems() {
128
+ heldItemBeat.stop()
129
+ if (root.heldItems.length === 0) return
130
+ root.pane.transfer = Transfer.itemsDone(root.pane.transfer, root.heldItems)
131
+ root.heldItems = []
132
+ root.pane.sticky(Ops.progressLine(root.pane.transfer))
133
+ }
134
+
135
+ // A debt owed for the directory the pane has left is not owed by the one it arrived in: without
136
+ // this, a change in A held back by a selection is paid by a full re-list of B.
137
+ Connections {
138
+ target: pane
139
+ function onPathChanged() {
140
+ root.stale = false
141
+ root.anchor = null
142
+ watchSettle.stop()
143
+ root.retryId = 0
144
+ root.retryPaths = []
145
+ }
146
+ function onMenuSelectionInputsChanged() {
147
+ if (root.retrySelectionText && root.pane.menuSelectionIdentity() !== root.retrySelectionIdentity) root.retrySelectionText = ""
148
+ }
149
+ function onListInFlightChanged() { if (!pane.listInFlight) root.locateRetry() }
150
+ }
151
+
152
+ function locateRetry() {
153
+ if (!root.retryId || root.retryListing || pane.listInFlight || pane.searchRunning) return
154
+ if (pane.path !== root.retryFolder) { root.retryId = 0; root.retryPaths = []; return }
155
+ root.retryListing = pane.menuSelectionIdentity()
156
+ pane.backend.send({c: "locate", paths: root.retryPaths, transferId: root.retryId})
157
+ }
158
+
159
+ // Only arm an editor after the new folder's actual row arrives in the held window, matched
160
+ // by the name the backend lists so an NFC name on hfsplus finds its NFD row and editor.
161
+ function openRenameOnArrival() {
162
+ if (root.renameOnArrival.length === 0)
163
+ return
164
+ var target = root.renameOnArrival
165
+ root.renameOnArrival = ""
166
+ var at = Anchor.matchListed(pane, target)
167
+ if (at >= 0) {
168
+ pane.setCursor(at)
169
+ pane.act("rename")
170
+ }
171
+ }
172
+
173
+ function refreshRename(request, selected, pointer) {
174
+ if (pane.path !== request.folder) return
175
+ if (pane.listInFlight || pane.searchMode.length > 0) { root.stale = true; return }
176
+ root.stale = false
177
+ watchSettle.stop()
178
+ var anchor = Anchor.pointerRow(pane, request, pane.anchorRowHeight)
179
+ // A cursor a click or key moved off the renamed row while the write was pending is the operator's, so it wins at any scroll.
180
+ var keepsCursor = pointer || anchor.moved
181
+ // The re-list resets the view to its top, so every commit keeps the anchor: it puts the cursor row back at its screen y.
182
+ root.anchor = anchor
183
+ pane.refresh(keepsCursor ? "" : selected)
184
+ if (anchor.start > 0) pane.backend.window(anchor.start, pane.windowSize)
185
+ }
186
+
187
+ Connections {
188
+ target: pane.backend
189
+
190
+ function onListed(total, readMs, sortMs, path, changed, gen) { swap.takeListed(total, readMs, sortMs, path, changed, gen) }
191
+ function onRows(start, items, ms, kinds, listing, gen) { swap.takeRows(start, items, kinds, listing, gen) }
192
+
193
+ function onLocated(message) {
194
+ if (BackReturn.takeLocated(pane, message)) return
195
+ Tabs.locatedCursor(pane, message)
196
+ var taken = Anchor.takeLocated(root.pane, root.anchor, message, Theme.fileRowHeight)
197
+ if (taken.handled) {
198
+ root.anchor = taken.anchor
199
+ return
200
+ }
201
+ if (!root.retryId || message.transferId !== root.retryId) return
202
+ root.retryId = 0
203
+ root.retryPaths = []
204
+ if (message.directory !== pane.path || pane.path !== root.retryFolder
205
+ || root.retryListing !== pane.menuSelectionIdentity() || pane.listInFlight) return
206
+ if (!message.ok) { pane.message(message.error, true); return }
207
+ var matches = message.matches || []
208
+ if (!matches.length) return
209
+ pane.selection.clear()
210
+ for (var i = 0; i < matches.length; i++) pane.selection.toggle(matches[i].index)
211
+ pane.selectionVersion++
212
+ pane.setCursor(matches[0].index)
213
+ root.retrySelectionIdentity = root.pane.menuSelectionIdentity()
214
+ root.retrySelectionText = Ops.retrySelectionLine(matches)
215
+ }
216
+
217
+ // Sample input: {"t":"searched","n":14673,"scanned":284446,"ms":229.008,"cancelled":false,"gen":3,"walking":false}
218
+ // The answered counts land for the newest sent generation with the first window already in place.
219
+ function onSearched(total, scanned, ms, cancelled, gen, walking) {
220
+ Search.searched(pane, total, scanned, ms, cancelled, gen, walking)
221
+ }
222
+
223
+ // Sample input: {"t":"unmounted","path":"/media/stick","parent":"/media"}
224
+ // The open mount went away, so the pane moves up to its nearest existing parent.
225
+ function onUnmounted(path, parent) {
226
+ if (path !== pane.path && !pane.path.startsWith(path + "/"))
227
+ return
228
+ pane.openWithoutHistory(parent)
229
+ pane.message("That drive or share was disconnected, so this folder is no longer available", false)
230
+ }
231
+
232
+ // Sample input: {"t":"changed","path":"/home/gm/Downloads"}
233
+ // Unsolicited, and the only line here that is: the listed directory changed under the pane.
234
+ function onChanged(path) {
235
+ // A notification for a directory the pane has already left says nothing about this one.
236
+ if (path !== pane.path)
237
+ return
238
+ root.retrySelectionText = ""
239
+ root.stale = true
240
+ if (!watchSettle.running)
241
+ watchSettle.start()
242
+ }
243
+
244
+ // A thumbed line for the previous listing is still in the pipe when open() clears the map, so it is dropped.
245
+ // A cache-only miss on a generating class returns to unasked so the viewport asks it again instead of keeping the miss.
246
+ function onThumbed(row, file) {
247
+ if (pane.listInFlight)
248
+ return
249
+ var next = ExtThumbs.thumbReply(pane.thumbState, row, file, pane.thumbCap, pane.storageKnown, pane.storageClass, ViewState.preview)
250
+ pane.thumbState = next.state
251
+ // A lost prefetch is visible work again: the settled view re-plans it in full and never as a prefetch, so it asks once per rest.
252
+ if (next.missed && pane.listArea) pane.listArea.restartSettle()
253
+ }
254
+
255
+ // The Make executable row's own probe, answered off the loop; the pane keeps only its newest id.
256
+ function onShebang(path, hasShebang, id) { pane.noteShebang(path, hasShebang, id) }
257
+
258
+ // A dirsized line for the previous listing is still in the pipe when open() clears the map.
259
+ function onDirSized(row, bytes, partial) {
260
+ if (!pane.listInFlight)
261
+ pane.dirSizeState = DirSizes.remember(pane.dirSizeState, row, bytes, partial, pane.dirSizeCap)
262
+ }
263
+
264
+ // The measuring run ended: nothing still waiting will be answered.
265
+ function onDirSizeDone(cancelled) { pane.dirSizeState = DirSizes.settled(pane.dirSizeState) }
266
+
267
+ // Sample input: {"t":"transferstarted","id":12,"n":2,"moving":true}
268
+ // The verb comes off the wire, never off the clipboard: paste spends a cut before this line
269
+ // arrives, and a Dropbox move never touches the clipboard at all.
270
+ function onTransferStarted(id, n, moving, extract) {
271
+ root.heldItems = []
272
+ root.retryId = 0
273
+ root.retryPaths = []
274
+ root.retrySelectionText = ""
275
+ pane.transfer = Ops.started(id, moving, n, extract)
276
+ pane.sticky(Ops.progressLine(pane.transfer))
277
+ }
278
+
279
+ // Sample input: {"t":"transferprogress","id":12,"index":0,"name":"a.txt","bytes":40000000,"total":120000000,"scanned":8400000000}
280
+ // Sample input: {"t":"transferprogress","id":12,"index":0,"name":"","bytes":0,"total":0,"scanned":0,"phase":"writing","drive":"128GB"}
281
+ function onTransferProgress(id, index, name, bytes, total, scanned, phase, drive) {
282
+ if (id !== pane.transfer.id) {
283
+ return
284
+ }
285
+ root.flushItems()
286
+ // Reassigned rather than mutated in place: an in-place write re-evaluates no binding,
287
+ // so the card would never see a sample. The bytes and the total ride along with it.
288
+ // The writing phase names the drive instead of a file: every file is already complete,
289
+ // so the card holds its counted bytes; see docs/protocol.md "transferprogress".
290
+ if (phase === "writing")
291
+ pane.transfer = Transfer.markWriting(pane.transfer, drive)
292
+ else
293
+ pane.transfer = Transfer.sampled(pane.transfer, index, name, bytes, total, scanned)
294
+ pane.sticky(Ops.progressLine(pane.transfer))
295
+ }
296
+
297
+ // One named failure per transfer owns the status slot until acknowledged; later failures remain in its summary.
298
+ function onTransferItem(id, index, name, ok, err) {
299
+ if (id !== pane.transfer.id) {
300
+ return
301
+ }
302
+ if (ok) { root.heldItems.push({ index: index, name: name }); if (!heldItemBeat.running) heldItemBeat.start(); return }
303
+ root.flushItems()
304
+ var firstFailure = !ok && err !== "cancelled" && !pane.transfer.failureReported
305
+ pane.transfer = Object.assign(Transfer.itemDone(pane.transfer, index, name),
306
+ { failureReported: pane.transfer.failureReported || firstFailure })
307
+ if (firstFailure)
308
+ pane.message(Ops.transferFailure(pane.transfer, name, err), true)
309
+ pane.sticky(Ops.progressLine(pane.transfer))
310
+ }
311
+
312
+ // Sample input: {"t":"transferdone","id":12,"ok":1,"failed":1,"skipped":0,"cancelled":false,"durable":false,"note":""}
313
+ // Sample input: {"t":"transferdone","id":12,"ok":1,"failed":0,"skipped":0,"cancelled":false,"durable":false,"note":"","merged":212,"keptBoth":3,"into":"trip"}
314
+ function onTransferDone(id, ok, failed, skipped, cancelled, retryPaths, durable, note, merged, keptBoth, into) {
315
+ if (id !== pane.transfer.id) {
316
+ return
317
+ }
318
+ root.flushItems()
319
+ // A merge carries into on its own line; every other transfer keeps today's line.
320
+ var line = into && pane.collide ? pane.collide.doneLine(pane.transfer,
321
+ { into: into, merged: merged, keptBoth: keptBoth, ok: ok, failed: failed, skipped: skipped, cancelled: cancelled, durable: durable, note: note })
322
+ : Ops.transferDone(pane.transfer, ok, failed, skipped, cancelled, durable, note)
323
+ var unreportedFailure = failed > 1 || (failed > 0 && !pane.transfer.failureReported)
324
+ pane.transfer = Ops.emptyTransfer()
325
+ pane.sticky("")
326
+ pane.message(line, unreportedFailure)
327
+ if (unreportedFailure) pane.message(line, false)
328
+ root.retryId = retryPaths.length ? id : 0
329
+ root.retryPaths = retryPaths
330
+ root.retryFolder = pane.path
331
+ root.retryListing = ""
332
+ if (pane.searchMode === Search.RESULTS) {
333
+ root.stale = true
334
+ root.locateRetry()
335
+ } else pane.refresh("")
336
+ }
337
+
338
+ // The listing is read again with the cursor left where the deleted rows were, and the row
339
+ // that took their place selected, so the next delete needs no mouse. The whole selection is
340
+ // gone from disk, so there is nothing to carry over but the position.
341
+ function onTrashed(ok, failed, reason) {
342
+ if (ok === 0 && failed === 0) return
343
+ pane.sticky("")
344
+ pane.message(Ops.trashed(ok, failed, reason), ok === 0)
345
+ pane.clearSelection()
346
+ root.anchor = Anchor.afterDelete(pane, ok > 0)
347
+ }
348
+
349
+ // The listing is re-read with the new name selected, so the row the operator was on stays
350
+ // under the cursor; a cursor a click or key moved meanwhile keeps its own row instead.
351
+ function onRenamed(ok, path) {
352
+ var request = pane.renameRequest
353
+ if (!SlowOp.closesRename(request, path)) return
354
+ pane.renameRequest = null
355
+ pane.renamingIndex = -1
356
+ var target = Nav.renameRefreshTarget(pane, path)
357
+ root.refreshRename(request, target, target === "")
358
+ }
359
+
360
+ // A remote write past its deadline: information only, so the request stays open
361
+ // for the late reply, which closes it exactly as an in-time reply would.
362
+ function onSlowOp(op, path, msg) { pane.message(msg, false) }
363
+ // One line for the whole batch, and one undo reverses every rename it made.
364
+ function onBulkRenamed(ok) { pane.bulkRenamed(ok) }
365
+
366
+ // Sample input: {"t":"made","ok":true,"path":"/home/gm/Pictures/New Folder"}
367
+ // The same refresh onRenamed does, which is also what puts the order back to name ascending
368
+ // and drops any filter, so the new row is never sorted or filtered out of sight.
369
+ function onMade(ok, path) {
370
+ root.renameOnArrival = path
371
+ pane.message(Ops.made(path), false)
372
+ pane.refresh(path)
373
+ }
374
+
375
+ function onDuplicated(ok, path) {
376
+ pane.message(Format.fill(Ops.WORDS.duplicated, Ops.leaf(path)) + Status.undoHint(), false)
377
+ pane.refresh(path)
378
+ }
379
+
380
+ // MenuAdditions040: Paste as links answers one line per request, and
381
+ // one journal entry, so one undo removes every link it created.
382
+ function onLinked(ok, failed, skipped, note) {
383
+ // A stranded note is shown as an error, so a leftover link is never silent.
384
+ var stranded = String(note || "").length > 0
385
+ pane.message(Ops.linkedLine(ok, failed, skipped, note || ""), (failed > 0 && ok === 0) || stranded)
386
+ pane.refresh("")
387
+ }
388
+
389
+ // MenuAdditions040: Show original reveals the link's target in its own
390
+ // folder, the same path Show in folder uses.
391
+ function onLinkTarget(path, directory, name, id) {
392
+ // A stale or foreign id is ignored, so a late reply never yanks a navigation.
393
+ if (!pane.linkTargetPendingId || id !== pane.linkTargetPendingId) return
394
+ pane.linkTargetPendingId = 0
395
+ if (directory.length === 0 || (name.length === 0 && directory !== "/")) {
396
+ pane.message("That link points to an item that no longer exists.", true)
397
+ return
398
+ }
399
+ pane.pendingSelect = name.length === 0 ? "" : directory === "/" ? "/" + name : directory + "/" + name
400
+ pane.open(directory)
401
+ }
402
+
403
+ function onUndone(op, ok) {
404
+ pane.sticky("")
405
+ pane.message(Ops.undone(op), false)
406
+ pane.refresh("", op === "permissions" || op === "settags")
407
+ }
408
+
409
+ // MenuAdditions040 callout 10: Make executable reuses permissions batch; only this pane's pending id is answered here.
410
+ function onPermissionsResult(message) {
411
+ var pending = Permissions.MAKE_EXEC_ID + pane.makeExecPendingId
412
+ if (!pane.makeExecPendingId || !message || message.id !== pending || message.op !== "applyMany") return
413
+ pane.makeExecPendingId = 0
414
+ if (message.ok === true) {
415
+ pane.message(Status.withUndo("Made it executable."), false)
416
+ pane.refresh("")
417
+ } else {
418
+ pane.message(message.error && message.error.length > 0 ? message.error : "That file could not be made executable.", true)
419
+ }
420
+ }
421
+
422
+ function onRedoStarted(id, n, op) {
423
+ var next = Ops.started(id, false, n)
424
+ next.redo = op
425
+ pane.transfer = next
426
+ pane.sticky(Ops.progressLine(next))
427
+ }
428
+ function onRedone(op, ok) {
429
+ pane.transfer = Ops.emptyTransfer()
430
+ pane.sticky("")
431
+ pane.message(Ops.redone(op) + Status.undoHint(), false)
432
+ pane.refresh("", op === "permissions" || op === "settags")
433
+ }
434
+
435
+ // An unverified extract says so in the status slot, an encrypted archive opens the extract card, and any other failure messages.
436
+ function onArchiveDone(id, ok, verified, err, path, dest) {
437
+ if (pane.transfer.extract === true && pane.transfer.id === id)
438
+ pane.transfer = Ops.emptyTransfer()
439
+ pane.sticky("")
440
+ var action = Archive.doneAction(ok, err)
441
+ if (action !== "") {
442
+ pane.extractPasswordRequested(path, dest, action === "wrong" ? err : "")
443
+ pane.refresh("")
444
+ return
445
+ }
446
+ pane.message(ok ? Ops.archiveDoneLine(verified) : err === "cancelled" ? "Extraction cancelled." : Errors.sentence("archive", err), !ok && err !== "cancelled")
447
+ pane.refresh("")
448
+ }
449
+
450
+ function onConvertDone(id, ok, path, err, requestId, source, collision) {
451
+ if (requestId && (!pane.convertSource || pane.convertSource.requestId !== requestId || pane.convertSource.path !== source)) return
452
+ pane.sticky("")
453
+ pane.message(ok ? Format.fill(Ops.WORDS.convertedTo, Ops.leaf(path)) : collision ? err : Errors.sentence("convert", err), !ok)
454
+ if (ok) {
455
+ if (pane.searchMode === Search.RESULTS) root.stale = true
456
+ else pane.refresh(path)
457
+ }
458
+ }
459
+
460
+ // The backend statfs's its own base, which only moves when a listing succeeds, and Nav.js moves pane.path before one does: a failed hop's figures are of the directory we never left, while a failed refresh's are still of what is on screen.
461
+ // Recent spans mounts and asks for no figures of its own, so a late answer for its base is refused with the stale ones.
462
+ function onFsInfo(fs, free, path, storageClass, tagable, systemVolume) {
463
+ // The line follows its listing's, but a loading mark makes the rows wait, so pane.path still names the folder left while the listing out is the one this line answers.
464
+ var ours = (path.length === 0 || path === root.pane.path || (root.pane.listInFlight && path === root.pane.listingPath)) && root.pane.recentMode.length === 0
465
+ root.pane.fsName = ours ? fs : ""; root.pane.fsFree = ours ? free : 0
466
+ if (ours || !root.pane.listInFlight) root.pane.fsAnswered = true
467
+ if (ours) {
468
+ pane.storageClass = storageClass || ""
469
+ pane.systemVolume = systemVolume === true
470
+ pane.storageKnown = true
471
+ pane.canTag = tagable === true
472
+ // The verdict follows the directory, so a class switch later compares
473
+ // against this listing's own gate rather than the one navigated from.
474
+ pane.extVerdict = ExtThumbs.verdict(pane.storageClass, ViewState.preview)
475
+ if (pane.listArea) pane.listArea.restartSettle()
476
+ }
477
+ }
478
+
479
+ // A paths reply reaches only the asker its tag names; the anchor's own is consumed above.
480
+ function onPaths(list) {
481
+ if (Anchor.takesPaths(root.pane, root.anchor)) {
482
+ root.anchor = Anchor.fillPaths(root.pane, root.anchor, list)
483
+ return
484
+ }
485
+ Ops.pathsResolved(pane, list)
486
+ }
487
+
488
+ function onClipResult(message) { Clipboard.receive(pane, message) }
489
+
490
+ function onFailed(where, input, message, mode) {
491
+ if (pane.path.length === 0 && input.length > 0) pane.path = input
492
+ var text = Errors.sentence(where, message, input && input !== pane.path ? Ops.leaf(input) : "")
493
+ var terminal = where === "backend" || where === "read"
494
+ // A dead backend ends every listing, so no deferred menu can ever land on one.
495
+ if (terminal) {
496
+ pane.pendingMenu = false
497
+ Nav.clearPendingBackground(pane)
498
+ }
499
+ var request = pane.renameRequest
500
+ var renamePath = request && (input === request.source || input === request.destination
501
+ || (where === "rename" && (input.length === 0 || input.indexOf(request.source + "/") === 0
502
+ || input.indexOf(request.destination + "/") === 0)))
503
+ if (request && (terminal || (renamePath && ["rename", "journal", "rename-kept", "rename-stranded"].indexOf(where) >= 0))) {
504
+ var pointer = pane.renameKeepsPointerRow
505
+ pane.renameRequest = null
506
+ pane.renameKeepsPointerRow = false
507
+ if (terminal) {
508
+ text = "Flea stopped responding, so the rename may not have finished. Check the name."
509
+ } else if (where === "rename-kept" || where === "rename-stranded" || (where === "journal" && input === request.destination)) {
510
+ // A destination-side journal failure happens after the filesystem rename succeeded.
511
+ pane.renamingIndex = -1
512
+ if (where === "journal") text = "Renamed, but undo cannot reverse this rename."
513
+ pane.message(text, true)
514
+ root.refreshRename(request, pointer ? "" : (where === "journal" ? request.destination : ""), pointer)
515
+ return
516
+ } else {
517
+ var reason = Errors.exists(message) ? Format.fill(Ops.WORDS.alreadyExists, Ops.leaf(request.destination)) : Errors.capitalised(message)
518
+ // Grid closing review G1: with no live editor to show it, the
519
+ // refusal goes to the status bar and the edit closes.
520
+ Ops.refuseRename(pane, reason)
521
+ return
522
+ }
523
+ }
524
+ if (where === "redo") { pane.transfer = Ops.emptyTransfer(); pane.sticky("") }
525
+ // A refused sort changes nothing in the backend, so it changes nothing here: a notice in the
526
+ // plain role, never the error role, which is for a listing that stopped being true.
527
+ if (where === "sort") {
528
+ pane.message(text, false)
529
+ return
530
+ }
531
+ // Rows parked for a Back's locate land at the top on every failure that reaches here but a stale one, so that listing still ends.
532
+ var parkedLanded = where !== "stale" && pane.swap.landParked()
533
+ // The rows a request named were another numbering's, so only that request ended, see src/backend/rowguard.rs.
534
+ // A paths failure clears its claim either way. Leaving it set blocks the next copy.
535
+ var listingEnded = (terminal || !parkedLanded) && Swap.failListing(pane, where, input)
536
+ if (input === "paths") {
537
+ var claim = pane.pathsPending
538
+ if (claim && claim.kind === "drag") {
539
+ pane.pathsPending = null
540
+ claim.deliver(null, claim)
541
+ if (!listingEnded) return
542
+ } else if (claim && claim.kind === "anchor") {
543
+ // A failed anchor ask ends the anchor on its clamped index instead of stranding it.
544
+ if (root.anchor && root.anchor.needPaths)
545
+ root.anchor = Anchor.failAnchor(root.pane, root.anchor, Theme.fileRowHeight)
546
+ else
547
+ root.pane.pathsPending = null
548
+ if (!listingEnded) return
549
+ } else if (claim) pane.pathsPending = null
550
+ else Ops.clipFailed(pane)
551
+ }
552
+ if (!listingEnded) {
553
+ // A refused window ends its directory's anchor so the owed re-read can run.
554
+ if (where === "window" && root.anchor && input === root.anchor.path
555
+ && root.anchor.path === root.pane.path)
556
+ root.anchor = Anchor.failAnchor(root.pane, root.anchor, Theme.fileRowHeight)
557
+ pane.message(text, true)
558
+ return
559
+ }
560
+ // The target listing actually ended, so neither deferred menu can land on it; a stale or refused sort never reaches here.
561
+ pane.pendingMenu = false
562
+ Nav.clearPendingBackground(pane)
563
+ // Neither the child nor its stream comes back, so the listing it produced stops being true.
564
+ // Only these two mean the refresh will never deliver rows. An editor left armed past that
565
+ // would open over whatever row the cursor happens to hold in some later listing.
566
+ if (terminal || where === "scan")
567
+ root.renameOnArrival = ""
568
+ if (terminal) {
569
+ pane.renamingIndex = -1
570
+ root.retrySelectionText = ""
571
+ pane.total = 0
572
+ pane.held = 0
573
+ pane.rows = []
574
+ pane.cursorIndex = 0
575
+ // No transferdone is coming from a backend that is gone, and nothing else ends a
576
+ // running transfer, so the card would crawl over a dead child until the app closed.
577
+ pane.transfer = Ops.emptyTransfer()
578
+ pane.sticky("")
579
+ }
580
+ // A failure landing on the waiting state ends the wait the same way, so no
581
+ // stale "not responding" outlives the answer that replaced it.
582
+ if (terminal || where === "scan" || pane.listingState === "loading" || pane.listingState === "waiting") {
583
+ pane.listingState = Errors.listingState(where, message)
584
+ pane.lockedMode = mode; pane.stateMessage = text
585
+ }
586
+ pane.message(text, true) // The rule: the centre lane carries the refusal, both StatusBar lanes
587
+ // The names on disk changed in a way no reply listed (a kept copy, or a twin left under its temp), so re-read the listing and select nothing.
588
+ if (where === "rename-kept" || where === "rename-stranded")
589
+ pane.refresh("")
590
+ }
591
+ }
592
+
593
+ // flea --ui-state is a reply from outside the window too. A refused patch, or a state file it
594
+ // could not write, means the change is on screen and the file does not have it; nothing else
595
+ // would ever say so, because the window's own read is taken once before the first frame.
596
+ Connections {
597
+ target: ViewState
598
+ function onSaveFailed() { pane.message(Errors.sentence("state", ""), true) }
599
+ }
600
+
601
+ // The other half of the same seam: main() leaves a ui.json it cannot read exactly as the operator
602
+ // wrote it, and the window draws the shipped defaults, so this says once that none of it was used.
603
+ Component.onCompleted: if (ViewState.unreadable) pane.message(Errors.sentence("statefile", ""), true)
604
+
605
+ }
@@ -0,0 +1,9 @@
1
+ import QtQuick
2
+
3
+ // The parked Back's listing wait, built on the first park by ui/PaneSwap.qml so a window that never parks starts no Timer.
4
+ Timer {
5
+ required property var swap
6
+ interval: swap.parkedWaitMs
7
+ repeat: false
8
+ onTriggered: swap.landParked()
9
+ }