flea-qml 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (637) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +511 -2
  3. package/THIRD-PARTY-NOTICES.md +29 -0
  4. package/demos/App.java +5 -0
  5. package/demos/Dockerfile +4 -0
  6. package/demos/Main.kt +3 -0
  7. package/demos/Program.cs +1 -0
  8. package/demos/README.md +12 -0
  9. package/demos/app.dart +3 -0
  10. package/demos/app.deb +0 -0
  11. package/demos/app.js +1 -0
  12. package/demos/backup.tar +0 -0
  13. package/demos/budget.xlsx +0 -0
  14. package/demos/build.sh +2 -0
  15. package/demos/bundle.zip +0 -0
  16. package/demos/clip.mp4 +0 -0
  17. package/demos/data.sqlite +0 -0
  18. package/demos/disk.iso +0 -0
  19. package/demos/engine.cpp +5 -0
  20. package/demos/firmware.bin +0 -0
  21. package/demos/flake.nix +4 -0
  22. package/demos/folder/inside.txt +1 -0
  23. package/demos/font.ttf +0 -0
  24. package/demos/index.html +5 -0
  25. package/demos/index.php +2 -0
  26. package/demos/init.lua +1 -0
  27. package/demos/letter.docx +0 -0
  28. package/demos/lib.rs +3 -0
  29. package/demos/main.c +6 -0
  30. package/demos/main.h +3 -0
  31. package/demos/math-and-diagrams.md +200 -0
  32. package/demos/notes.tar.gz +0 -0
  33. package/demos/notes.txt +3 -0
  34. package/demos/photo.png +0 -0
  35. package/demos/program +2 -0
  36. package/demos/report.pdf +32 -0
  37. package/demos/script.py +1 -0
  38. package/demos/server.go +7 -0
  39. package/demos/settings.json +4 -0
  40. package/demos/slides.pptx +0 -0
  41. package/demos/song.mp3 +0 -0
  42. package/demos/style.css +4 -0
  43. package/demos/tool.rb +1 -0
  44. package/demos/types.ts +2 -0
  45. package/docs/pele.md +23 -0
  46. package/docs/protocol.md +3420 -0
  47. package/docs/temml.md +63 -0
  48. package/index.js +107 -0
  49. package/package.json +34 -4
  50. package/src/archive.js +407 -0
  51. package/src/archiveops.js +728 -0
  52. package/src/backend.js +369 -0
  53. package/src/bulkrename.js +95 -0
  54. package/src/clip-host.js +76 -0
  55. package/src/clip.js +462 -0
  56. package/src/code.js +168 -0
  57. package/src/compare.js +74 -0
  58. package/src/create.js +128 -0
  59. package/src/dirsize.js +147 -0
  60. package/src/figure-svg.js +530 -0
  61. package/src/figure-thread.js +23 -0
  62. package/src/figure.js +132 -0
  63. package/src/find.js +55 -0
  64. package/src/flea.js +39 -0
  65. package/src/fsinfo.js +39 -0
  66. package/src/highlight.js +141 -0
  67. package/src/html.js +52 -0
  68. package/src/kinds.js +89 -0
  69. package/src/listing.js +130 -0
  70. package/src/markdown-html.js +317 -0
  71. package/src/mathml.js +186 -0
  72. package/src/menu.js +180 -0
  73. package/src/meta.js +135 -0
  74. package/src/office.js +810 -0
  75. package/src/order.js +100 -0
  76. package/src/peek.js +49 -0
  77. package/src/pele-wrapper.js +695 -0
  78. package/src/permissions.js +180 -0
  79. package/src/places.js +313 -0
  80. package/src/preview-language.js +10 -0
  81. package/src/terminal-server.js +95 -0
  82. package/src/terminal-shell.js +26 -0
  83. package/src/transfer.js +669 -0
  84. package/src/trash-record.js +41 -0
  85. package/src/trash.js +210 -0
  86. package/src/trashbrowse.js +327 -0
  87. package/src/uistate.js +393 -0
  88. package/src/uistore.js +168 -0
  89. package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
  90. package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
  91. package/src/vendor/LICENSES/MIT-katex.txt +21 -0
  92. package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
  93. package/src/vendor/LICENSES/MIT-pele.txt +40 -0
  94. package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
  95. package/src/vendor/LICENSES/MIT-temml.txt +21 -0
  96. package/src/vendor/pele.js +145 -0
  97. package/src/vendor/temml.mjs +14708 -0
  98. package/src/watch.js +98 -0
  99. package/src/wayland/client.js +109 -0
  100. package/src/wayland/protocol.js +55 -0
  101. package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
  102. package/src/wayland/protocols/wayland.xml +3248 -0
  103. package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
  104. package/src/wayland/resource-io.js +6 -0
  105. package/src/wayland/socket-discovery.js +26 -0
  106. package/src/wayland/transport-posix.js +120 -0
  107. package/src/wayland/transport-win32.js +11 -0
  108. package/src/wayland/transport.js +3 -0
  109. package/src/wayland/win32-resources.js +80 -0
  110. package/src/wayland/win32-wire.js +62 -0
  111. package/test/archive.test.js +80 -0
  112. package/test/bench-markdown-scroll.mjs +190 -0
  113. package/test/clip-host.test.js +113 -0
  114. package/test/code-preview.test.js +35 -0
  115. package/test/compare-ui-paths.test.js +24 -0
  116. package/test/compare.test.js +54 -0
  117. package/test/delete-trash.test.js +67 -0
  118. package/test/dirsize.test.js +138 -0
  119. package/test/file-ops.test.js +307 -0
  120. package/test/file-url.test.js +24 -0
  121. package/test/find-contents.test.js +161 -0
  122. package/test/find-input.test.js +66 -0
  123. package/test/fixtures/pele-parity.json +1006 -0
  124. package/test/highlight-launcher.test.js +35 -0
  125. package/test/html-preview.test.js +22 -0
  126. package/test/input.test.js +15 -0
  127. package/test/keymap.test.js +26 -0
  128. package/test/language-icons.test.js +36 -0
  129. package/test/launcher.test.js +51 -0
  130. package/test/manual-archive-here-ui.mjs +47 -0
  131. package/test/manual-code-scroll.mjs +28 -0
  132. package/test/manual-column-scroll.mjs +24 -0
  133. package/test/manual-compare-ui.mjs +20 -0
  134. package/test/manual-find-status.mjs +37 -0
  135. package/test/manual-folder-focus.mjs +63 -0
  136. package/test/manual-html-security.mjs +23 -0
  137. package/test/manual-html-ui.mjs +30 -0
  138. package/test/manual-syntax-preview.mjs +26 -0
  139. package/test/manual-terminal-lifecycle.mjs +42 -0
  140. package/test/manual-terminal-navigation.mjs +48 -0
  141. package/test/manual-terminal-ui.mjs +47 -0
  142. package/test/manual-trash-ui.mjs +86 -0
  143. package/test/markdown-diagrams.test.js +93 -0
  144. package/test/markdown-html.test.js +105 -0
  145. package/test/mathml.test.js +92 -0
  146. package/test/menu-transfer.test.js +57 -0
  147. package/test/office-preview.test.js +154 -0
  148. package/test/pele-parity.test.js +28 -0
  149. package/test/places.test.js +134 -0
  150. package/test/preview-keys.test.js +60 -0
  151. package/test/preview-language.test.js +22 -0
  152. package/test/status-filename.test.js +20 -0
  153. package/test/transfer-replace-merge.test.js +187 -0
  154. package/test/trash-address.test.js +23 -0
  155. package/test/trash-view.test.js +37 -0
  156. package/test/trashbrowse.test.js +135 -0
  157. package/ui/AboutFacts.qml +78 -0
  158. package/ui/ArchiveCards.qml +95 -0
  159. package/ui/ArchiveCompressDialog.qml +378 -0
  160. package/ui/ArchiveHereConfirm.qml +127 -0
  161. package/ui/ArchivePasswordDialog.qml +257 -0
  162. package/ui/Backend.qml +775 -0
  163. package/ui/BulkOldNames.qml +47 -0
  164. package/ui/BulkRenameDialog.qml +380 -0
  165. package/ui/CardFrame.qml +67 -0
  166. package/ui/CardScroll.qml +79 -0
  167. package/ui/CheckBox.qml +73 -0
  168. package/ui/ChromeBar.qml +360 -0
  169. package/ui/ChromeButton.qml +131 -0
  170. package/ui/ChromeModes.qml +43 -0
  171. package/ui/CodeLines.qml +256 -0
  172. package/ui/CodeRefusal.qml +52 -0
  173. package/ui/CollideConfirm.qml +147 -0
  174. package/ui/CollideHost.qml +167 -0
  175. package/ui/ColumnPane.qml +525 -0
  176. package/ui/ColumnRow.qml +380 -0
  177. package/ui/ColumnsArea.qml +594 -0
  178. package/ui/ColumnsLanding.qml +147 -0
  179. package/ui/CompareView.qml +321 -0
  180. package/ui/ContextMenu.qml +743 -0
  181. package/ui/ConvertDialog.qml +456 -0
  182. package/ui/CountedWorker.qml +7 -0
  183. package/ui/Crumb.qml +64 -0
  184. package/ui/CrumbDrop.qml +25 -0
  185. package/ui/CsvTable.qml +394 -0
  186. package/ui/CursorMark.qml +41 -0
  187. package/ui/DefaultClaim.qml +130 -0
  188. package/ui/DeviceLock.qml +47 -0
  189. package/ui/DeviceMounts.qml +540 -0
  190. package/ui/DialogButton.qml +150 -0
  191. package/ui/DialogField.qml +147 -0
  192. package/ui/DialogHeader.qml +31 -0
  193. package/ui/DialogScrim.qml +20 -0
  194. package/ui/DialogTitle.qml +37 -0
  195. package/ui/Divider.qml +9 -0
  196. package/ui/DropInto.qml +126 -0
  197. package/ui/DropTarget.qml +35 -0
  198. package/ui/DropboxMark.qml +60 -0
  199. package/ui/EmptyState.qml +150 -0
  200. package/ui/EscapeHint.qml +11 -0
  201. package/ui/FactsTable.qml +54 -0
  202. package/ui/FastScrollHandler.qml +476 -0
  203. package/ui/FatNamesConfirm.qml +157 -0
  204. package/ui/Favourites.qml +143 -0
  205. package/ui/FigureService.qml +120 -0
  206. package/ui/FileDrag.qml +267 -0
  207. package/ui/FilterStrip.qml +133 -0
  208. package/ui/FitMetrics.qml +22 -0
  209. package/ui/FlashDriveRows.qml +137 -0
  210. package/ui/FlashHost.qml +72 -0
  211. package/ui/FlashImageRow.qml +104 -0
  212. package/ui/FlashRunner.qml +119 -0
  213. package/ui/FlashStepRow.qml +172 -0
  214. package/ui/FlashStrip.qml +38 -0
  215. package/ui/FlashView.qml +397 -0
  216. package/ui/FleaMark.qml +88 -0
  217. package/ui/FlyoutFade.qml +23 -0
  218. package/ui/FontPane.qml +170 -0
  219. package/ui/Glass.qml +114 -0
  220. package/ui/GlassTagger.qml +59 -0
  221. package/ui/Glyph.qml +64 -0
  222. package/ui/GlyphSolid.qml +22 -0
  223. package/ui/GridArea.qml +664 -0
  224. package/ui/GridTile.qml +325 -0
  225. package/ui/GvfsBridge.qml +164 -0
  226. package/ui/Header.qml +433 -0
  227. package/ui/HoverTimers.qml +39 -0
  228. package/ui/HtmlClip.qml +30 -0
  229. package/ui/HtmlPane.qml +63 -0
  230. package/ui/HyprlandMark.qml +45 -0
  231. package/ui/Ipc.qml +1005 -0
  232. package/ui/IpcControls.qml +7 -0
  233. package/ui/IpcMenuState.qml +48 -0
  234. package/ui/IpcPreviewState.qml +185 -0
  235. package/ui/JumpPath.qml +51 -0
  236. package/ui/KeymapSheet.qml +561 -0
  237. package/ui/KeymapSheetResult.qml +89 -0
  238. package/ui/KindStack.qml +40 -0
  239. package/ui/LangMark.qml +51 -0
  240. package/ui/LangMarkLoader.qml +26 -0
  241. package/ui/List.qml +480 -0
  242. package/ui/LoadingState.qml +54 -0
  243. package/ui/LocalSend.qml +56 -0
  244. package/ui/LocalSendMark.qml +73 -0
  245. package/ui/MarkdownBlockView.qml +311 -0
  246. package/ui/MarkdownBlocks.qml +35 -0
  247. package/ui/MarkdownFigure.qml +254 -0
  248. package/ui/MarkdownImages.qml +72 -0
  249. package/ui/MarkdownList.qml +81 -0
  250. package/ui/MarkdownMathsText.qml +97 -0
  251. package/ui/MarkdownPane.qml +83 -0
  252. package/ui/MarkdownPictures.qml +41 -0
  253. package/ui/MarkdownQuote.qml +52 -0
  254. package/ui/MarkdownRemote.qml +82 -0
  255. package/ui/MarkdownSource.qml +155 -0
  256. package/ui/MarkdownTable.qml +222 -0
  257. package/ui/MarkdownTableScroll.qml +64 -0
  258. package/ui/MarkdownTableWheel.qml +126 -0
  259. package/ui/MarkdownText.qml +87 -0
  260. package/ui/MarkdownWorker.js +132 -0
  261. package/ui/MatchText.qml +99 -0
  262. package/ui/MediaSession.qml +38 -0
  263. package/ui/MediaSound.qml +26 -0
  264. package/ui/MediaStrip.qml +191 -0
  265. package/ui/MediaTrack.qml +36 -0
  266. package/ui/MediaVolume.qml +54 -0
  267. package/ui/MenuActionDialog.qml +396 -0
  268. package/ui/MenuEdgeFade.qml +24 -0
  269. package/ui/MenuHost.qml +227 -0
  270. package/ui/MenuRow.qml +351 -0
  271. package/ui/MountListing.qml +100 -0
  272. package/ui/NetworkDialog.qml +435 -0
  273. package/ui/NetworkForm.qml +426 -0
  274. package/ui/NetworkMounts.qml +913 -0
  275. package/ui/NetworkPlaces.qml +127 -0
  276. package/ui/OpenWithDialog.qml +613 -0
  277. package/ui/Opener.qml +95 -0
  278. package/ui/Pane.qml +1320 -0
  279. package/ui/PaneMenuActions.qml +527 -0
  280. package/ui/PanePath.qml +90 -0
  281. package/ui/PaneRail.qml +268 -0
  282. package/ui/PaneStates.qml +88 -0
  283. package/ui/PaneSwap.qml +339 -0
  284. package/ui/PaneWire.qml +601 -0
  285. package/ui/ParkedWait.qml +9 -0
  286. package/ui/PathEntry.qml +186 -0
  287. package/ui/PathJump.qml +400 -0
  288. package/ui/PdfViewer.qml +297 -0
  289. package/ui/PermissionsDialog.qml +658 -0
  290. package/ui/PermissionsHeadings.qml +31 -0
  291. package/ui/PhoneMounts.qml +67 -0
  292. package/ui/PickerAnswers.qml +75 -0
  293. package/ui/PickerBox.qml +26 -0
  294. package/ui/PickerChrome.qml +295 -0
  295. package/ui/PickerFilter.qml +97 -0
  296. package/ui/PickerGrid.qml +308 -0
  297. package/ui/PickerHeader.qml +28 -0
  298. package/ui/PickerLifecycle.qml +27 -0
  299. package/ui/PickerList.qml +218 -0
  300. package/ui/PickerListing.qml +149 -0
  301. package/ui/PickerPathBar.qml +127 -0
  302. package/ui/PickerPlaces.qml +189 -0
  303. package/ui/PickerRecent.qml +92 -0
  304. package/ui/PickerSave.qml +101 -0
  305. package/ui/PickerSelection.qml +155 -0
  306. package/ui/PickerWindow.qml +846 -0
  307. package/ui/PowerSectorsReader.qml +10 -0
  308. package/ui/PrebuildDriver.qml +146 -0
  309. package/ui/Preview.qml +1005 -0
  310. package/ui/PreviewAnimation.qml +24 -0
  311. package/ui/PreviewArchive.qml +91 -0
  312. package/ui/PreviewColumn.qml +553 -0
  313. package/ui/PreviewEdge.qml +63 -0
  314. package/ui/PreviewFacts.qml +30 -0
  315. package/ui/PreviewFactsLine.qml +34 -0
  316. package/ui/PreviewHtml.qml +233 -0
  317. package/ui/PreviewImage.qml +253 -0
  318. package/ui/PreviewImagePan.qml +13 -0
  319. package/ui/PreviewImageSharp.qml +32 -0
  320. package/ui/PreviewLines.qml +106 -0
  321. package/ui/PreviewMarkdown.qml +706 -0
  322. package/ui/PreviewMedia.qml +250 -0
  323. package/ui/PreviewPdf.qml +482 -0
  324. package/ui/PreviewScroll.qml +201 -0
  325. package/ui/PreviewSwap.qml +335 -0
  326. package/ui/PreviewText.qml +149 -0
  327. package/ui/ProtocolChip.qml +18 -0
  328. package/ui/QuickLookArchive.qml +41 -0
  329. package/ui/QuickLookBar.qml +103 -0
  330. package/ui/QuickLookPrepare.qml +355 -0
  331. package/ui/QuickLookSwap.qml +10 -0
  332. package/ui/QuickLookWarm.qml +65 -0
  333. package/ui/RailDrop.qml +155 -0
  334. package/ui/RailHeading.qml +19 -0
  335. package/ui/RailPlaces.qml +38 -0
  336. package/ui/RailTrashRow.qml +67 -0
  337. package/ui/RenameField.qml +353 -0
  338. package/ui/RendererRetry.qml +11 -0
  339. package/ui/ResizeHandle.qml +52 -0
  340. package/ui/Reveal.qml +54 -0
  341. package/ui/Row.qml +476 -0
  342. package/ui/RowDrag.qml +213 -0
  343. package/ui/RowDropTarget.qml +27 -0
  344. package/ui/RunCard.qml +286 -0
  345. package/ui/Scripts.qml +65 -0
  346. package/ui/SearchStrip.qml +232 -0
  347. package/ui/SelectionBand.qml +140 -0
  348. package/ui/SelectionPreview.qml +370 -0
  349. package/ui/SettingsFavourite.qml +122 -0
  350. package/ui/SettingsGroup.qml +96 -0
  351. package/ui/SettingsHint.qml +12 -0
  352. package/ui/SettingsMetrics.qml +29 -0
  353. package/ui/SettingsPane.qml +178 -0
  354. package/ui/SettingsPanel.qml +547 -0
  355. package/ui/SettingsRail.qml +128 -0
  356. package/ui/SettingsRow.qml +409 -0
  357. package/ui/SettingsRuler.qml +85 -0
  358. package/ui/SettingsSegment.qml +85 -0
  359. package/ui/ShareBrowser.qml +113 -0
  360. package/ui/ShareLink.qml +67 -0
  361. package/ui/ShelfPins.qml +101 -0
  362. package/ui/Sidebar.qml +728 -0
  363. package/ui/SidebarRow.qml +358 -0
  364. package/ui/Spinner.qml +60 -0
  365. package/ui/StableModel.qml +89 -0
  366. package/ui/StateMessage.qml +84 -0
  367. package/ui/StatusBar.qml +512 -0
  368. package/ui/StatusFileName.qml +27 -0
  369. package/ui/TabBar.qml +673 -0
  370. package/ui/TabDragGeometry.qml +60 -0
  371. package/ui/TagMenuMark.qml +52 -0
  372. package/ui/TagRailSection.qml +53 -0
  373. package/ui/TagSlot.qml +40 -0
  374. package/ui/TagState.qml +150 -0
  375. package/ui/TagSwatch.qml +28 -0
  376. package/ui/Taildrop.qml +86 -0
  377. package/ui/TailscaleMark.qml +50 -0
  378. package/ui/TerminalService.qml +69 -0
  379. package/ui/TerminalTab.qml +48 -0
  380. package/ui/TerminalTabs.qml +27 -0
  381. package/ui/Theme.qml +460 -0
  382. package/ui/ThemeColors.qml +43 -0
  383. package/ui/TransferCard.qml +239 -0
  384. package/ui/TrashConfirm.qml +129 -0
  385. package/ui/TrashDropHandler.qml +11 -0
  386. package/ui/TrashHost.qml +202 -0
  387. package/ui/TrashMonitor.qml +30 -0
  388. package/ui/TrashToolbar.qml +19 -0
  389. package/ui/TrashView.qml +492 -0
  390. package/ui/UnlockDialog.qml +450 -0
  391. package/ui/UnlockHost.qml +206 -0
  392. package/ui/UpdateCheck.qml +97 -0
  393. package/ui/UserDirs.qml +25 -0
  394. package/ui/ViewState.qml +565 -0
  395. package/ui/ViewportScrollBar.qml +195 -0
  396. package/ui/ViewportScrollBars.qml +25 -0
  397. package/ui/WebPreview.qml +33 -0
  398. package/ui/WebPreviewView.qml +26 -0
  399. package/ui/WindowBody.qml +829 -0
  400. package/ui/WindowDrag.qml +35 -0
  401. package/ui/boot/Commons/AudioNodes.qml +50 -0
  402. package/ui/boot/Commons/AudioNodesModel.js +96 -0
  403. package/ui/boot/Commons/Border.qml +243 -0
  404. package/ui/boot/Commons/BorderGeometry.js +373 -0
  405. package/ui/boot/Commons/Color.qml +258 -0
  406. package/ui/boot/Commons/I18n.qml +118 -0
  407. package/ui/boot/Commons/InputDevices.qml +112 -0
  408. package/ui/boot/Commons/InputMethodState.qml +38 -0
  409. package/ui/boot/Commons/IpcRegistry.qml +77 -0
  410. package/ui/boot/Commons/Numbers.js +19 -0
  411. package/ui/boot/Commons/Plural.js +91 -0
  412. package/ui/boot/Commons/ShellIpc.qml +12 -0
  413. package/ui/boot/Commons/Style.qml +561 -0
  414. package/ui/boot/Commons/Translations.qml +100 -0
  415. package/ui/boot/Commons/UntypedInput.qml +152 -0
  416. package/ui/boot/Commons/Util.qml +188 -0
  417. package/ui/boot/Commons/qmldir +13 -0
  418. package/ui/boot/LICENSE-omarchy +20 -0
  419. package/ui/boot/Ui/BackgroundMedia.qml +49 -0
  420. package/ui/boot/Ui/BarIconButton.qml +106 -0
  421. package/ui/boot/Ui/BarIconContent.qml +38 -0
  422. package/ui/boot/Ui/BarIndicator.qml +53 -0
  423. package/ui/boot/Ui/BarWidget.qml +50 -0
  424. package/ui/boot/Ui/BorderOverlay.qml +54 -0
  425. package/ui/boot/Ui/BorderSurface.qml +40 -0
  426. package/ui/boot/Ui/Button.qml +224 -0
  427. package/ui/boot/Ui/ButtonGroup.qml +131 -0
  428. package/ui/boot/Ui/ConfirmDialog.qml +134 -0
  429. package/ui/boot/Ui/CursorSurface.qml +42 -0
  430. package/ui/boot/Ui/Dropdown.qml +245 -0
  431. package/ui/boot/Ui/FilterInput.qml +26 -0
  432. package/ui/boot/Ui/IconContentBounds.qml +141 -0
  433. package/ui/boot/Ui/KeyboardPanel.qml +453 -0
  434. package/ui/boot/Ui/MultiSelect.qml +624 -0
  435. package/ui/boot/Ui/NumberField.qml +86 -0
  436. package/ui/boot/Ui/OpticalGlyph.qml +68 -0
  437. package/ui/boot/Ui/OverlayWindow.qml +102 -0
  438. package/ui/boot/Ui/Panel.qml +60 -0
  439. package/ui/boot/Ui/PanelActionButton.qml +105 -0
  440. package/ui/boot/Ui/PanelController.qml +16 -0
  441. package/ui/boot/Ui/PanelHero.qml +112 -0
  442. package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
  443. package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
  444. package/ui/boot/Ui/PanelSeparator.qml +19 -0
  445. package/ui/boot/Ui/PanelSlider.qml +156 -0
  446. package/ui/boot/Ui/PanelToolTip.qml +50 -0
  447. package/ui/boot/Ui/PluginBarApi.qml +89 -0
  448. package/ui/boot/Ui/PointerMoveGate.qml +54 -0
  449. package/ui/boot/Ui/PopupCard.qml +181 -0
  450. package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
  451. package/ui/boot/Ui/SearchableDropdown.qml +354 -0
  452. package/ui/boot/Ui/SizedImage.qml +125 -0
  453. package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
  454. package/ui/boot/Ui/TextField.qml +58 -0
  455. package/ui/boot/Ui/Toggle.qml +118 -0
  456. package/ui/boot/Ui/ToggleSwitch.qml +115 -0
  457. package/ui/boot/Ui/WidgetButton.qml +172 -0
  458. package/ui/boot/Ui/qmldir +41 -0
  459. package/ui/boot/fleatab.qml +50 -0
  460. package/ui/boot/picker.qml +39 -0
  461. package/ui/boot/shell.qml +131 -0
  462. package/ui/boot/tabtearoff.qml +51 -0
  463. package/ui/js/Anchor.js +379 -0
  464. package/ui/js/AnchorHold.js +162 -0
  465. package/ui/js/Archive.js +157 -0
  466. package/ui/js/ArchiveCard.js +44 -0
  467. package/ui/js/ArchiveOps.js +44 -0
  468. package/ui/js/BackReturn.js +118 -0
  469. package/ui/js/BulkRename.js +100 -0
  470. package/ui/js/Buttons.js +54 -0
  471. package/ui/js/ChromeKeys.js +116 -0
  472. package/ui/js/ClipMarks.js +73 -0
  473. package/ui/js/ClipSelection.js +67 -0
  474. package/ui/js/Clipboard.js +179 -0
  475. package/ui/js/Cloud.js +97 -0
  476. package/ui/js/CodeRuns.js +72 -0
  477. package/ui/js/Collide.js +212 -0
  478. package/ui/js/ColumnFit.js +28 -0
  479. package/ui/js/ColumnMenu.js +111 -0
  480. package/ui/js/Columns.js +298 -0
  481. package/ui/js/ColumnsCarry.js +103 -0
  482. package/ui/js/Compare.js +74 -0
  483. package/ui/js/Contrast.js +157 -0
  484. package/ui/js/ControlReader.js +42 -0
  485. package/ui/js/Convert.js +52 -0
  486. package/ui/js/CopyAs.js +52 -0
  487. package/ui/js/Crumbs.js +178 -0
  488. package/ui/js/Csv.js +231 -0
  489. package/ui/js/Density.js +44 -0
  490. package/ui/js/Devices.js +440 -0
  491. package/ui/js/DirSizes.js +180 -0
  492. package/ui/js/Drag.js +360 -0
  493. package/ui/js/DragOut.js +166 -0
  494. package/ui/js/DropDev.js +52 -0
  495. package/ui/js/Dropbox.js +41 -0
  496. package/ui/js/Eject.js +217 -0
  497. package/ui/js/Errors.js +188 -0
  498. package/ui/js/ExtThumbs.js +115 -0
  499. package/ui/js/Facts.js +402 -0
  500. package/ui/js/FigureDate.js +14 -0
  501. package/ui/js/Filter.js +285 -0
  502. package/ui/js/Find.js +46 -0
  503. package/ui/js/Flash.js +184 -0
  504. package/ui/js/FlashCard.js +79 -0
  505. package/ui/js/FlashEndings.js +125 -0
  506. package/ui/js/FlashPane.js +116 -0
  507. package/ui/js/FleaBin.js +12 -0
  508. package/ui/js/Focus.js +504 -0
  509. package/ui/js/FolderSorts.js +108 -0
  510. package/ui/js/FolderViews.js +44 -0
  511. package/ui/js/Format.js +314 -0
  512. package/ui/js/Fuzzy.js +141 -0
  513. package/ui/js/GlassTag.js +72 -0
  514. package/ui/js/Grid.js +33 -0
  515. package/ui/js/GridGeometry.js +90 -0
  516. package/ui/js/GridNames.js +153 -0
  517. package/ui/js/GvfsBridge.js +200 -0
  518. package/ui/js/HostClipboard.js +29 -0
  519. package/ui/js/Icons.js +218 -0
  520. package/ui/js/Input.js +50 -0
  521. package/ui/js/Jump.js +200 -0
  522. package/ui/js/KeyName.js +64 -0
  523. package/ui/js/Keymap.js +401 -0
  524. package/ui/js/Kinds.js +164 -0
  525. package/ui/js/LICENSES/ISC-lucide.txt +43 -0
  526. package/ui/js/LangMarkPaths.js +47 -0
  527. package/ui/js/LangMarks.js +120 -0
  528. package/ui/js/Lists.js +11 -0
  529. package/ui/js/LocalSend.js +39 -0
  530. package/ui/js/LockedMenu.js +63 -0
  531. package/ui/js/MakeDefault.js +186 -0
  532. package/ui/js/MarkBox.js +7 -0
  533. package/ui/js/Markdown.js +119 -0
  534. package/ui/js/MarkdownLists.js +86 -0
  535. package/ui/js/MarkdownMaths.js +58 -0
  536. package/ui/js/MarkdownPictures.js +32 -0
  537. package/ui/js/MarkdownPrepared.js +139 -0
  538. package/ui/js/MarkdownTableFit.js +34 -0
  539. package/ui/js/Marks.js +148 -0
  540. package/ui/js/Marquee.js +96 -0
  541. package/ui/js/Match.js +93 -0
  542. package/ui/js/Material.js +109 -0
  543. package/ui/js/MdBlocks.js +437 -0
  544. package/ui/js/MdBreak.js +71 -0
  545. package/ui/js/MdChunks.js +70 -0
  546. package/ui/js/MdContainer.js +137 -0
  547. package/ui/js/MdDocument.js +337 -0
  548. package/ui/js/MdEmph.js +97 -0
  549. package/ui/js/MdEntity.js +108 -0
  550. package/ui/js/MdEntityTable.js +223 -0
  551. package/ui/js/MdEscape.js +59 -0
  552. package/ui/js/MdFront.js +37 -0
  553. package/ui/js/MdHold.js +32 -0
  554. package/ui/js/MdHtml.js +307 -0
  555. package/ui/js/MdHtmlBlock.js +290 -0
  556. package/ui/js/MdHtmlHeading.js +53 -0
  557. package/ui/js/MdHtmlImage.js +179 -0
  558. package/ui/js/MdInline.js +154 -0
  559. package/ui/js/MdItems.js +212 -0
  560. package/ui/js/MdLeaf.js +309 -0
  561. package/ui/js/MdLink.js +196 -0
  562. package/ui/js/MdMath.js +67 -0
  563. package/ui/js/MdParagraphs.js +138 -0
  564. package/ui/js/MdRefs.js +232 -0
  565. package/ui/js/MdResolve.js +226 -0
  566. package/ui/js/MdRun.js +300 -0
  567. package/ui/js/MdUrl.js +226 -0
  568. package/ui/js/Menu.js +514 -0
  569. package/ui/js/MenuContext.js +85 -0
  570. package/ui/js/MenuFit.js +13 -0
  571. package/ui/js/MenuRefresh.js +74 -0
  572. package/ui/js/MenuWheel.js +35 -0
  573. package/ui/js/Messages.js +186 -0
  574. package/ui/js/Motion.js +16 -0
  575. package/ui/js/Mounts.js +320 -0
  576. package/ui/js/MouseNav.js +13 -0
  577. package/ui/js/Nav.js +329 -0
  578. package/ui/js/NetFs.js +26 -0
  579. package/ui/js/OpenWith.js +83 -0
  580. package/ui/js/Ops.js +585 -0
  581. package/ui/js/Palette.js +33 -0
  582. package/ui/js/PathBar.js +260 -0
  583. package/ui/js/Permissions.js +179 -0
  584. package/ui/js/Phones.js +112 -0
  585. package/ui/js/Picker.js +353 -0
  586. package/ui/js/PlaceMenu.js +96 -0
  587. package/ui/js/Places.js +265 -0
  588. package/ui/js/PreviewAsk.js +21 -0
  589. package/ui/js/PreviewKeys.js +155 -0
  590. package/ui/js/PreviewSettle.js +29 -0
  591. package/ui/js/PreviewSwap.js +101 -0
  592. package/ui/js/PropertyFacts.js +144 -0
  593. package/ui/js/Protocols.js +296 -0
  594. package/ui/js/QuickLookKinds.js +27 -0
  595. package/ui/js/QuickLookRect.js +24 -0
  596. package/ui/js/RailDrop.js +51 -0
  597. package/ui/js/RailKeys.js +87 -0
  598. package/ui/js/RailMenu.js +133 -0
  599. package/ui/js/Recent.js +135 -0
  600. package/ui/js/RecentMode.js +156 -0
  601. package/ui/js/Reload.js +60 -0
  602. package/ui/js/Renderer.js +9 -0
  603. package/ui/js/RunFile.js +143 -0
  604. package/ui/js/Scripts.js +28 -0
  605. package/ui/js/Scroll.js +304 -0
  606. package/ui/js/ScrollOff.js +69 -0
  607. package/ui/js/Search.js +478 -0
  608. package/ui/js/Selection.js +97 -0
  609. package/ui/js/Settings.js +476 -0
  610. package/ui/js/SettingsAbout.js +97 -0
  611. package/ui/js/SettingsShelf.js +52 -0
  612. package/ui/js/SheetKeys.js +42 -0
  613. package/ui/js/SheetQuery.js +281 -0
  614. package/ui/js/ShelfPile.js +27 -0
  615. package/ui/js/SlowClick.js +53 -0
  616. package/ui/js/SlowOp.js +6 -0
  617. package/ui/js/Sort.js +134 -0
  618. package/ui/js/Startup.js +63 -0
  619. package/ui/js/StateWords.js +17 -0
  620. package/ui/js/Status.js +238 -0
  621. package/ui/js/Swap.js +166 -0
  622. package/ui/js/TabMove.js +39 -0
  623. package/ui/js/Tabs.js +751 -0
  624. package/ui/js/Tags.js +134 -0
  625. package/ui/js/Taildrop.js +128 -0
  626. package/ui/js/Tap.js +180 -0
  627. package/ui/js/TextSize.js +107 -0
  628. package/ui/js/Thumbs.js +158 -0
  629. package/ui/js/Transfer.js +172 -0
  630. package/ui/js/Trash.js +84 -0
  631. package/ui/js/TrashDates.js +47 -0
  632. package/ui/js/TrashDrop.js +64 -0
  633. package/ui/js/UiState.js +438 -0
  634. package/ui/js/Unlock.js +152 -0
  635. package/ui/js/Update.js +130 -0
  636. package/ui/js/UserDirs.js +56 -0
  637. package/ui/qmldir +230 -0
