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,305 @@
1
+ .pragma library
2
+
3
+ // SI, because a file's size on disk has no power-of-two basis; GLib's own rule and the whole GUI group.
4
+ var BYTES_PER_UNIT = 1000
5
+ var UNITS = ["B", "kB", "MB", "GB", "TB"]
6
+ // GNOME renders a narrow no-break space before the unit, and Flea's neighbours are GLib-formatted.
7
+ var UNIT_SPACE = " "
8
+
9
+ // Below one kilobyte a fraction is noise, so bytes print whole.
10
+ // Counts reach six figures on a real directory, so they are grouped the way the canvas draws them.
11
+ function count(n) {
12
+ var digits = String(n)
13
+ var out = ""
14
+ for (var i = 0; i < digits.length; i++) {
15
+ if (i > 0 && (digits.length - i) % 3 === 0)
16
+ out += ","
17
+ out += digits.charAt(i)
18
+ }
19
+ return out
20
+ }
21
+
22
+ function size(bytes) {
23
+ if (bytes < BYTES_PER_UNIT) {
24
+ return bytes + UNIT_SPACE + UNITS[0]
25
+ }
26
+ var value = bytes
27
+ var unit = 0
28
+ while (value >= BYTES_PER_UNIT && unit < UNITS.length - 1) {
29
+ value = value / BYTES_PER_UNIT
30
+ unit += 1
31
+ }
32
+ return value.toFixed(1) + UNIT_SPACE + UNITS[unit]
33
+ }
34
+
35
+ // Fills %1 to %9 in one pass: a value prints as given, a dollar sign or placeholder in it included; an unfilled one stays.
36
+ function fill(template) {
37
+ var values = arguments
38
+ return String(template).replace(/%([1-9])/g, function (token, at) { return at < values.length ? String(values[at]) : token })
39
+ }
40
+
41
+ function pad(n) {
42
+ return n < 10 ? "0" + n : "" + n
43
+ }
44
+
45
+ // "2026-09-12 15:29", the one form every surface prints, in the machine's local wall clock.
46
+ function stamp(d) {
47
+ return d.getFullYear() + "-" + pad(d.getMonth() + 1) + "-" + pad(d.getDate())
48
+ + " " + pad(d.getHours()) + ":" + pad(d.getMinutes())
49
+ }
50
+
51
+ // One form, sortable and unambiguous, so no surface has to invent a relative word for a time.
52
+ function date(mtime) {
53
+ return stamp(new Date(mtime * 1000))
54
+ }
55
+
56
+ // The send picker's column is SendPicker.html's 80 and not the window's 125, which holds about ten
57
+ // characters: the one place the full stamp does not fit. It drops the time and keeps the date, so it
58
+ // is still sortable and still unambiguous. Preview board, "One function, four surfaces".
59
+ function compactDate(mtime) {
60
+ var d = new Date(mtime * 1000)
61
+ return d.getFullYear() + "-" + pad(d.getMonth() + 1) + "-" + pad(d.getDate())
62
+ }
63
+
64
+ // The low nine bits of st_mode, read three at a time.
65
+ var PERMISSION_BITS = 9
66
+ var TRIAD = "rwx"
67
+
68
+ function permissions(mode) {
69
+ var out = ""
70
+ for (var i = 0; i < PERMISSION_BITS; i++) {
71
+ var bit = 1 << (PERMISSION_BITS - 1 - i)
72
+ out += (mode & bit) ? TRIAD[i % TRIAD.length] : "-"
73
+ }
74
+ return out
75
+ }
76
+
77
+ // The file type lives in the top four bits of st_mode, as S_IFMT masks it.
78
+ var S_IFMT = 0o170000
79
+ var S_IFREG = 0o100000
80
+ var S_IFDIR = 0o040000
81
+ // The owner execute bit, the one Make executable adds.
82
+ var S_IXUSR = 0o100
83
+ var S_IFLNK = 0o120000
84
+ var ANY_EXECUTE_BIT = 0o111
85
+
86
+ function isSymlink(mode) {
87
+ return (mode & S_IFMT) === S_IFLNK
88
+ }
89
+
90
+ function isExecutable(mode) {
91
+ return (mode & ANY_EXECUTE_BIT) !== 0
92
+ }
93
+
94
+ // Shared by Row.qml's iconSource and PreviewMedia.qml's player source: encodeURI leaves # and ?
95
+ // literal, which Qt then reads as a URL fragment or query rather than path bytes.
96
+ function fileUri(path) {
97
+ return "file://" + encodeURI(path).replace(/#/g, "%23").replace(/\?/g, "%3F")
98
+ }
99
+
100
+ // "3:05", or "1:03:05" once an hour is on the clock; mm/ss are always two digits, matching a media player's own clock rather than Format.date's prose.
101
+ function duration(ms) {
102
+ var totalSeconds = Math.max(0, Math.floor(ms / 1000))
103
+ var hours = Math.floor(totalSeconds / 3600)
104
+ var minutes = Math.floor((totalSeconds % 3600) / 60)
105
+ var seconds = totalSeconds % 60
106
+ if (hours > 0) {
107
+ return hours + ":" + pad(minutes) + ":" + pad(seconds)
108
+ }
109
+ return minutes + ":" + pad(seconds)
110
+ }
111
+
112
+ // The scope reads as the user writes it, so the home prefix comes back as a tilde. Both the search
113
+ // strip and the window chrome draw a path through this, so the rule has one definition.
114
+ // Issue 95, nixfred: a bare prefix made /home/gmx into "~x", a sibling wearing home's name. The test
115
+ // is home itself or home and a separator, the one ui/js/Nav.js crumbs and Search.scopeRoot both make.
116
+ function tilde(path, home) {
117
+ var text = String(path)
118
+ if (home.length > 0 && (text === home || text.indexOf(home + "/") === 0)) {
119
+ return "~" + text.substring(home.length)
120
+ }
121
+ return text
122
+ }
123
+
124
+ // A tab is named after the directory it is standing in, so the label is the path's last segment.
125
+ function leafPart(display) {
126
+ var text = String(display)
127
+ var cut = text.lastIndexOf("/")
128
+ if (cut < 0) {
129
+ return text
130
+ }
131
+ // "/" itself has no leaf, and its own separator is the whole label.
132
+ return cut === text.length - 1 ? text : text.substring(cut + 1)
133
+ }
134
+
135
+ // "44.1 kHz", the way the canvas writes an audio row's Rate; a zero is not a rate and reads empty.
136
+ function sampleRate(hz) {
137
+ var n = Number(hz)
138
+ if (!n || n <= 0) {
139
+ return ""
140
+ }
141
+ var khz = n / 1000
142
+ // A whole number of kilohertz reads without a decimal, so 48000 is "48 kHz" and not "48.0 kHz".
143
+ return (khz === Math.round(khz) ? khz : khz.toFixed(1)) + " kHz"
144
+ }
145
+
146
+ // Issue 67, jesedv: a yanked path is quoted unless a shell reads every character of it as itself.
147
+ function shellQuoted(path) {
148
+ var text = String(path)
149
+ if (/^[A-Za-z0-9_@%+=:,.\/-]+$/.test(text)) {
150
+ return text
151
+ }
152
+ return "'" + text.split("'").join("'\\''") + "'"
153
+ }
154
+
155
+ // One window-level day boundary, so no Date is built and no timer ticks per row.
156
+
157
+ // Sample input: Date.now() on the board date, 2026-09-23 11:40 local.
158
+ var DAY_MS = 24 * 60 * 60 * 1000
159
+ // The midnight timer's minute step, so a suspend still lands the day within a minute of resume.
160
+ var MINUTE_MS = 60 * 1000
161
+
162
+ // Local midnight starting the day nowMs falls in, in ms since the epoch.
163
+ function dayStart(nowMs) {
164
+ var now = new Date(nowMs)
165
+ return new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime()
166
+ }
167
+
168
+ // True when the stamp is on or after today's local midnight.
169
+ function isRecent(mtimeSec, todayStartMs) {
170
+ if (typeof mtimeSec !== "number" || !isFinite(mtimeSec))
171
+ return false
172
+ return mtimeSec * 1000 >= todayStartMs
173
+ }
174
+
175
+ // Built from components, so a daylight-saving night still lands on midnight.
176
+ function msUntilMidnight(nowMs) {
177
+ var now = new Date(nowMs)
178
+ return new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).getTime() - nowMs
179
+ }
180
+
181
+ // Elides in the middle so the extension stays visible; truncation costs a slice, never a relayout.
182
+ // Sample input: "screenshot-2026-08-30-final-review-for-gm-after-the-bench-v3.png", 49.
183
+
184
+ // The walk pairs surrogates by hand, so a cut never splits a code point.
185
+ function charsOf(text) {
186
+ var out = []
187
+ for (var i = 0; i < text.length; i++) {
188
+ var lead = text.charCodeAt(i)
189
+ if (lead >= 0xD800 && lead <= 0xDBFF && i + 1 < text.length) {
190
+ var trail = text.charCodeAt(i + 1)
191
+ if (trail >= 0xDC00 && trail <= 0xDFFF) {
192
+ out.push(text.substring(i, i + 2))
193
+ i += 1
194
+ continue
195
+ }
196
+ }
197
+ // A combining mark rides with the char before it, so an NFD accent never orphans.
198
+ if (lead >= 0x0300 && lead <= 0x036F && out.length > 0) {
199
+ out[out.length - 1] += text.charAt(i)
200
+ continue
201
+ }
202
+ out.push(text.charAt(i))
203
+ }
204
+ return out
205
+ }
206
+
207
+ // Every fast unit sits below U+0300, so a fast name holds no surrogate, no combining mark and no wide glyph.
208
+ var FAST_LIMIT = 0x0300
209
+
210
+ // True when every UTF-16 unit is fast: each char paints one cell and slices never split a point.
211
+ function isFastText(text) {
212
+ for (var i = 0; i < text.length; i++)
213
+ if (text.charCodeAt(i) >= FAST_LIMIT) return false
214
+ return true
215
+ }
216
+
217
+ function middleElide(name, maxCells) {
218
+ var text = String(name), max = Math.max(0, Math.floor(maxCells))
219
+ // A non-finite budget names no width, so the name goes through untouched.
220
+ if (!isFinite(max)) return text
221
+ // One scan serves the fit check and the store below, so a fitting fast name builds nothing.
222
+ var fast = isFastText(text)
223
+ // A fast name counts one cell a char, so a short one already fits untouched.
224
+ if (fast && text.length <= max) return text
225
+ var st = fast ? fastStoreOf(text) : storeOf(charsOf(text))
226
+ if (rangeCells(st, 0, st.n) <= max) return text
227
+ // The head takes the odd cell, so a 49-wide board keeps 24 and 24.
228
+ var h = spanFrom(st, 0, Math.ceil((max - 1) / 2)), t = tailSpan(st, Math.floor((max - 1) / 2))
229
+ return pieceOf(st, 0, h) + "…" + pieceOf(st, st.n - t, st.n)
230
+ }
231
+
232
+ // Display cells: East Asian Wide and Fullwidth paint two columns, emoji paint two, all else one.
233
+ // Sample input: cellWidthOf("🎉") is 2, cellWidthOf("A") is 1.
234
+ var WIDE_RANGES = [[0x1100, 0x115F], [0x2E80, 0x303E], [0x3041, 0x33FF], [0x3400, 0x4DBF], [0x4E00, 0xA4CF], [0xAC00, 0xD7A3], [0xF900, 0xFAFF], [0xFE10, 0xFE19], [0xFE30, 0xFE4F], [0xFF00, 0xFF60], [0xFFE0, 0xFFE6], [0x20000, 0x3FFFD]]
235
+ var EMOJI_RANGES = [[0x2600, 0x26FF], [0x2700, 0x27BF], [0x2B00, 0x2BFF], [0x1F000, 0x1FAFF]]
236
+
237
+ // True when a code point paints two columns rather than one.
238
+ function isWideCode(cp) {
239
+ // Every wide range starts at U+1100, so a smaller code point never scans.
240
+ if (cp < 0x1100) return false
241
+ for (var i = 0; i < WIDE_RANGES.length; i++)
242
+ if (cp >= WIDE_RANGES[i][0] && cp <= WIDE_RANGES[i][1]) return true
243
+ for (var j = 0; j < EMOJI_RANGES.length; j++)
244
+ if (cp >= EMOJI_RANGES[j][0] && cp <= EMOJI_RANGES[j][1]) return true
245
+ return false
246
+ }
247
+
248
+ // The code point one charsOf element starts with, read without wrapping it in a string.
249
+ // Sample input: codeOf("🎉") is 0x1F389, codeOf("A") is 0x41.
250
+ function codeOf(ch) {
251
+ var s = String(ch), lead = s.charCodeAt(0)
252
+ if (lead >= 0xD800 && lead <= 0xDBFF && s.length > 1) {
253
+ var trail = s.charCodeAt(1)
254
+ if (trail >= 0xDC00 && trail <= 0xDFFF) return 0x10000 + ((lead - 0xD800) << 10) + (trail - 0xDC00)
255
+ }
256
+ return lead
257
+ }
258
+
259
+ // Cells one char paints: 2 for a wide code point, 1 for all else.
260
+ function cellWidthOf(ch) {
261
+ return isWideCode(codeOf(ch)) ? 2 : 1
262
+ }
263
+
264
+ // One layout per call: widths plus prefix sums, so every range below is one subtraction.
265
+ // Sample input: storeOf(["a", "🎉"]) carries widths [1, 2].
266
+ function storeOf(chars) {
267
+ var widths = new Array(chars.length), prefix = new Array(chars.length + 1)
268
+ prefix[0] = 0
269
+ for (var i = 0; i < chars.length; i++) {
270
+ widths[i] = isWideCode(codeOf(chars[i])) ? 2 : 1
271
+ prefix[i + 1] = prefix[i] + widths[i]
272
+ }
273
+ return { seq: chars, widths: widths, prefix: prefix, n: chars.length }
274
+ }
275
+
276
+ // The same layout over a fast string: no arrays, every range counts chars as cells.
277
+ function fastStoreOf(text) {
278
+ return { seq: text, widths: null, prefix: null, n: text.length }
279
+ }
280
+
281
+ // Cells of elements [a..b).
282
+ function rangeCells(st, a, b) {
283
+ return st.widths === null ? b - a : st.prefix[b] - st.prefix[a]
284
+ }
285
+
286
+ // Elements from pos fitting in this many cells.
287
+ function spanFrom(st, pos, budget) {
288
+ if (st.widths === null) return Math.min(Math.max(budget, 0), st.n - pos)
289
+ var used = 0, i = pos
290
+ while (i < st.widths.length && used + st.widths[i] <= budget) { used += st.widths[i]; i += 1 }
291
+ return i - pos
292
+ }
293
+
294
+ // Trailing elements fitting in this many cells.
295
+ function tailSpan(st, budget) {
296
+ if (st.widths === null) return Math.min(Math.max(budget, 0), st.n)
297
+ var used = 0, i = st.widths.length
298
+ while (i > 0 && used + st.widths[i - 1] <= budget) { used += st.widths[i - 1]; i -= 1 }
299
+ return st.widths.length - i
300
+ }
301
+
302
+ // Text of elements [a..b): a slice for a fast string, a join for a char array.
303
+ function pieceOf(st, a, b) {
304
+ return st.widths === null ? st.seq.slice(a, b) : st.seq.slice(a, b).join("")
305
+ }
package/ui/js/Fuzzy.js ADDED
@@ -0,0 +1,141 @@
1
+ .pragma library
2
+
3
+ // src/backend/fuzzy.rs ported, weight for weight, so the path bar's jump and search agree on what matched
4
+ // and where. Pure; tests/js/jump.js holds it to the Rust tests' own table of exact scores.
5
+ var BONUS_CONSECUTIVE = 8
6
+ var BONUS_BOUNDARY = 6
7
+ var BONUS_BASENAME = 4
8
+ var PENALTY_GAP = 1
9
+ var MAX_STARTS = 16
10
+
11
+ function isSeparator(c) {
12
+ return c === "/" || c === "-" || c === "_" || c === "." || c === " "
13
+ }
14
+
15
+ // corner: a character whose lowercase form is longer keeps its first unit, the corner fuzzy.rs documents,
16
+ // and a character outside the basic plane counts as two here where Rust counts one, which moves only a gap charge.
17
+ function fold(text) {
18
+ var out = []
19
+ for (var i = 0; i < text.length; i++) {
20
+ var c = text.charAt(i)
21
+ var lower = c.toLowerCase().charAt(0)
22
+ out.push({ lower: lower, upper: lower !== c })
23
+ }
24
+ return out
25
+ }
26
+
27
+ function baseStart(hay) {
28
+ var start = 0
29
+ for (var i = 0; i < hay.length; i++) {
30
+ if (hay[i].lower === "/") {
31
+ start = i + 1
32
+ }
33
+ }
34
+ return start
35
+ }
36
+
37
+ function startsAWord(hay, at) {
38
+ if (at === 0) {
39
+ return true
40
+ }
41
+ var before = hay[at - 1]
42
+ return isSeparator(before.lower) || (hay[at].upper && !before.upper)
43
+ }
44
+
45
+ // What one matched character is worth: a run, a boundary and the base name each add, and the
46
+ // characters skipped to reach it are charged back.
47
+ function characterScore(hay, at, base, previous) {
48
+ var score = 0
49
+ if (previous >= 0) {
50
+ score += at === previous + 1 ? BONUS_CONSECUTIVE : -PENALTY_GAP * (at - previous - 1)
51
+ }
52
+ if (startsAWord(hay, at)) {
53
+ score += BONUS_BOUNDARY
54
+ }
55
+ if (at >= base) {
56
+ score += BONUS_BASENAME
57
+ }
58
+ return score
59
+ }
60
+
61
+ // Greedy from one start: every query character takes the next candidate character that matches it.
62
+ function alignFrom(hay, needle, start, base) {
63
+ var total = 0
64
+ var at = start
65
+ var previous = -1
66
+ var positions = []
67
+ for (var k = 0; k < needle.length; k++) {
68
+ if (k > 0) {
69
+ at++
70
+ while (at < hay.length && hay[at].lower !== needle.charAt(k)) {
71
+ at++
72
+ }
73
+ if (at === hay.length) {
74
+ return null
75
+ }
76
+ }
77
+ total += characterScore(hay, at, base, previous)
78
+ positions.push(at)
79
+ previous = at
80
+ }
81
+ return { score: total, positions: positions }
82
+ }
83
+
84
+ // null when the query is not a subsequence of the candidate; otherwise the best alignment's score and
85
+ // the positions it matched, which is what the wash is drawn from. The needle is the query lowered once
86
+ // by the caller; the hay is folded once per open by ui/js/Jump.js prepare, never per keystroke.
87
+ function matchFolded(hay, base, needle) {
88
+ if (needle.length === 0) {
89
+ return { score: 0, positions: [] }
90
+ }
91
+ var best = null
92
+ var starts = 0
93
+ for (var i = 0; i < hay.length; i++) {
94
+ if (hay[i].lower !== needle.charAt(0)) {
95
+ continue
96
+ }
97
+ var found = alignFrom(hay, needle, i, base)
98
+ // A start that cannot finish means no later start can either, the greedy scan's own guarantee.
99
+ if (found === null) {
100
+ return best
101
+ }
102
+ if (best === null || found.score > best.score) {
103
+ best = found
104
+ }
105
+ starts++
106
+ if (starts === MAX_STARTS) {
107
+ break
108
+ }
109
+ }
110
+ return best
111
+ }
112
+
113
+ // null when the query is not a subsequence of the candidate; otherwise the best alignment's score and
114
+ // the positions it matched, which is what the wash is drawn from.
115
+ function match(candidate, query) {
116
+ var needle = String(query).toLowerCase()
117
+ if (needle.length === 0) {
118
+ return { score: 0, positions: [] }
119
+ }
120
+ var hay = fold(String(candidate))
121
+ var base = baseStart(hay)
122
+ return matchFolded(hay, base, needle)
123
+ }
124
+
125
+ // The one run the row washes: the longest stretch of consecutive matched positions, the first on a tie.
126
+ function run(positions) {
127
+ var best = { start: -1, length: 0 }
128
+ var i = 0
129
+ while (i < positions.length) {
130
+ var j = i
131
+ while (j + 1 < positions.length && positions[j + 1] === positions[j] + 1) {
132
+ j++
133
+ }
134
+ if (j - i + 1 > best.length) {
135
+ best = { start: positions[i], length: j - i + 1 }
136
+ }
137
+ i = j + 1
138
+ }
139
+ return best
140
+ }
141
+
@@ -0,0 +1,72 @@
1
+ .pragma library
2
+
3
+ // The Hyprland tag Omarchy's transparency hotkey sets; Omarchy's own rule then draws the window at its Transparent opacity.
4
+ var TAG = "transparent"
5
+ // Hyprland addresses are lowercase hex with a 0x prefix; nothing else reaches a dispatch.
6
+ var ADDRESS = /^0x[0-9a-f]+$/
7
+ // Prints "address opacity inactive" for each address argument, read from Hyprland's own window properties.
8
+ var PROBE = 'for a in "$@"; do printf "%s %s %s\\n" "$a" "$(hyprctl getprop "address:$a" opacity)" "$(hyprctl getprop "address:$a" opacity_inactive)"; done'
9
+ // Applies "address tag" argument pairs with the Lua dispatcher, else the classic one, as omarchy-hyprland-window-pop does.
10
+ var DISPATCH = 'while [ "$#" -ge 2 ]; do hyprctl dispatch "hl.dsp.window.tag({ window = \\"address:$1\\", tag = \\"$2\\" })" >/dev/null 2>&1 || hyprctl dispatch tagwindow "$2" "address:$1" >/dev/null; shift 2; done'
11
+
12
+ // Sample input: hyprctl clients -j, '[{"address":"0x55bacb0a1f80","pid":4211,"class":"com.thisisgm.flea"}]'.
13
+ function ownAddresses(json, pid) {
14
+ var list
15
+ try {
16
+ list = JSON.parse(json)
17
+ } catch (e) {
18
+ return []
19
+ }
20
+ if (!Array.isArray(list))
21
+ return []
22
+ var out = []
23
+ for (var i = 0; i < list.length; i++) {
24
+ var c = list[i]
25
+ if (c && c.pid === pid && ADDRESS.test(String(c.address)))
26
+ out.push(String(c.address))
27
+ }
28
+ return out
29
+ }
30
+
31
+ // Sample input, one PROBE line: "0x55bacb0a1f80 0.985 0.96".
32
+ function parseProps(line) {
33
+ var f = String(line).trim().split(/\s+/)
34
+ if (f.length !== 3 || !ADDRESS.test(f[0]))
35
+ return null
36
+ return {address: f[0], opacity: Number(f[1]), inactive: Number(f[2])}
37
+ }
38
+
39
+ // "add", "remove" or "keep" for one Flea window: the tag goes only where Omarchy draws Transparent and Hyprland leaves the window at 1.
40
+ function decide(mode, usesDefault, opacity, inactive, taggedByFlea) {
41
+ var wanted = mode === "transparent" && usesDefault
42
+ // The hotkey's own test, which also re-tags a window that reuses a closed one's address: a window Hyprland already draws
43
+ // below 1, as stable Omarchy draws every window, keeps its rule.
44
+ if (wanted && opacity === 1 && inactive === 1)
45
+ return "add"
46
+ return taggedByFlea && !wanted ? "remove" : "keep"
47
+ }
48
+
49
+ // The dispatch pairs for PROBE's output, and the set Flea has tagged once they run; a closed window's record drops out.
50
+ function plan(text, mode, usesDefault, tagged) {
51
+ var next = {}
52
+ var pairs = []
53
+ var lines = String(text).split("\n")
54
+ for (var i = 0; i < lines.length; i++) {
55
+ var w = parseProps(lines[i])
56
+ if (!w)
57
+ continue
58
+ var mine = tagged[w.address] === true
59
+ if (mine)
60
+ next[w.address] = true
61
+ var act = decide(mode, usesDefault, w.opacity, w.inactive, mine)
62
+ if (act === "add") {
63
+ pairs.push(w.address, "+" + TAG)
64
+ next[w.address] = true
65
+ }
66
+ if (act === "remove") {
67
+ pairs.push(w.address, "-" + TAG)
68
+ delete next[w.address]
69
+ }
70
+ }
71
+ return {pairs: pairs, tagged: next}
72
+ }
package/ui/js/Grid.js ADDED
@@ -0,0 +1,33 @@
1
+ .pragma library
2
+
3
+ .import "Filter.js" as Filter
4
+ .import "Marks.js" as Marks
5
+
6
+ // The grid's own geometry: which cell a key means when the rows are tiles rather than lines. Split
7
+ // out of ui/js/Focus.js, which holds the key map and the actions every view shares.
8
+
9
+ // Which way a key steps across a row of tiles, the arrow and the letter the presets spell it with.
10
+ function sideways(event) {
11
+ return event.key === Qt.Key_Left || event.text === "h" ? -1
12
+ : event.key === Qt.Key_Right || event.text === "l" ? 1 : 0
13
+ }
14
+
15
+ // Arrow and letter actions share visual cells; absent neighbours clamp even when list navigation wraps.
16
+ function arrow(event, action, root) {
17
+ if (root.viewMode !== "grid") return false
18
+ var columns = root.cursorStride
19
+ var across = sideways(event)
20
+ var delta = (action === "cursorDown" || action === "extendDown") ? columns
21
+ : (action === "cursorUp" || action === "extendUp") ? -columns
22
+ : across < 0 && action === "cursorLeft" ? -1
23
+ : across > 0 && action === "cursorRight" ? 1 : 0
24
+ if (!delta) return false
25
+ var index = Filter.viewOf(root.shown, root.cursorIndex)
26
+ var nextIndex = index + delta
27
+ if (nextIndex < 0 || nextIndex >= root.shownTotal
28
+ || (across < 0 && index % columns === 0)
29
+ || (across > 0 && nextIndex % columns === 0)) return true
30
+ if (action === "extendDown" || action === "extendUp") root.extendSelection(delta)
31
+ else { Filter.moveCursor(root, delta); Marks.follow(root) }
32
+ return true
33
+ }
@@ -0,0 +1,90 @@
1
+ .pragma library
2
+
3
+ // The grid's tile maths, split out of ui/GridArea.qml so tests/js/gridgeometry.js can pin it.
4
+
5
+ // Width less one gap and the scroll lane, so no tile sits under the bar.
6
+ // Sample input: columnsFor(800, 146, 96, 7, 8) is 5, five tiles across an 800 px grid.
7
+ function columnsFor(width, minCellWidth, tilePixels, rowPaddingX, gap, lane) {
8
+ var cell = Math.max(minCellWidth, tilePixels + 2 * rowPaddingX)
9
+ return Math.max(1, Math.floor((width - gap - (Number(lane) || 0)) / cell))
10
+ }
11
+
12
+ // Sample input: cellWidthFor(800, 5, 8) is 158, five cells filling the 792 beside the gap.
13
+ function cellWidthFor(width, columns, gap, lane) {
14
+ return Math.max(1, Math.floor((width - gap - (Number(lane) || 0)) / Math.max(1, columns)))
15
+ }
16
+
17
+ // A cell is its slot plus the name gap plus two caption lines plus the pad above and below.
18
+ // Sample input: cellHeightFor(128, 9, 33, 14) is 198, the board tile.
19
+ function cellHeightFor(thumbPixels, gap, captionHeight, padY) {
20
+ return Math.max(1, thumbPixels + gap + captionHeight + 2 * padY)
21
+ }
22
+
23
+ // Tile rows the view keeps built beyond its edge, the one number ui/GridArea.qml's cacheBuffer and a landing's ask both count.
24
+ var cacheRows = 2
25
+
26
+ // The window a grid holds, in whole tile rows: the list's context in pixels (bufferRows of rowHeight each side) rebuilt in tiles, so a screen of tiles keeps the room a screen of rows keeps.
27
+ // Sample input: windowFor(18, 11, 150, 26, 124, 25) is {columns: 18, visible: 11, buffer: 576, size: 1350, margin: 36}, 32 tile rows each side of 11, and a margin of two tile rows.
28
+ function windowFor(columns, visibleTileRows, bufferRows, rowHeight, cellHeight, refetchMargin) {
29
+ var across = Math.max(1, columns)
30
+ var rows = Math.max(1, Math.ceil(bufferRows * rowHeight / Math.max(1, cellHeight)))
31
+ var visible = Math.max(1, visibleTileRows)
32
+ return { columns: across, visible: visible, buffer: across * rows, size: across * (visible + 2 * rows), margin: Math.max(refetchMargin, 2 * across) }
33
+ }
34
+
35
+ // The window the visible items owe the backend once they come within the margin of an edge the held rows have a further side to, or when none are held.
36
+ // Sample input: driftAsk({buffer: 576, size: 1350, margin: 36}, 1000, 1330, 0, 1350, 2000) is {start: 424, count: 1350}, and null at 1000 to 1200.
37
+ function driftAsk(plan, first, last, held, length, total) {
38
+ var end = held + length
39
+ var behind = held > 0 && first - held < plan.margin
40
+ var ahead = end < total && end - last < plan.margin
41
+ return length === 0 || behind || ahead ? { start: Math.max(0, first - plan.buffer), count: plan.size } : null
42
+ }
43
+
44
+ // The window a far cursor landing owes the backend before the view moves, or null for a step or a landing the held rows reach.
45
+ // Sample input: landingAsk(plan, 1999, 0, 2000, 0, 352) with the plan above is {start: 1746, count: 254}, the tail of the listing; with 1500 rows held from 700 it is null.
46
+ function landingAsk(plan, cursorIndex, firstIndex, total, held, heldLength) {
47
+ var row = Math.floor(cursorIndex / plan.columns)
48
+ var seen = Math.floor(firstIndex / plan.columns)
49
+ if (Math.abs(row - seen) <= plan.visible)
50
+ return null
51
+ var before = row > seen ? plan.visible + 1 : cacheRows + 1
52
+ var after = row > seen ? cacheRows + 1 : plan.visible + 1
53
+ var start = Math.max(0, (row - before) * plan.columns - plan.margin)
54
+ var end = Math.min(total, (row + after) * plan.columns + plan.margin)
55
+ if (start >= held && end <= held + heldLength)
56
+ return null
57
+ return { start: start, count: end - start }
58
+ }
59
+
60
+ // Whether two rows draw the same tile: every field equal, so a reply that repeats a row hands its tile nothing to redraw.
61
+ // Sample input: sameRow({n: "a", tg: [2]}, {n: "a", tg: [2]}) is true, sameRow({n: "a"}, null) is false.
62
+ function sameRow(a, b) {
63
+ if (a === b)
64
+ return true
65
+ if (a === null || b === null || a === undefined || b === undefined)
66
+ return false
67
+ var keys = Object.keys(a)
68
+ if (keys.length !== Object.keys(b).length)
69
+ return false
70
+ for (var i = 0; i < keys.length; i++) {
71
+ var x = a[keys[i]], y = b[keys[i]]
72
+ if (x !== y && (typeof x !== "object" || typeof y !== "object" || JSON.stringify(x) !== JSON.stringify(y)))
73
+ return false
74
+ }
75
+ return true
76
+ }
77
+
78
+ // The row a tile draws from the held snapshot {start, rows, listing}: the held row, else the row it kept at this index on the same listing, else null; memo is the tile's own {row, index, listing}.
79
+ // Sample input: heldRow({row: null, index: -1, listing: 0}, {start: 10, rows: [a, b], listing: 1}, 11) is b, and a tile at 5 afterwards keeps what it drew at 5.
80
+ function heldRow(memo, held, index) {
81
+ var offset = index - held.start
82
+ var next = offset >= 0 && offset < held.rows.length ? held.rows[offset] : null
83
+ var kept = next === null ? memo.index === index && memo.listing === held.listing : sameRow(memo.row, next)
84
+ memo.index = index
85
+ memo.listing = held.listing
86
+ if (kept)
87
+ return memo.row
88
+ memo.row = next
89
+ return next
90
+ }