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,512 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+ import "." as Flea
4
+ import "js/Format.js" as Format
5
+ import "js/Filter.js" as Filter
6
+ import "js/Focus.js" as Focus
7
+ import "js/Ops.js" as Ops
8
+ import "js/Status.js" as Status
9
+ import "js/Trash.js" as Trash
10
+
11
+ Item {
12
+ id: root
13
+
14
+ property string path: ""
15
+ property int total: 0
16
+ // The flasher's own count line while it owns the pane, set by the window from the host.
17
+ property string flashCount: ""
18
+ property string listingState: "loading"
19
+ // The pane whose listing this strip is counting, or null while the trash view owns the pane.
20
+ property var pane: null
21
+ // Separate from the legacy counts owner: Trash also supplies its shared pane.
22
+ property var filePane: root.pane
23
+ readonly property string selectedName: root.filePane && root.filePane.selectionVersion >= 0
24
+ ? Status.fileName(root.filePane) : ""
25
+ // Cursor-only focus has no selection total; show its already-known file size
26
+ // here without starting directory-size scans or changing count semantics.
27
+ readonly property string fileLabel: (root.selectionCount === 0 && root.filePane
28
+ && root.filePane.cursorRow && !root.filePane.cursorRow.d
29
+ && typeof root.filePane.cursorRow.s === "number" && root.filePane.cursorRow.s >= 0
30
+ ? Format.size(root.filePane.cursorRow.s) + " · " : "") + root.selectedName
31
+ property var fileNameItem: null
32
+ readonly property bool showFileName: root.selectedName.length > 0 && root.listingState === "ready"
33
+ && root.flashCount.length === 0 && !root.busy && root.centreText().length === 0
34
+ && root.restText.length === 0 && !root.undoSplit
35
+ readonly property int shownTotal: root.pane ? root.pane.shownTotal : root.total
36
+ // selectionVersion is read here so a selection mutated in place still re-runs this binding.
37
+ readonly property real selectionBytes: root.pane && root.pane.selectionVersion >= 0
38
+ ? Status.selectionBytes(root.pane) : -1
39
+ property int selectionCount: 0
40
+ property string fsName: ""
41
+ property real fsFree: 0
42
+ // True while the pane's fs facts for its folder are still out, so the slot draws nothing yet.
43
+ property bool fsPending: false
44
+ property string notice: ""
45
+ // Each notice carries a serial, so a withdrawal names the notice it owns.
46
+ property int noticeSerial: 0
47
+ // [{text, detail, place}]: place is the path a no-Trash refusal was raised in, "" for every other error.
48
+ property var errors: []
49
+ // An arm's prompt and its record, kept apart from the notice so the arm's own life, not the text, ranks it.
50
+ property string prompt: ""
51
+ property var arm: null
52
+ // The arm's owner: the listing pane here, the Trash view while ui/WindowBody.qml has that view open.
53
+ property var armOwner: root.pane
54
+ readonly property bool armLive: Status.armLive(root.arm, root.armOwner)
55
+ // The owner zeroing or replacing its own stamp ends the prompt: the second press, any other key, a new listing.
56
+ Connections {
57
+ target: root.arm !== null ? root.arm.owner : null
58
+ function onTrashArmedAtChanged() { if (root.arm !== null && root.arm.owner.trashArmedAt !== root.arm.stamp) root.endArm() }
59
+ }
60
+ onArmOwnerChanged: if (root.arm !== null && root.arm.owner !== root.armOwner) root.loseArm()
61
+ readonly property var shown: Status.transientOf(root.errors, root.notice, root.prompt, root.armLive)
62
+ readonly property string transient_: root.shown.text
63
+ readonly property string errorDetail: root.shown.detail
64
+ // Directive 48, final form: no centre lane at all. The transient sits beside the disk facts, one
65
+ // padding before the text those facts actually draw, which is not the left edge of their fixed
66
+ // zone box: a short filesystem line would otherwise leave the pair drifting apart by the slack.
67
+ readonly property real diskTextWidth: Math.min(disk.implicitWidth, disk.width)
68
+ // From the count's right edge, one padding on, to one padding before that text. A transient elides
69
+ // inside this rather than growing into the facts, which is rule 2: they keep their zone and never move.
70
+ readonly property real transientRoom: Math.max(0, strip.width - 2 * Theme.spacing.rowPaddingX - root.diskTextWidth
71
+ - (counts.x + counts.width + Theme.spacing.rowPaddingX))
72
+ readonly property var stripItem: background
73
+ readonly property var transferCard: cardLoader.item
74
+ readonly property var countsItem: counts
75
+ readonly property var primaryItem: primary
76
+ readonly property var secondaryItem: secondary
77
+ readonly property var undoItem: undoLink
78
+ readonly property var diskItem: disk
79
+ readonly property var centreItem: centre
80
+ readonly property bool transientIsError: root.shown.isError
81
+ property var activities: []
82
+ // The bridge board's busy mark walks while a Starting line stands, and only then.
83
+ property bool busy: false
84
+ property var dragFeedbackOwner: null
85
+ readonly property var activity: root.activities.length ? root.activities[0] : null
86
+ // StatusBar rule 8: the card owns a transfer's progress and it is up whenever one runs, so the
87
+ // strip draws nothing for it at all. A drag's own feedback is not a transfer and still reports.
88
+ readonly property string sticky: root.activity && !root.activity.transfer.running ? root.activity.text : ""
89
+ readonly property var transfer: root.activity ? root.activity.transfer : Ops.emptyTransfer()
90
+ readonly property var transferOwner: root.activity ? root.activity.owner : null
91
+ readonly property bool stickyHere: root.sticky.length > 0
92
+ property string searchLine: ""
93
+ property string retryLine: ""
94
+ property bool searchRunning: false
95
+ // Completed Find results are a listing: keep their summary in the counts zone,
96
+ // leaving the filename lane available just like an ordinary folder.
97
+ readonly property bool searching: root.searchRunning && root.searchLine.length > 0
98
+ readonly property int messageMs: 4000
99
+ readonly property real ruleOpacity: 0.12
100
+ // The hint a result carries: the primary drops it and the secondary draws it, so no sentence on
101
+ // this strip ends in advice. ui/js/Status.js owns the two of them.
102
+ readonly property string noticeHint: root.stickyHere || root.searching
103
+ ? "" : Status.hintOf(root.transient_)
104
+ readonly property bool hasUndo: Status.hasUndoHint(root.noticeHint)
105
+ // Durability callout 6: "z undoes" takes a click, the same as z, on every line that carries
106
+ // it. The undo segment draws as its own target while the rest draws as today.
107
+ readonly property bool undoSplit: root.hasUndo
108
+ readonly property string keyHintRest: root.undoSplit ? Status.withoutUndoKey(root.keyHint) : root.keyHint
109
+ // Round two, StatusBar rule 4: a refusal is drawn alone. When the strip's error is the pane's own
110
+ // state sentence, the block under it is already saying so and the key is not information.
111
+ readonly property string keyHint: root.transientIsError
112
+ ? [root.pane && root.errors[0].text === root.pane.stateMessage ? "" : "esc dismisses",
113
+ root.noticeHint.length > 0 ? Status.hintKey(root.noticeHint) : ""]
114
+ .filter(function (s) { return s.length > 0 }).join(" · ")
115
+ : root.noticeHint.length > 0 ? Status.hintKey(root.noticeHint) : ""
116
+ readonly property string secondaryText: Status.secondaryText(root.keyHint, root.transientIsError,
117
+ root.stickyHere, root.sticky, root.activities, root.searching, root.searchLine, root.retryLine)
118
+ readonly property string restText: Status.secondaryText(root.keyHintRest, root.transientIsError,
119
+ root.stickyHere, root.sticky, root.activities, root.searching, root.searchLine, root.retryLine)
120
+ // Three zones that never trade places: the board fixes the outer two at a third of the strip
121
+ // each, so the centre stays put however long the count or the disk line gets.
122
+ readonly property real zoneSpan: Math.max(0, root.width - 2 * Theme.spacing.rowPaddingX)
123
+ readonly property real zoneWidth: Math.round(root.zoneSpan / 3)
124
+ readonly property real hintWidth: hintMetrics.advanceWidth // Advance keeps the hint's edge space; bounding width drops it, 114 against 115.
125
+ signal transferCancelRequested(int id)
126
+ implicitHeight: Theme.chromeHeight + detailView.height
127
+
128
+ // Completion messages cannot acknowledge a failure; each error requires its own dismissal.
129
+ function say(text, isError, detail) {
130
+ if (!text) { root.dismiss(); return }
131
+ if (isError) {
132
+ root.errors = Status.withError(root.errors, text, detail, root.path)
133
+ return
134
+ }
135
+ // The serial moves with the notice, so a later withdrawal names this one.
136
+ root.notice = text
137
+ root.noticeSerial += 1
138
+ root.syncNoticeTimer()
139
+ }
140
+
141
+ // An arm's prompt arrives on its own channel, so the bar starts the arm from the call and not from the sentence.
142
+ function sayArm(text) {
143
+ if (!text) { root.dismiss(); return }
144
+ root.startArm(text)
145
+ }
146
+
147
+ // A surface replacing its own standing verdict names the one it is replacing. say("") dismisses
148
+ // the head of the queue, which is somebody else's error whenever more than one is waiting.
149
+ function forget(text) {
150
+ if (!text) return
151
+ root.errors = root.errors.filter(function (entry) { return entry.text !== text })
152
+ }
153
+
154
+ // Dismisses the head error when one is drawn, else the notice; a live prompt belongs to its arm.
155
+ function dismiss() {
156
+ if (root.transientIsError) root.errors = root.errors.slice(1)
157
+ else root.notice = ""
158
+ }
159
+ // A stale serial names a past notice, so only the still-standing one is cleared.
160
+ function withdraw(serial) {
161
+ if (serial === root.noticeSerial) root.notice = ""
162
+ }
163
+ // A refusal and an arm belong to the place they were raised in, so leaving that place drops both.
164
+ onPathChanged: {
165
+ var kept = Status.errorsAt(root.errors, root.path)
166
+ if (kept !== root.errors) root.errors = kept
167
+ if (root.arm !== null) root.loseArm()
168
+ }
169
+
170
+ // The prompt supersedes the notice it covers. One said before its owner stamped could never be ended by the arm, so it is only a notice, and said loudly.
171
+ function startArm(text) {
172
+ var stamp = root.armOwner ? root.armOwner.trashArmedAt : 0
173
+ if (!(stamp > 0)) {
174
+ console.warn("StatusBar: \"" + text + "\" was said before its owner armed, so it is only a notice")
175
+ root.notice = text
176
+ root.syncNoticeTimer()
177
+ return
178
+ }
179
+ root.notice = ""
180
+ root.prompt = text
181
+ root.arm = Status.armOf(root.armOwner, stamp)
182
+ armClock.interval = Math.max(1, Status.armLeft(root.arm, Date.now(), Trash.ARM_MS))
183
+ armClock.restart()
184
+ root.syncNoticeTimer()
185
+ }
186
+ function endArm() {
187
+ armClock.stop()
188
+ root.arm = null
189
+ root.prompt = ""
190
+ root.syncNoticeTimer()
191
+ }
192
+ // The bar ending an arm (its owner lost, its place left, its clock run out) ends it at the owner too, so no key completes a hidden arm.
193
+ function loseArm() {
194
+ var arm = root.arm
195
+ root.endArm()
196
+ if (arm !== null && arm.owner && arm.owner.trashArmedAt === arm.stamp) arm.owner.trashArmedAt = 0
197
+ }
198
+ Timer {
199
+ id: armClock
200
+ onTriggered: {
201
+ var left = Status.armLeft(root.arm, Date.now(), Trash.ARM_MS)
202
+ if (left > 0) { armClock.interval = left; armClock.restart() } else root.loseArm()
203
+ }
204
+ }
205
+
206
+ function cancelTransfer() {
207
+ var next = Status.cancelActivity(root.activities)
208
+ if (next === root.activities) return
209
+ root.activities = next
210
+ root.transferCancelRequested(root.transfer.id)
211
+ }
212
+
213
+ // The click refuses through the gate it shares with the z key.
214
+ function clickUndo() {
215
+ if (!Focus.canUndo(root.pane, root.pane ? root.pane.sidebar : null)) return
216
+ Ops.undo(root.pane)
217
+ }
218
+
219
+ function escapePressed() {
220
+ if (root.transientIsError) { root.dismiss(); return true }
221
+ // A final flush cannot be cancelled (every file is complete), and a flash stops only by its own Cancel.
222
+ var transfer = root.transfer
223
+ if (transfer.running && transfer.writing !== true && transfer.flash !== true) { root.cancelTransfer(); return true }
224
+ return false
225
+ }
226
+
227
+ function setActivity(owner, text, transfer, starting) {
228
+ root.activities = Status.activityChanged(root.activities, owner, transfer.running ? Ops.progressLine(transfer) : text, transfer, starting === true)
229
+ root.busy = Status.displayedStarting(root.activities)
230
+ }
231
+
232
+ // A completion hidden by an error or live activity keeps its full display time after acknowledgement.
233
+ function syncNoticeTimer() {
234
+ if (root.notice && Status.noticeShown(root.slot()) && (Status.undoHint().length === 0 || root.notice.indexOf(Status.undoHint()) < 0))
235
+ clear.restart()
236
+ else clear.stop()
237
+ }
238
+ onTransientIsErrorChanged: root.syncNoticeTimer()
239
+ onStickyHereChanged: root.syncNoticeTimer()
240
+ onSearchingChanged: root.syncNoticeTimer()
241
+
242
+ function itemText() {
243
+ if (root.listingState === "empty") return "empty"
244
+ if (root.listingState === "error" || root.listingState === "locked") return "unavailable"
245
+ if (root.listingState !== "ready") return ""
246
+ return Format.count(root.total) + (root.total === 1 ? " item" : " items")
247
+ }
248
+
249
+ // The left zone answers the question the view raises: the selection if there is one, what the
250
+ // filter left standing if there is one, and otherwise the directory. StatusBar board rule 3.
251
+ function countText() {
252
+ if (root.listingState !== "ready") {
253
+ return root.itemText()
254
+ }
255
+ // The flasher's own count, which names drives rather than items and never a selection.
256
+ if (root.flashCount.length > 0) {
257
+ return root.flashCount
258
+ }
259
+ if (root.selectionCount > 0) {
260
+ var head = Format.count(root.selectionCount) + " of " + Format.count(root.total) + " selected"
261
+ return root.selectionBytes >= 0 ? head + " · " + Format.size(root.selectionBytes) : head
262
+ }
263
+ // SearchFilter rule 2: the same sentence the strip carries, scope and all, because the count
264
+ // is of the rows the filter could see and those are a window on the directory, not all of it.
265
+ // The trash view and the picker both draw this strip with no pane behind it, so the filter's
266
+ // sentence is asked for only where there is a listing to have filtered.
267
+ if (root.pane && root.shownTotal !== root.total) {
268
+ return Filter.summary(root.pane.shown, root.pane.rows.length, root.total)
269
+ }
270
+ if (!root.searchRunning && root.searchLine.length > 0) return root.searchLine
271
+ return root.itemText()
272
+ }
273
+
274
+ // The one fact a result or an error may not evict: unknown once answered with nothing, never the folder failed to leave, and empty while the answer is out.
275
+ function fsText() {
276
+ return root.fsName.length ? root.fsName + " · " + Format.size(root.fsFree) + " free" : root.fsPending ? "" : "unknown"
277
+ }
278
+
279
+ function slot() {
280
+ return { transient: root.transient_, transientIsError: root.transientIsError, armLive: root.armLive,
281
+ searching: root.searching, searchLine: root.searchLine,
282
+ stickyHere: root.stickyHere, sticky: root.sticky }
283
+ }
284
+
285
+ function centreText() {
286
+ var text = Status.centreText(root.slot())
287
+ return root.noticeHint.length > 0 ? text.replace(root.noticeHint, "") : text
288
+ }
289
+ // Centre ink sits on the surface, so error takes the surface lift and any other role its own.
290
+ function centreColor() {
291
+ var role = Status.centreRole(root.slot())
292
+ if (role === "error")
293
+ return Theme.color.errorOnSurface
294
+ return Theme.color[role] !== undefined ? Theme.color[role] : Theme.color.foreground
295
+ }
296
+
297
+ Timer { id: clear; interval: root.messageMs; onTriggered: root.notice = "" }
298
+
299
+ Item { id: strip; width: parent.width; height: Theme.chromeHeight }
300
+
301
+ Rectangle {
302
+ id: background
303
+ width: parent.width
304
+ height: Theme.chromeHeight
305
+ color: Glass.surface
306
+ border.width: 0
307
+ }
308
+
309
+ Rectangle {
310
+ width: parent.width
311
+ height: Theme.spacing.hairline
312
+ color: Theme.color.foreground
313
+ opacity: root.ruleOpacity
314
+ }
315
+
316
+ // Left: what is in front of you.
317
+ Text {
318
+ id: counts
319
+ anchors.left: parent.left
320
+ anchors.leftMargin: Theme.spacing.rowPaddingX
321
+ anchors.verticalCenter: strip.verticalCenter
322
+ width: root.showFileName ? Math.min(implicitWidth, root.zoneWidth) : root.zoneWidth
323
+ text: root.countText()
324
+ color: Theme.color.foreground
325
+ font.family: Theme.font.family
326
+ font.pixelSize: Theme.font.caption
327
+ elide: Text.ElideRight
328
+ textFormat: Text.PlainText
329
+ }
330
+
331
+ // Like TagSlot, build this optional surface only on first use. Parent ownership
332
+ // destroys it with the status bar; ordinary cursor moves reuse the same instance.
333
+ function syncFileName() {
334
+ if (root.fileNameItem !== null || !root.showFileName) return
335
+ root.fileNameItem = Qt.createComponent("StatusFileName.qml").createObject(root, {
336
+ name: Qt.binding(function () { return root.fileLabel }),
337
+ visible: Qt.binding(function () { return root.showFileName }),
338
+ x: Qt.binding(function () { return counts.x + counts.width + Theme.spacing.gap }),
339
+ width: Qt.binding(function () {
340
+ return Math.max(0, strip.width - Theme.spacing.rowPaddingX - root.diskTextWidth
341
+ - Theme.spacing.gap - (counts.x + counts.width + Theme.spacing.gap))
342
+ }),
343
+ height: Qt.binding(function () { return strip.height })
344
+ })
345
+ }
346
+ onShowFileNameChanged: root.syncFileName()
347
+ Component.onCompleted: root.syncFileName()
348
+
349
+ // Right: the disk, which no result and no error may take the space of.
350
+ Text {
351
+ id: disk
352
+ anchors.right: parent.right
353
+ anchors.rightMargin: Theme.spacing.rowPaddingX
354
+ anchors.verticalCenter: strip.verticalCenter
355
+ width: root.zoneWidth
356
+ horizontalAlignment: Text.AlignRight
357
+ text: root.fsText()
358
+ color: Theme.color.foreground
359
+ font.family: Theme.font.family
360
+ font.pixelSize: Theme.font.caption
361
+ elide: Text.ElideRight
362
+ textFormat: Text.PlainText
363
+ }
364
+
365
+ // Right, before the disk facts: what just happened, ending one padding short of their own text.
366
+ Row {
367
+ id: centre
368
+ anchors.right: parent.right
369
+ anchors.rightMargin: 2 * Theme.spacing.rowPaddingX + root.diskTextWidth
370
+ anchors.verticalCenter: strip.verticalCenter
371
+ // Rule 2: the disk keeps its zone whatever the transient says, so the pair share this and elide
372
+ // inside it rather than growing into the facts beside them.
373
+ readonly property real room: root.transientRoom
374
+ readonly property real busyRoom: root.busy ? busyLoader.width + centre.spacing : 0
375
+ spacing: root.busy ? Theme.spacing.gap : 0
376
+
377
+ // The bridge board's busy mark, built only while a Starting line stands.
378
+ Loader {
379
+ id: busyLoader
380
+ active: root.busy
381
+ visible: root.busy
382
+ anchors.verticalCenter: parent.verticalCenter
383
+ width: root.busy ? Theme.chromeMarkSize : 0
384
+ height: Theme.chromeMarkSize
385
+ sourceComponent: Flea.Spinner {
386
+ width: Theme.chromeMarkSize
387
+ height: Theme.chromeMarkSize
388
+ color: Theme.color.mutedFrame
389
+ }
390
+ }
391
+
392
+ Text {
393
+ id: primary
394
+ anchors.verticalCenter: parent.verticalCenter
395
+ text: root.centreText()
396
+ color: root.centreColor()
397
+ width: Math.min(implicitWidth, Math.max(0, centre.room - secondary.width - undoDot.width - undoLink.width - centre.busyRoom))
398
+ font.family: Theme.font.family
399
+ font.pixelSize: Theme.font.caption
400
+ elide: Text.ElideMiddle
401
+ textFormat: Text.PlainText
402
+ }
403
+
404
+ Text {
405
+ id: secondary
406
+ anchors.verticalCenter: parent.verticalCenter
407
+ text: root.restText
408
+ color: Theme.color.muted
409
+ width: Math.min(implicitWidth, Math.max(0, centre.room - undoDot.width - undoLink.width - Math.min(primary.implicitWidth,
410
+ Math.max(0, centre.room - root.hintWidth))))
411
+ font.family: Theme.font.family
412
+ font.pixelSize: Theme.font.caption
413
+ elide: Text.ElideRight
414
+ textFormat: Text.PlainText
415
+ }
416
+
417
+ // The undo target: muted at rest like the hint it was, foreground under the pointer while
418
+ // its middot stays muted. Empty unless split, so no hidden text is held.
419
+ Text {
420
+ id: undoDot
421
+ anchors.verticalCenter: parent.verticalCenter
422
+ visible: root.undoSplit
423
+ width: visible ? implicitWidth : 0
424
+ text: root.undoSplit ? " · " : ""
425
+ color: Theme.color.muted
426
+ font.family: Theme.font.family
427
+ font.pixelSize: Theme.font.caption
428
+ textFormat: Text.PlainText
429
+ }
430
+
431
+ Text {
432
+ id: undoLink
433
+ anchors.verticalCenter: parent.verticalCenter
434
+ visible: root.undoSplit
435
+ width: visible ? implicitWidth : 0
436
+ text: root.undoSplit ? Status.hintKey(Status.undoHint()) : ""
437
+ color: undoHover.hovered ? Theme.color.foreground : Theme.color.muted
438
+ font.family: Theme.font.family
439
+ font.pixelSize: Theme.font.caption
440
+ textFormat: Text.PlainText
441
+ Accessible.role: Accessible.Link
442
+ Accessible.name: Status.hintKey(Status.undoHint())
443
+ Accessible.onPressAction: root.clickUndo()
444
+ HoverHandler { id: undoHover; cursorShape: Qt.PointingHandCursor }
445
+ TapHandler {
446
+ acceptedButtons: Qt.LeftButton
447
+ gesturePolicy: TapHandler.ReleaseWithinBounds
448
+ onTapped: root.clickUndo()
449
+ }
450
+ }
451
+ }
452
+
453
+ TextMetrics {
454
+ id: hintMetrics
455
+ font: secondary.font
456
+ text: root.keyHint.length ? " · " + root.keyHint
457
+ + (root.secondaryText !== " · " + root.keyHint ? " · …" : "") : ""
458
+ }
459
+
460
+ Rectangle {
461
+ x: detailView.x; y: detailView.y
462
+ width: detailView.width; height: detailView.height
463
+ visible: detailView.visible
464
+ color: Glass.surface
465
+ border.width: 0
466
+ }
467
+ Flickable {
468
+ id: detailView
469
+ y: Theme.chromeHeight
470
+ width: parent.width
471
+ visible: root.errorDetail.length > 0
472
+ height: visible ? Math.min(contentHeight, root.parent ? root.parent.height / 3 : contentHeight) : 0
473
+ contentWidth: width
474
+ contentHeight: detailText.implicitHeight + 2 * Theme.spacing.rowPaddingY
475
+ clip: true
476
+ boundsBehavior: Flickable.StopAtBounds
477
+ onVisibleChanged: contentY = 0
478
+ Flea.FastScrollHandler {
479
+ parent: detailView
480
+ flickable: detailView
481
+ }
482
+ // No bar and no lane: the detail fills the strip and still scrolls by wheel and touchpad.
483
+ Text {
484
+ id: detailText
485
+ x: Theme.spacing.rowPaddingX
486
+ y: Theme.spacing.rowPaddingY
487
+ width: parent.width - 2 * Theme.spacing.rowPaddingX
488
+ text: root.errorDetail
489
+ color: Theme.color.errorOnSurface
490
+ font.family: Theme.font.family
491
+ font.pixelSize: Theme.font.caption
492
+ wrapMode: Text.Wrap
493
+ textFormat: Text.PlainText
494
+ }
495
+ }
496
+
497
+ Loader {
498
+ id: cardLoader
499
+ active: root.transfer.running
500
+ anchors.right: parent.right
501
+ anchors.rightMargin: Theme.spacing.rowPaddingX
502
+ anchors.bottom: parent.top
503
+ anchors.bottomMargin: Theme.spacing.gap
504
+ sourceComponent: TransferCard {
505
+ width: Math.min(implicitWidth, Math.max(0, root.width - 2 * Theme.spacing.rowPaddingX))
506
+ transfer: root.transfer
507
+ owner: root.transferOwner
508
+ cancelling: root.activity ? root.activity.cancelling : false
509
+ onCancelRequested: root.cancelTransfer()
510
+ }
511
+ }
512
+ }
@@ -0,0 +1,27 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+ import "." as Flea
4
+
5
+ // No elision: the spare status-strip width shows the name, horizontal scrolling
6
+ // exposes the rest. Share the existing wheel/touch scrolling implementation.
7
+ Flickable {
8
+ id: root
9
+ property string name: ""
10
+ contentWidth: Math.max(width, label.implicitWidth)
11
+ contentHeight: height
12
+ clip: true
13
+ flickableDirection: Flickable.HorizontalFlick
14
+ boundsBehavior: Flickable.StopAtBounds
15
+ onNameChanged: contentX = 0
16
+ onWidthChanged: contentX = Math.max(0, Math.min(contentX, contentWidth - width))
17
+ Flea.FastScrollHandler { flickable: root }
18
+ Text {
19
+ id: label
20
+ anchors.verticalCenter: parent.verticalCenter
21
+ text: root.name
22
+ color: Theme.color.foreground
23
+ font.family: Theme.font.family
24
+ font.pixelSize: Theme.font.caption
25
+ textFormat: Text.PlainText
26
+ }
27
+ }