@@ -0,0 +1,355 @@
1
+ import QtQuick
2
+ import "js/Lists.js" as Lists
3
+ import Quickshell.Io
4
+ import "js/Markdown.js" as Markdown
5
+ import "js/MarkdownMaths.js" as Maths
6
+ import "js/MarkdownPrepared.js" as Prepared
7
+ import "js/Search.js" as Search
8
+
9
+ // A rested cursor on a small local Markdown file prepares Quick Look's entry and holds its small pictures decoded for the first frame.
10
+ Item {
11
+ id: root
12
+
13
+ property var pane: null
14
+ // False while Quick Look is open: the entry is for the next Space.
15
+ property bool resting: true
16
+ // The rest the preview column's own settle waits, so a sweep reads nothing; the pane owns that settle.
17
+ property int restMs: root.pane ? root.pane.settleMs : 120
18
+ // What a suite reads: files read at rest, the bytes the last read returned, parses the worker answered, and the file the entry last took.
19
+ property int reads: 0
20
+ property int readBytes: 0
21
+ property int workerAnswers: 0
22
+ property string preparedPath: ""
23
+ // True once the cursor has rested on a listed row, false from its next move; Quick Look's own build waits on it.
24
+ property bool rested: false
25
+ // A cursor move bumps seq, so a read or a parse that answers after it is dropped.
26
+ property int seq: 0
27
+ // The one request waiting on the worker: its seq, path, text and the inputs the parse took.
28
+ property var asked: null
29
+ // The small local pictures the prepared document names, held decoded until the cursor moves, and whether each has finished loading.
30
+ property var pictures: []
31
+ property bool picturesSettled: true
32
+ // The formulas a rested document draws, typeset ahead so the open takes their drawings from the figure service's memory; empty once the cursor moves.
33
+ property var formulas: []
34
+ // A rested formula holds one decoded picture, so the process's first picture decode (about 20 ms of plugin set-up) is paid at rest.
35
+ property bool warmDecoder: false
36
+ readonly property bool decoderWarm: decoder.status === Image.Ready
37
+ // How many times a rest turned the warm on, which a suite reads to prove a held key never does.
38
+ property int decoderWarms: 0
39
+ onWarmDecoderChanged: if (root.warmDecoder) root.decoderWarms++
40
+ // A rested table builds one unseen table once, so the process's first table types, bold and code faces and rich import are paid at rest.
41
+ property bool tableWarmed: false
42
+ // How many warm tables a rest built and measured, which a suite reads to prove it runs once, never under a held key or after Space.
43
+ property int tableWarms: 0
44
+ // The warm table's Markdown and the width it lays out in: a bold cell, a code span and a link, so each face and the link markup are first used here.
45
+ readonly property string tableWarmText: "| A | B | C |\n|:--|:-:|--:|\n| **x** | `y` | [l](https://e.t) |\n"
46
+ readonly property int tableWarmWidth: 400
47
+ // The one stat child sizing them (null when none), and a suite's counts of those started and alive.
48
+ property var sizer: null
49
+ property int sizersStarted: 0
50
+ property int sizersAlive: 0
51
+
52
+ Timer {
53
+ id: rest
54
+ interval: root.restMs
55
+ onTriggered: root.prepare()
56
+ }
57
+
58
+ Connections {
59
+ target: root.pane
60
+ function onCursorIndexChanged() { root.moved() }
61
+ function onRowsChanged() { root.moved() }
62
+ function onListInFlightChanged() { root.moved() }
63
+ function onStorageKnownChanged() { root.moved() }
64
+ }
65
+
66
+ function moved() {
67
+ root.rested = false
68
+ root.seq++
69
+ root.releaseSizer()
70
+ // The move back waits on the new rest below, never on the entry from before it.
71
+ root.preparedPath = ""
72
+ if (root.pictures.length > 0)
73
+ root.pictures = []
74
+ root.picturesSettled = true
75
+ root.warmDecoder = false
76
+ if (root.formulas.length > 0)
77
+ root.formulas = []
78
+ rest.restart()
79
+ }
80
+
81
+ // head caps the bytes actually read, whatever the file grew to since its row was listed.
82
+ Component {
83
+ id: readerComponent
84
+ Process {
85
+ id: proc
86
+ property int seq: 0
87
+ property string path: ""
88
+ command: ["head", "-c", String(Prepared.MAX_BYTES + 1), "--", proc.path]
89
+ stdout: StdioCollector {
90
+ onStreamFinished: {
91
+ root.landed(proc.seq, proc.path, this.text, this.data.byteLength)
92
+ proc.destroy()
93
+ }
94
+ }
95
+ }
96
+ }
97
+
98
+ // stat sizes the pictures in one child, so none past PICTURE_MAX_BYTES is decoded ahead; the deadline drops a child a hung mount holds.
99
+ Timer {
100
+ id: sizerDeadline
101
+ interval: Prepared.PICTURE_SIZE_DEADLINE_MS
102
+ onTriggered: {
103
+ root.releaseSizer()
104
+ root.picturesSettled = true
105
+ }
106
+ }
107
+
108
+ Component {
109
+ id: sizerComponent
110
+ Process {
111
+ id: sizer
112
+ property int seq: 0
113
+ property var urls: []
114
+ command: ["stat", "-L", "--printf", "%s\\t%n\\n", "--"].concat(sizer.urls.map(Prepared.pathOfUrl))
115
+ Component.onCompleted: root.sizersAlive++
116
+ Component.onDestruction: root.sizersAlive--
117
+ stdout: StdioCollector {
118
+ onStreamFinished: {
119
+ // The child is let go first: a recount settles nothing while it is out.
120
+ var seq = sizer.seq
121
+ var urls = sizer.urls
122
+ var text = this.text
123
+ if (root.sizer === sizer)
124
+ root.releaseSizer()
125
+ root.sized(seq, urls, text)
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ // One held Image per picture, built as a block builds its own: the pixmap cache key holds url, transform and fill, so Stretch never hits.
132
+ Repeater {
133
+ id: held
134
+ model: root.pictures
135
+ delegate: Image {
136
+ required property string modelData
137
+ visible: false
138
+ fillMode: Image.PreserveAspectFit
139
+ asynchronous: true
140
+ autoTransform: true
141
+ source: modelData
142
+ onStatusChanged: root.recount()
143
+ }
144
+ }
145
+
146
+ // One unseen figure per formula, built as the document builds its own, so the service holds the drawing under the key the open asks with.
147
+ Repeater {
148
+ id: typeset
149
+ model: root.formulas
150
+ delegate: MarkdownFigure {
151
+ required property var modelData
152
+ visible: false
153
+ kind: "math"
154
+ source: modelData.source
155
+ display: modelData.display
156
+ inline: true
157
+ bare: true
158
+ bgHex: Prepared.hexOf(Theme.color.background)
159
+ fgHex: Prepared.hexOf(Theme.color.foreground)
160
+ accentHex: Prepared.hexOf(Theme.color.accent)
161
+ mutedHex: Prepared.hexOf(Theme.color.muted)
162
+ surfaceHex: Prepared.hexOf(Theme.color.surface)
163
+ fontFamily: Theme.font.family
164
+ bodyPx: Theme.font.body
165
+ onSvgChanged: root.recount()
166
+ onErrorChanged: root.recount()
167
+ }
168
+ }
169
+
170
+ Image {
171
+ id: decoder
172
+ visible: false
173
+ asynchronous: true
174
+ source: root.warmDecoder ? Maths.CLEAR : ""
175
+ onStatusChanged: root.recount()
176
+ }
177
+
178
+ // MarkdownTable's preview at Quick Look's body size, holding the warm table: no card holds a Markdown pane at rest.
179
+ Component {
180
+ id: tableHost
181
+ Item {
182
+ id: host
183
+ visible: false
184
+ property var block: null
185
+ property real availableWidth: 0
186
+ readonly property alias table: tableLoader.item
187
+ readonly property int bodyPx: Theme.font.body
188
+ readonly property int blockGap: 0
189
+ readonly property real ruleOpacity: 0
190
+ // Loaded by file name and given its block before it completes, so the table builds once and only when a warm runs.
191
+ Loader {
192
+ id: tableLoader
193
+ Component.onCompleted: setSource("MarkdownTable.qml", { visible: false, preview: host, availableWidth: host.availableWidth, block: host.block })
194
+ }
195
+ }
196
+ }
197
+
198
+ Loader {
199
+ id: parser
200
+ active: false
201
+ sourceComponent: CountedWorker {
202
+ source: "MarkdownWorker.js"
203
+ onMessage: function (messageObject) { root.answered(messageObject) }
204
+ }
205
+ }
206
+
207
+ function prepare() {
208
+ var pane = root.pane
209
+ if (!root.resting || !pane || pane.listInFlight)
210
+ return
211
+ root.rested = true
212
+ var row = pane.rowFor(pane.cursorIndex)
213
+ if (!Prepared.readsInline(row, pane.storageClass, pane.storageKnown))
214
+ return
215
+ root.reads++
216
+ var request = readerComponent.createObject(root, { seq: root.seq, path: pane.join(Search.baseOf(pane), row.n) })
217
+ request.running = true
218
+ }
219
+
220
+ // The read landed: a stale or oversized answer is dropped, a held one is kept, and anything else goes to the worker.
221
+ function landed(seq, path, text, bytes) {
222
+ root.readBytes = bytes
223
+ if (seq !== root.seq || bytes > Prepared.MAX_BYTES || text.length === 0)
224
+ return
225
+ var dir = Markdown.dirOf(path)
226
+ var chrome = Prepared.hexOf(Theme.color.background)
227
+ var ink = Prepared.hexOf(Theme.color.foreground)
228
+ var entry = Prepared.take(path, text, dir, chrome, ink)
229
+ if (entry !== null) {
230
+ root.startPictures(entry, dir)
231
+ root.preparedPath = path
232
+ return
233
+ }
234
+ root.asked = { seq: seq, path: path, text: text, dir: dir, chrome: chrome, ink: ink }
235
+ parser.active = true
236
+ parser.item.sendMessage({ seq: seq, source: text, dir: dir, chrome: chrome, ink: ink })
237
+ }
238
+
239
+ // The worker answered: the entry is stored only for the request still waiting and a cursor that has not moved.
240
+ function answered(reply) {
241
+ var a = root.asked
242
+ if (a === null || a.seq !== reply.seq)
243
+ return
244
+ root.asked = null
245
+ Qt.callLater(root.retire)
246
+ // A parse that throws is Quick Look's to report on Space, so nothing is kept here.
247
+ if (reply.seq !== root.seq || reply.error !== "")
248
+ return
249
+ if (a.warm === true) {
250
+ root.buildWarmTable(reply.blocks[0])
251
+ return
252
+ }
253
+ Prepared.store(a.path, a.text, a.dir, a.chrome, a.ink, reply.blocks)
254
+ root.workerAnswers++
255
+ root.startPictures(reply.blocks, a.dir)
256
+ root.preparedPath = a.path
257
+ }
258
+
259
+ // The first rested document holding a table, a quote's or a list item's included, sends the warm table's Markdown to the worker.
260
+ function warmTable(blocks, dir) {
261
+ if (root.tableWarmed || !root.resting || root.asked !== null || !root.holdsTable(blocks))
262
+ return
263
+ // A warm never replaces a request still out; one the cursor overtakes is dropped with its seq, so the next rested table asks again.
264
+ parser.active = true
265
+ root.asked = { seq: root.seq, warm: true }
266
+ parser.item.sendMessage({ seq: root.seq, source: root.tableWarmText, dir: dir, chrome: Prepared.hexOf(Theme.color.background), ink: Prepared.hexOf(Theme.color.foreground) })
267
+ }
268
+
269
+ // The warm table's blocks came back at rest: build the table unseen and drop it at once.
270
+ function buildWarmTable(block) {
271
+ if (!root.resting || !block)
272
+ return
273
+ root.tableWarmed = true
274
+ var host = tableHost.createObject(root, { block: block, availableWidth: root.tableWarmWidth })
275
+ // Reading the measured width lays its cells out now; only a table that built and measured counts.
276
+ if (host.table !== null && host.table.tableWidth > 0)
277
+ root.tableWarms++
278
+ host.destroy()
279
+ }
280
+
281
+ function holdsTable(list) {
282
+ for (var i = 0; i < list.length; i++) {
283
+ var b = list[i]
284
+ // A list's parts hold one array of blocks per item.
285
+ if (b && (b.type === "table" || (Lists.isList(b) && root.holdsTable(b)) || (b.parts !== undefined && root.holdsTable(b.parts))))
286
+ return true
287
+ }
288
+ return false
289
+ }
290
+
291
+ function releaseSizer() {
292
+ sizerDeadline.stop()
293
+ if (root.sizer !== null)
294
+ root.sizer.destroy()
295
+ root.sizer = null
296
+ }
297
+
298
+ function startPictures(blocks, dir) {
299
+ root.releaseSizer()
300
+ root.formulas = Prepared.formulasIn(blocks, Prepared.FORMULA_LIMIT)
301
+ root.warmDecoder = root.formulas.length > 0
302
+ root.warmTable(blocks, dir)
303
+ var urls = Prepared.pictureUrls(blocks, Prepared.PICTURE_LIMIT, dir)
304
+ if (urls.length === 0) {
305
+ root.recount()
306
+ return
307
+ }
308
+ root.picturesSettled = false
309
+ root.sizersStarted++
310
+ root.sizer = sizerComponent.createObject(root, { seq: root.seq, urls: urls })
311
+ root.sizer.running = true
312
+ sizerDeadline.restart()
313
+ }
314
+
315
+ // The sizes landed: only a cursor that has not moved holds the pictures that fit.
316
+ function sized(seq, urls, statText) {
317
+ if (seq !== root.seq)
318
+ return
319
+ root.pictures = Prepared.smallPictures(urls, statText)
320
+ root.recount()
321
+ }
322
+
323
+ // Settled once no held picture is still loading, a failed one included, and the decoder's picture and every typeset formula with them.
324
+ function recount() {
325
+ if (root.sizer !== null) {
326
+ root.picturesSettled = false
327
+ return
328
+ }
329
+ for (var f = 0; f < typeset.count; f++) {
330
+ var figure = typeset.itemAt(f)
331
+ if (figure !== null && figure.svg === "" && figure.error === "") {
332
+ root.picturesSettled = false
333
+ return
334
+ }
335
+ }
336
+ if (decoder.status === Image.Loading) {
337
+ root.picturesSettled = false
338
+ return
339
+ }
340
+ for (var i = 0; i < held.count; i++) {
341
+ var one = held.itemAt(i)
342
+ if (one !== null && one.status === Image.Loading) {
343
+ root.picturesSettled = false
344
+ return
345
+ }
346
+ }
347
+ root.picturesSettled = true
348
+ }
349
+
350
+ // The worker thread lives only while a parse waits.
351
+ function retire() {
352
+ if (root.asked === null)
353
+ parser.active = false
354
+ }
355
+ }
@@ -0,0 +1,10 @@
1
+ import QtQuick
2
+ import "." as Flea
3
+
4
+ // Quick Look wrapper, built on first open; it captures ui/Preview.qml's eager panes container.
5
+ Flea.PreviewSwap {
6
+ // Fills its Loader, or it measures zero and every hold answers at once.
7
+ anchors.fill: parent
8
+ property Item panesSource: null
9
+ captureSource: panesSource
10
+ }
@@ -0,0 +1,65 @@
1
+ import QtQuick
2
+ import "." as Flea
3
+ import "js/QuickLookKinds.js" as LookKinds
4
+
5
+ // What Quick Look's first Space needs before it opens: the rested file's prepared entry and held pictures, the compiled units, and the card itself built closed.
6
+ Item {
7
+ id: root
8
+
9
+ // WindowBody builds this on the cursor's first landing on a file: a Markdown file at once, any other once a key has moved the cursor.
10
+ property var pane: null
11
+ // False while Quick Look is open: the entry is for the next Space.
12
+ readonly property bool resting: !(root.look !== null && root.look.active)
13
+ readonly property alias prepare: prepare
14
+ // Quick Look's own unit and the swap wrapper, held from the first idle after the window settles on a file Quick Look opens, and never instantiated, so the first Space compiles and loads no unit.
15
+ property var previewUnit: null
16
+ property var swapUnit: null
17
+ // The unit the rested file's kind opens its content from, "" for a folder or a kind with none (ui/js/QuickLookKinds.js).
18
+ readonly property string kindUnit: LookKinds.unitOf(root.pane ? root.pane.cursorRow : null)
19
+ onKindUnitChanged: if (unitTimer.running) unitTimer.restart()
20
+ // The kind units the cursor has rested on, held by file name as the two above are, so a kind the window never rested on (PdfViewer, PreviewMedia) is never compiled.
21
+ property var kindUnits: ({})
22
+ readonly property var markdownUnit: root.kindUnits[LookKinds.MARKDOWN] || null
23
+ readonly property int unitWarmMs: 1000
24
+ // The unit the rested file's kind opens from, once held.
25
+ readonly property var restUnit: root.kindUnit !== "" ? (root.kindUnits[root.kindUnit] || null) : null
26
+ readonly property bool unitsReady: root.previewUnit !== null && root.previewUnit.status === Component.Ready
27
+ && root.restUnit !== null && root.restUnit.status === Component.Ready
28
+ && root.swapUnit !== null && root.swapUnit.status === Component.Ready
29
+ // The cursor has rested on a file whose kind opens from a unit, every unit compiled: the card and its swap wrapper are built now, hidden and inactive, so the first Space only opens them.
30
+ readonly property bool cardDue: root.unitsReady && prepare.rested && root.pane !== null
31
+ onCardDueChanged: if (root.cardDue && root.pane.previewLoader) {
32
+ root.pane.previewLoader.active = true
33
+ if (root.pane.previewLoader.item) root.pane.previewLoader.item.ensureSwap()
34
+ }
35
+ readonly property bool windowSettled: root.pane !== null && root.pane.listingState === "ready" && !root.pane.listInFlight
36
+
37
+ // Counts from the last move onto a file with a unit, so a cursor passing over a kind holds none of it.
38
+ Timer {
39
+ id: unitTimer
40
+ running: root.windowSettled && root.previewUnit === null && root.kindUnit !== ""
41
+ interval: root.unitWarmMs
42
+ onTriggered: {
43
+ root.previewUnit = Qt.createComponent("Preview.qml", Component.Asynchronous)
44
+ root.swapUnit = Qt.createComponent("QuickLookSwap.qml", Component.Asynchronous)
45
+ root.holdKind()
46
+ }
47
+ }
48
+ // The cursor's file kind unit, held once and kept; the key that lands on a file never compiles it.
49
+ function holdKind() {
50
+ var file = root.kindUnit
51
+ if (file === "" || root.kindUnits[file] !== undefined)
52
+ return
53
+ var held = Object.assign({}, root.kindUnits)
54
+ held[file] = Qt.createComponent(file, Component.Asynchronous)
55
+ root.kindUnits = held
56
+ }
57
+ // Quick Look's own unit is held and the cursor has rested on a file whose kind has a unit: the first landing on a new kind holds its unit. A move clears rested, so a held key compiles none.
58
+ readonly property bool kindDue: root.previewUnit !== null && prepare.rested && root.kindUnit !== ""
59
+ onKindDueChanged: if (root.kindDue) root.holdKind()
60
+ Flea.QuickLookPrepare { id: prepare; pane: root.pane; resting: root.resting }
61
+ // The card Quick Look opens; resting reads it so a rest never prepares over an open card.
62
+ readonly property var look: root.pane ? root.pane.preview : null
63
+ // The cursor is already on its file when this is built, so the first rest starts here and not on a move.
64
+ Component.onCompleted: prepare.moved()
65
+ }
@@ -0,0 +1,155 @@
1
+ import QtQuick
2
+ import "js/Drag.js" as DragOps
3
+ import "js/DragOut.js" as DragOut
4
+ import "js/RailDrop.js" as RailDrop
5
+ import "js/Tabs.js" as Tabs
6
+
7
+ // One receiver under the rail's rows; Trash keeps its own receiver above it.
8
+ DropArea {
9
+ id: root
10
+
11
+ required property var sidebar
12
+ property Item viewport: root.sidebar
13
+ readonly property var pane: root.sidebar.navigationPane
14
+ property var entered: null
15
+ property int rowIndex: -1
16
+ property var targetRow: null
17
+ property var held: null
18
+ property point pointer: Qt.point(0, 0)
19
+ property point cuePoint: Qt.point(0, 0)
20
+ anchors.fill: parent
21
+ keys: [DragOps.ROWS_MIME, DragOps.SHELF_MIME, "text/uri-list", "text/plain"]
22
+
23
+ function session() {
24
+ if (feedback.item) return feedback.item
25
+ feedback.setSource(Qt.resolvedUrl("FileDrag.qml"), { pane: Qt.binding(function () { return root.pane }) })
26
+ feedback.active = true
27
+ return feedback.item
28
+ }
29
+
30
+ // Sample input: a drag offers a marker, a shelf token, text/plain and file:///d/a.txt.
31
+ function read(drag) {
32
+ var urls = []
33
+ for (var i = 0; i < drag.urls.length; i++) urls.push(String(drag.urls[i]))
34
+ return { marker: drag.getDataAsString(DragOps.ROWS_MIME), urls: urls,
35
+ shelf: drag.getDataAsString(DragOps.SHELF_MIME), plain: drag.getDataAsString("text/plain"),
36
+ proposed: drag.proposedAction }
37
+ }
38
+
39
+ function clearTarget() {
40
+ if (root.targetRow) root.targetRow.trailingLabel = null
41
+ root.targetRow = null
42
+ root.held = null
43
+ root.rowIndex = -1
44
+ if (feedback.item) feedback.item.leaveTarget()
45
+ }
46
+
47
+ function aim(x, y) {
48
+ root.pointer = Qt.point(x, y)
49
+ if (!root.entered) return
50
+ var index = RailDrop.rowAt(root.sidebar, x, y)
51
+ var entry = index >= 0 ? root.sidebar.entries[index] : null
52
+ var data = root.entered
53
+ var path = root.pane && !root.pane.listInFlight
54
+ ? RailDrop.destination(entry, data.marker, data.urls, data.shelf, data.plain) : ""
55
+ var row = index >= 0 ? root.sidebar.railItemFor(index) : null
56
+ if (index === root.rowIndex && row === root.targetRow && root.held && root.held.path === path) {
57
+ root.cuePoint = row.mapToItem(root.viewport, 0, 0)
58
+ root.sayTarget()
59
+ return
60
+ }
61
+ root.clearTarget()
62
+ if (!path) return
63
+ root.rowIndex = index
64
+ root.targetRow = row
65
+ root.cuePoint = row.mapToItem(root.viewport, 0, 0)
66
+ root.held = RailDrop.pending(path)
67
+ root.sayTarget()
68
+ root.pane.backend.send({ c: "devs", paths: [path], id: root.held.id })
69
+ }
70
+
71
+ function sayTarget() {
72
+ if (!root.held || !feedback.item) return
73
+ feedback.item.showTarget(root.sidebar.entries[root.rowIndex].label, root.held.dev)
74
+ if (root.targetRow && cue.item) root.targetRow.trailingLabel = cue.item.label
75
+ }
76
+
77
+ function leave() {
78
+ root.clearTarget()
79
+ root.entered = null
80
+ }
81
+
82
+ function reaim() { if (root.entered) root.aim(root.pointer.x, root.pointer.y) }
83
+
84
+ onPaneChanged: root.leave()
85
+ Component.onDestruction: root.clearTarget()
86
+ Connections {
87
+ target: root.sidebar
88
+ function onEntriesChanged() {
89
+ root.clearTarget()
90
+ // The aggregate changes before its repeaters finish replacing rows.
91
+ Qt.callLater(root.reaim)
92
+ }
93
+ }
94
+ Connections {
95
+ target: root.pane ? root.pane.backend : null
96
+ function onMetaResult(message) {
97
+ if (message.t !== "devs" || !root.entered) return
98
+ root.held = RailDrop.answer(root.held, message.id, message.devs)
99
+ root.sayTarget()
100
+ }
101
+ }
102
+
103
+ Loader {
104
+ id: feedback
105
+ active: false
106
+ onStatusChanged: if (status === Loader.Error) throw new Error("FileDrag.qml did not load: Loader status " + status)
107
+ }
108
+ Loader {
109
+ id: cue
110
+ active: root.held !== null
111
+ parent: root.viewport
112
+ x: root.cuePoint.x
113
+ y: root.cuePoint.y
114
+ width: root.targetRow ? root.targetRow.width : 0
115
+ height: root.targetRow ? root.targetRow.height : 0
116
+ z: 1
117
+ onActiveChanged: {
118
+ if (!cue.active) { cue.source = ""; return }
119
+ cue.setSource(Qt.resolvedUrl("DropTarget.qml"), {
120
+ text: Qt.binding(function () { return DragOps.label(feedback.item ? feedback.item.dragCopy : true, feedback.item ? feedback.item.dragLink : false) })
121
+ })
122
+ }
123
+ onLoaded: root.sayTarget()
124
+ onStatusChanged: if (status === Loader.Error) throw new Error("DropTarget.qml did not load: Loader status " + status)
125
+ }
126
+
127
+ function enterAt(drag) {
128
+ if (!root.pane || !root.pane.backend || drag.getDataAsString(Tabs.TAB_MIME) !== "") { drag.accepted = false; return }
129
+ root.entered = root.read(drag)
130
+ DragOut.keys.enter(root.entered.marker, drag.getDataAsString(DragOut.keys.liftMime))
131
+ var session = root.session()
132
+ if (!session) { root.leave(); drag.accepted = false; return }
133
+ session.enterTarget(root.entered.marker, root.entered.urls, "", DragOps.markerDev(root.entered.marker), root.entered.shelf, drag.proposedAction)
134
+ root.aim(drag.x, drag.y)
135
+ }
136
+ function dropAt(drop) {
137
+ var ctrl = DragOut.keys.ctrl, shift = DragOut.keys.shift
138
+ DragOut.keys.clear()
139
+ root.aim(drop.x, drop.y)
140
+ var data = root.read(drop)
141
+ var entry = root.rowIndex >= 0 ? root.sidebar.entries[root.rowIndex] : null
142
+ if (RailDrop.drop(root.pane, entry, root.held, data.marker, data.urls, data.shelf, data.plain, drop.proposedAction, ctrl, shift)) {
143
+ drop.accept(Qt.CopyAction)
144
+ // The rail's key table ignores undo, so an accepted drop gives the receiving listing the keyboard.
145
+ root.pane.focusView = "list"
146
+ root.pane.focusRequested()
147
+ root.pane.listArea.forceActiveFocus()
148
+ }
149
+ root.leave()
150
+ }
151
+ onEntered: function (drag) { root.enterAt(drag) }
152
+ onPositionChanged: function (drag) { root.aim(drag.x, drag.y) }
153
+ onExited: { DragOut.keys.leave(); root.leave() }
154
+ onDropped: function (drop) { root.dropAt(drop) }
155
+ }
@@ -0,0 +1,19 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+
4
+ // One rail heading: the caption text with the rail's lead and tracking.
5
+ Text {
6
+ id: root
7
+ property real topExtra: 0
8
+ property bool noBottom: false
9
+ readonly property real headingLead: 0.15
10
+ readonly property real headingTracking: 1
11
+ x: Style.spacing.rowPaddingX
12
+ topPadding: root.topExtra + Math.ceil(font.pixelSize * root.headingLead)
13
+ bottomPadding: root.noBottom ? 0 : Style.spacing.rowGap
14
+ color: Theme.color.muted
15
+ font.family: Theme.font.family
16
+ font.pixelSize: Theme.font.caption
17
+ font.letterSpacing: root.headingTracking
18
+ textFormat: Text.PlainText
19
+ }
@@ -0,0 +1,38 @@
1
+ pragma Singleton
2
+ import QtQuick
3
+ import Quickshell
4
+ import "js/Icons.js" as Icons
5
+ import "js/Places.js" as Places
6
+
7
+ // Place data outlives the visible rail, so hiding it cannot remove query destinations.
8
+ QtObject {
9
+ id: root
10
+ readonly property var settings: ViewState.state.places || ({})
11
+ // flea-qml: the folders and the drives the backend found by looking (src/places.js), null
12
+ // until its first `places` line. Upstream read user-dirs.dirs here and drew what it named.
13
+ property var probed: null
14
+ property var probedVolumes: null
15
+ property string probedText: ""
16
+ // An answer that says the same again changes nothing, so no rail rebuilds its rows for it.
17
+ function found(places, volumes) {
18
+ var text = JSON.stringify([places, volumes])
19
+ if (text === root.probedText) return
20
+ root.probedText = text
21
+ root.probed = places
22
+ root.probedVolumes = volumes
23
+ }
24
+ readonly property var homeEntries: root.settings.showHome === false ? []
25
+ : Places.homeEntries(Quickshell.env("HOME"), root.probed, Icons.sidebarGlyphFor)
26
+ readonly property var favouriteEntries: Places.storedEntries(Favourites.records, Quickshell.env("HOME")).map(function (entry) {
27
+ entry.error = entry.error || Favourites.statuses[entry.favouriteIndex] || ""
28
+ return entry
29
+ })
30
+ readonly property var recentEntries: root.settings.showRecent === true
31
+ ? [{ label: "Recent", path: "flea:recent", group: "recent", kind: "recent", glyph: "history" }] : []
32
+ readonly property var trashEntries: root.settings.showTrash === false ? []
33
+ : [{ label: "Trash", path: "trash:///", group: "trash", kind: "trash", glyph: "trash" }]
34
+ function entries() {
35
+ return root.homeEntries.slice(0, 1).concat(root.recentEntries,
36
+ root.homeEntries.slice(1), root.trashEntries, root.favouriteEntries)
37
+ }
38
+ }