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,103 @@
1
+ .pragma library
2
+ .import "Columns.js" as Columns
3
+ .import "FolderSorts.js" as FolderSorts
4
+ .import "Format.js" as Format
5
+
6
+ // Navigations carry answered peeks across a listing and refresh them without clearing drawn rows.
7
+
8
+ // A peek answers at most this many rows, src/backend/peek.rs PEEK_CAP.
9
+ var PEEK_CAP = 512
10
+
11
+ // The folder order a column asks under, as the tag its peek key and reply carry.
12
+ // Sample input: orderOf({ folderSorts: {}, rememberSort: true }, "/a", []) is "" for a folder with no order of its own.
13
+ function orderOf(state, path, drawn, newest) {
14
+ var order = FolderSorts.peekOrder(state.folderSorts, path, state.rememberSort, drawn, newest, state.sort)
15
+ return Columns.orderTag(order.by, order.desc)
16
+ }
17
+
18
+ // A read of the peeked rows that a binding re-evaluates when a peek lands; version is the trigger.
19
+ function rowsFor(peeked, key, path, version) {
20
+ return version >= 0 && path.length > 0 && peeked[key] ? peeked[key] : []
21
+ }
22
+
23
+ // -1 for a path that was not denied, so mode 0, the denial whose stat failed too, stays its own answer.
24
+ function deniedMode(denials, key, version) {
25
+ return version >= 0 && denials[key] !== undefined ? denials[key] : -1
26
+ }
27
+
28
+ // What a drag from a peek column's row needs. Sample input: peekSource(pane, "/a", { "/a": { v: 7, w: false } }, 0).
29
+ function peekSource(pane, path, facts, version) {
30
+ var held = version >= 0 ? facts[path] : undefined
31
+ return path.length > 0 ? { pane: pane, dir: path, v: held ? held.v : 0, w: held ? held.w : true } : null
32
+ }
33
+
34
+ // True when the target is the parent of the shown path: the one hop whose child is the folder left.
35
+ // Sample input: isBack("/a/b/c", "/a/b") is true, isBack("/a/b", "/a/b/c") and isBack("/", "/") are false.
36
+ function isBack(here, target) {
37
+ return String(target) !== String(here) && String(target) === Columns.ancestorParent(here)
38
+ }
39
+
40
+ // A peek sorts name-first with folders first, so the listing must match that order exactly.
41
+ // Sample input: sameOrder({ by: "name", desc: false, foldersFirst: true, groupByKind: false }, "") is true.
42
+ function sameOrder(list, tag) {
43
+ return list.by === "name" && list.desc !== true && list.foldersFirst !== false && list.groupByKind !== true
44
+ && (tag === "" || tag === "name0")
45
+ }
46
+
47
+ // The held window as peek rows; a link or an executable seeds nothing, shaped differently in a peek.
48
+ // Sample input: peekRows([{ n: "a", d: false, i: "text-x-generic", s: 1 }], 1).
49
+ function peekRows(rows, count) {
50
+ var out = []
51
+ for (var i = 0; i < count; i++) {
52
+ var row = rows[i]
53
+ if (!row || row.l !== undefined || (Number(row.p) & Format.S_IFMT) === Format.S_IFLNK || (row.d !== true && row.i === "application-x-executable"))
54
+ return null
55
+ out.push({ n: row.n, d: row.d === true, i: row.i })
56
+ }
57
+ return out
58
+ }
59
+
60
+ // A navigation plan, or null before the first listing has anything to carry.
61
+ // Sample input: plan(area at "/a/b/c" listing "/a/b", ["/a"], { foldersFirst: true, groupByKind: false }).pre is ["/a"].
62
+ function plan(area, asks, state) {
63
+ var p = area.pane, here = p.path, target = p.listingPath
64
+ if (!here || !target)
65
+ return null
66
+ var tag = area.orderOf(here), count = Math.min(p.windowSize, PEEK_CAP, p.total)
67
+ var list = { by: p.backend.sortBy, desc: p.backend.sortDesc, foldersFirst: state.foldersFirst, groupByKind: state.groupByKind }
68
+ var clean = p.held === 0 && p.filterQuery === "" && p.searchMode === "" && p.rows.length >= count && sameOrder(list, tag)
69
+ return { target: target, seed: here, tag: tag, pre: asks.filter(function (path) { return path !== target && path !== here }),
70
+ rows: clean ? peekRows(p.rows, count) : null, facts: { v: p.backend.dirDev || 0, w: p.backend.dirWritable !== false } }
71
+ }
72
+
73
+ // A landing keeps answered drawn folders under the same key and order, plus the old third while its replacement waits.
74
+ function landing(carry, area, asks) {
75
+ var next = { peeked: {}, denials: {}, orders: {}, facts: {}, pending: {} }
76
+ if (!carry || carry.target !== area.pane.path)
77
+ return next
78
+ var paths = asks.slice()
79
+ if (area.shownChildPath && paths.indexOf(area.shownChildPath) < 0) paths.push(area.shownChildPath)
80
+ for (var i = 0; i < paths.length; i++) {
81
+ var path = paths[i], key = area.peekKey(path)
82
+ if (area.peeked[key] === undefined || area.peekOrders[key] !== area.orderOf(path))
83
+ continue
84
+ next.peeked[key] = area.peeked[key]
85
+ next.orders[key] = area.peekOrders[key]
86
+ if (area.denials[key] !== undefined) next.denials[key] = area.denials[key]
87
+ if (area.peekFacts[path] !== undefined) next.facts[path] = area.peekFacts[path]
88
+ }
89
+ var seedKey = area.peekKey(carry.seed), seedTag = area.orderOf(carry.seed)
90
+ if ((asks.indexOf(carry.seed) >= 0 || isBack(carry.seed, carry.target))
91
+ && carry.rows !== null && carry.tag === seedTag && next.peeked[seedKey] === undefined) {
92
+ next.peeked[seedKey] = carry.rows
93
+ next.orders[seedKey] = seedTag
94
+ next.facts[carry.seed] = carry.facts
95
+ }
96
+ if (asks.indexOf(carry.seed) >= 0 || isBack(carry.seed, carry.target)) paths.push(carry.seed)
97
+ // A watched refresh already out must still land after navigation, even when its folder's settled rows are kept.
98
+ for (var path of paths) {
99
+ var sent = Columns.sentKey(area.peekKey(path), area.pane.windowSize, area.orderOf(path))
100
+ if (Columns.hasAsk(area.pending, sent)) next.pending[sent] = area.pending[sent]
101
+ }
102
+ return next
103
+ }
@@ -0,0 +1,74 @@
1
+ .pragma library
2
+
3
+ .import "Format.js" as Format
4
+ .import "CopyAs.js" as CopyAs
5
+ .import "Ops.js" as Ops
6
+
7
+ // The Compare overlay's text and rows: ui/CompareView.qml draws what these return and keeps no wording of its own.
8
+
9
+ // The board's sentences for a pair with no patch, by the backend's state (src/backend/compare.rs).
10
+ var SENTENCES = {
11
+ identical: "The two files are identical.",
12
+ binary: "These files are binary, so there is nothing to compare.",
13
+ over: "These files are over 1 MiB, too large to compare.",
14
+ failed: "These files could not be compared."
15
+ }
16
+
17
+ var HUNK = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/
18
+
19
+ function sentence(state) {
20
+ return SENTENCES[state] || ""
21
+ }
22
+
23
+ // Fills %1, %2 ... in one pass, so a file name holding "%2" is never read as a placeholder.
24
+ function fill(template, values) {
25
+ return template.replace(/%(\d)/g, function (whole, n) { return values[Number(n) - 1] })
26
+ }
27
+
28
+ // "notes-a.md and notes-b.md · 12 lines differ" with a patch; without one, the two names alone.
29
+ // Sample input: title("a.md", "b.md", 1) gives "a.md and b.md · 1 line differs".
30
+ function title(nameA, nameB, differing) {
31
+ if (differing === undefined || differing === null)
32
+ return fill("%1 and %2", [nameA, nameB])
33
+ var count = fill(Ops.pluralWord(differing, "%1 line differs", "%1 lines differ"), [Format.count(differing)])
34
+ return fill("%1 and %2 · %3", [nameA, nameB, count])
35
+ }
36
+
37
+ // What diff -u prints, as the rows the overlay draws; the --- and +++ lines are the copied patch's, not rows.
38
+ // Sample input: "--- a\n+++ b\n@@ -1,2 +1,2 @@\n x\n-y\n+z\n" gives a hunk row, a context row 1/1, a removed row 2/0 and an added row 0/2.
39
+ function rows(patch) {
40
+ var out = [], oldAt = 0, newAt = 0, inHunk = false
41
+ var lines = String(patch).split("\n")
42
+ if (lines[lines.length - 1] === "")
43
+ lines.pop()
44
+ for (var i = 0; i < lines.length; i++) {
45
+ var line = lines[i], head = HUNK.exec(line)
46
+ if (head) {
47
+ oldAt = Number(head[1])
48
+ newAt = Number(head[3])
49
+ inHunk = true
50
+ out.push({ kind: "hunk", oldNo: 0, newNo: 0, text: line })
51
+ } else if (!inHunk) {
52
+ continue
53
+ } else if (line.charAt(0) === "-") {
54
+ out.push({ kind: "removed", oldNo: oldAt++, newNo: 0, text: line.substring(1) })
55
+ } else if (line.charAt(0) === "+") {
56
+ out.push({ kind: "added", oldNo: 0, newNo: newAt++, text: line.substring(1) })
57
+ } else if (line.charAt(0) === "\\") {
58
+ out.push({ kind: "note", oldNo: 0, newNo: 0, text: line })
59
+ } else {
60
+ out.push({ kind: "context", oldNo: oldAt++, newNo: newAt++, text: line.substring(1) })
61
+ }
62
+ }
63
+ return out
64
+ }
65
+
66
+ // The removed plus added lines, which is what the title counts.
67
+ function changed(rowList) {
68
+ return rowList.filter(function (r) { return r.kind === "removed" || r.kind === "added" }).length
69
+ }
70
+
71
+ // The file name a title shows for a path.
72
+ function leaf(path) {
73
+ return CopyAs.leaf(path)
74
+ }
@@ -0,0 +1,157 @@
1
+ .pragma library
2
+
3
+ // WCAG 2.1 relative luminance, so a test can assert a ratio rather than an eye judging a screenshot.
4
+ function channel(c) {
5
+ return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)
6
+ }
7
+
8
+ function luminance(r, g, b) {
9
+ return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b)
10
+ }
11
+
12
+ // Sample input: "#c8ccd0"
13
+ function parse(hex) {
14
+ var s = String(hex).replace("#", "")
15
+ if (s.length === 8)
16
+ s = s.substring(2)
17
+ return [parseInt(s.substr(0, 2), 16) / 255,
18
+ parseInt(s.substr(2, 2), 16) / 255,
19
+ parseInt(s.substr(4, 2), 16) / 255]
20
+ }
21
+
22
+ function over(fg, alpha, bg) {
23
+ var f = parse(fg)
24
+ var b = parse(bg)
25
+ return [f[0] * alpha + b[0] * (1 - alpha),
26
+ f[1] * alpha + b[1] * (1 - alpha),
27
+ f[2] * alpha + b[2] * (1 - alpha)]
28
+ }
29
+
30
+ function ratioOf(a, b) {
31
+ var la = luminance(a[0], a[1], a[2])
32
+ var lb = luminance(b[0], b[1], b[2])
33
+ var hi = Math.max(la, lb)
34
+ var lo = Math.min(la, lb)
35
+ return (hi + 0.05) / (lo + 0.05)
36
+ }
37
+
38
+ function ratio(fgHex, bgHex) {
39
+ return ratioOf(parse(fgHex), parse(bgHex))
40
+ }
41
+
42
+ function pad2(n) {
43
+ return n < 16 ? "0" + n.toString(16) : n.toString(16)
44
+ }
45
+
46
+ function hexOf(rgb) {
47
+ return "#" + pad2(Math.round(Math.max(0, Math.min(1, rgb[0])) * 255))
48
+ + pad2(Math.round(Math.max(0, Math.min(1, rgb[1])) * 255))
49
+ + pad2(Math.round(Math.max(0, Math.min(1, rgb[2])) * 255))
50
+ }
51
+
52
+ function mix(a, b, t) {
53
+ return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t]
54
+ }
55
+
56
+ // Keep hue; walk lightness toward black or white until WCAG AA (or minRatio) holds.
57
+ function ensureRatio(fgHex, bgHex, minRatio) {
58
+ var need = minRatio > 0 ? minRatio : 4.5
59
+ if (ratio(fgHex, bgHex) >= need)
60
+ return String(fgHex)
61
+ var fg = parse(fgHex)
62
+ var bg = parse(bgHex)
63
+ var toward = luminance(bg[0], bg[1], bg[2]) > 0.179 ? [0, 0, 0] : [1, 1, 1]
64
+ var lo = 0
65
+ var hi = 1
66
+ var best = toward
67
+ for (var i = 0; i < 18; i++) {
68
+ var mid = (lo + hi) / 2
69
+ var cand = mix(fg, toward, mid)
70
+ if (ratioOf(cand, bg) >= need) {
71
+ best = cand
72
+ hi = mid
73
+ } else {
74
+ lo = mid
75
+ }
76
+ }
77
+ if (ratioOf(best, bg) < need)
78
+ best = toward
79
+ return stepped(hexOf(best), bgHex, need, toward)
80
+ }
81
+
82
+ // Rounding to 8 bits can land just under the ratio asked for, 2.99 for 3 on 20 of the 22 stock palettes.
83
+ function stepped(hex, bgHex, need, toward) {
84
+ var c = parse(hex)
85
+ var step = toward[0] > 0.5 ? 1 / 255 : -1 / 255
86
+ var bg = parse(bgHex)
87
+ for (var i = 0; i < 255; i++) {
88
+ if (ratioOf(c, bg) >= need)
89
+ break
90
+ // Each channel clamps on its own, so one already at the extreme cannot carry the others out.
91
+ var next = [clamp(c[0] + step), clamp(c[1] + step), clamp(c[2] + step)]
92
+ // A step that moves no channel at all is the extreme itself, and there is nowhere further to go.
93
+ if (hexOf(next) === hexOf(c))
94
+ break
95
+ c = next
96
+ }
97
+ return hexOf(c)
98
+ }
99
+
100
+ function clamp(v) {
101
+ return v < 0 ? 0 : (v > 1 ? 1 : v)
102
+ }
103
+
104
+ // The seven tag names, member for member with src/backend/tags.rs NAMES and ui/js/Tags.js NAMES.
105
+ var TAG_NAMES = ["Red", "Orange", "Yellow", "Green", "Blue", "Purple", "Gray"];
106
+ var TAG_ROLES = { Red: "red", Orange: "orange", Yellow: "yellow", Green: "green",
107
+ Blue: "blue", Purple: "magenta", Gray: "dark_foreground" };
108
+ var TAG_HUES = { Red: [335, 12], Orange: [8, 45], Yellow: [28, 70],
109
+ Green: [80, 170], Blue: [195, 255], Purple: [250, 335] };
110
+
111
+ // Each role lifted to 3:1 on the listing ground and the menu ground, plus the digit fallback, decided once per theme load.
112
+ function tagTheme(found, bg, surface) {
113
+ var colors = {};
114
+ var menuColors = {};
115
+ var seen = {};
116
+ var fallback = false;
117
+ for (var i = 0; i < TAG_NAMES.length; i++) {
118
+ var name = TAG_NAMES[i];
119
+ var hex = (found || {})[TAG_ROLES[name]] || "";
120
+ if (!hex) {
121
+ fallback = true;
122
+ } else {
123
+ var key = String(hex).toLowerCase();
124
+ if (seen[key]) fallback = true;
125
+ seen[key] = true;
126
+ }
127
+ colors[name] = hex ? ensureRatio(hex, bg, 3) : "";
128
+ menuColors[name] = hex ? ensureRatio(hex, surface, 3) : "";
129
+ if (name !== "Gray" && hex) {
130
+ var rgb = parse(hex);
131
+ var hi = Math.max(rgb[0], rgb[1], rgb[2]);
132
+ var lo = Math.min(rgb[0], rgb[1], rgb[2]);
133
+ // Almost no chroma is a grey whatever its name claims.
134
+ if (hi === 0 || (hi - lo) / hi < 0.12) fallback = true;
135
+ else if (!tagHueHolds(rgb, TAG_HUES[name])) fallback = true;
136
+ }
137
+ }
138
+ return { colors: colors, menuColors: menuColors, fallback: fallback };
139
+ }
140
+
141
+ // A hue inside a window that wraps past red, so one comparison covers both ends.
142
+ function tagHueHolds(rgb, window) {
143
+ var hi = Math.max(rgb[0], rgb[1], rgb[2]);
144
+ var lo = Math.min(rgb[0], rgb[1], rgb[2]);
145
+ var delta = hi - lo;
146
+ var hue = 0;
147
+ if (delta > 0) {
148
+ if (hi === rgb[0]) {
149
+ hue = 60 * (((rgb[1] - rgb[2]) / delta + 6) % 6);
150
+ } else if (hi === rgb[1]) {
151
+ hue = 60 * ((rgb[2] - rgb[0]) / delta + 2);
152
+ } else {
153
+ hue = 60 * ((rgb[0] - rgb[1]) / delta + 4);
154
+ }
155
+ }
156
+ return window[0] <= window[1] ? hue >= window[0] && hue <= window[1] : hue >= window[0] || hue <= window[1];
157
+ }
@@ -0,0 +1,42 @@
1
+ .pragma library
2
+
3
+ // Sample input: read(window, window.contentItem, /^(DialogButton)_QML/, {}) === {focus: {kind: "DialogButton", via: "owner", ...}, controls: [{kind: "DialogButton", name: "Open", x: 900, ...}]}.
4
+ // The cohesion captures' reader, shared by the window and the picker: every visible control that draws focus, its window box and its states.
5
+ function read(quick, top, kinds, alias) {
6
+ var out = []
7
+ function kindOf(item) { var m = String(item).match(kinds); return m ? (alias[m[1]] || m[1]) : "" }
8
+ function pointerFlag(item, name) {
9
+ if (item[name] !== undefined) return item[name]
10
+ var handler = name === "hovered" ? "QQuickHoverHandler" : "QQuickTapHandler"
11
+ var data = item.data || []
12
+ for (var i = 0; i < data.length; i++)
13
+ if (data[i] && String(data[i]).indexOf(handler) === 0) return data[i][name]
14
+ return undefined
15
+ }
16
+ function entry(item, kind, via) {
17
+ var p = item.mapToItem(null, 0, 0)
18
+ var hovered = pointerFlag(item, "hovered"), pressed = pointerFlag(item, "pressed")
19
+ return {kind: kind, name: String(item.label || item.accessName || item.title || item.objectName || item.name || item.glyph || ""),
20
+ x: Math.round(p.x), y: Math.round(p.y), w: Math.round(item.width), h: Math.round(item.height),
21
+ focused: !!(item.activeFocus || item.focused === true || item.keyboardFocused === true),
22
+ hovered: hovered === true, pressed: pressed === true,
23
+ hoverable: hovered !== undefined, pressable: pressed !== undefined,
24
+ enabled: !!item.enabled && item.available !== false && item.inputLive !== false,
25
+ value: item.value !== undefined ? String(item.value) : "",
26
+ primary: item.primary === true, destructive: item.destructive === true, member: item.setMember === true, via: via}
27
+ }
28
+ function walk(item) {
29
+ if (!item || !item.visible || item.opacity <= 0) return
30
+ var kind = kindOf(item)
31
+ if (kind) out.push(entry(item, kind, ""))
32
+ for (var i = 0; i < item.children.length; i++) walk(item.children[i])
33
+ }
34
+ walk(top)
35
+ var item = quick ? quick.activeFocusItem : null, owner = item
36
+ while (owner && !kindOf(owner)) owner = owner.parent
37
+ // A dialog that keeps the keyboard on its own scope names its focused control through that control's focused flag.
38
+ var focus = owner ? entry(owner, kindOf(owner), "owner") : null
39
+ for (var j = 0; !focus && j < out.length; j++) if (out[j].focused) focus = Object.assign({}, out[j], {via: "flag"})
40
+ if (!focus && item) focus = entry(item, String(item).split("(")[0], "item")
41
+ return JSON.stringify({focus: focus, controls: out})
42
+ }
@@ -0,0 +1,52 @@
1
+ .pragma library
2
+
3
+ // The convert popup's own two decisions: which format, and whether to strip. The destination name is
4
+ // built here because the popup is what decides it; the wire carries no format field at all, since
5
+ // ImageMagick reads the codec off the destination's extension.
6
+
7
+ // What the popup offers. Every one of these is in this box's ImageMagick delegate list.
8
+ var FORMATS = ["jpg", "png", "webp", "avif", "heic", "tiff", "bmp"]
9
+
10
+ // The canvas's own suffixes: a real conversion is "(converted)", a same-format strip is "(stripped)".
11
+ var CONVERTED = "(converted)"
12
+ var STRIPPED = "(stripped)"
13
+
14
+ function extensionOf(name) {
15
+ var cut = String(name).lastIndexOf(".")
16
+ return cut > 0 ? String(name).substring(cut + 1).toLowerCase() : ""
17
+ }
18
+
19
+ function stemOf(name) {
20
+ var cut = String(name).lastIndexOf(".")
21
+ return cut > 0 ? String(name).substring(0, cut) : String(name)
22
+ }
23
+
24
+ // Never the file it came from: an interrupted in-place strip destroys the file it was given, so no
25
+ // in-place option is offered at all.
26
+ function destName(name, format) {
27
+ var want = String(format).replace(/^\./, "").toLowerCase()
28
+ var word = want === extensionOf(name) ? STRIPPED : CONVERTED
29
+ return stemOf(name) + " " + word + "." + want
30
+ }
31
+
32
+ // The format row that starts selected: the canvas shows JPEG picked on a PNG, so it is the first
33
+ // format that is not the one the file already is.
34
+ function defaultFormat(name) {
35
+ var current = extensionOf(name)
36
+ for (var i = 0; i < FORMATS.length; i++) {
37
+ if (FORMATS[i] !== current) {
38
+ return FORMATS[i]
39
+ }
40
+ }
41
+ return FORMATS[0]
42
+ }
43
+
44
+ function destination(source, format) {
45
+ var parent = source.path.substring(0, source.path.lastIndexOf("/") + 1)
46
+ return parent + destName(source.name, format)
47
+ }
48
+
49
+ function matchesReply(source, requestId, reply) {
50
+ return source !== null && reply.requestId === requestId
51
+ && reply.source === source.path
52
+ }
@@ -0,0 +1,52 @@
1
+ .pragma library
2
+
3
+ .import "Format.js" as Format
4
+
5
+ // Sample input: "/home/gm/archive.tar.gz"; every Copy as variant covers the
6
+ // whole selection, one path per line, as plain text.
7
+ function leaf(path) {
8
+ var text = String(path)
9
+ var cut = text.lastIndexOf("/")
10
+ return cut < 0 ? text : text.substring(cut + 1)
11
+ }
12
+
13
+ // Sample input: "/home/gm/archive.tar.gz" -> "archive.tar"; a dotfile keeps
14
+ // its whole name, so ".bashrc" never becomes an empty stem.
15
+ function stem(path) {
16
+ var name = leaf(path)
17
+ var start = name.charAt(0) === "." ? 1 : 0
18
+ var dot = name.lastIndexOf(".")
19
+ if (dot <= start)
20
+ return name
21
+ return name.substring(0, dot)
22
+ }
23
+
24
+ // Sample input: "/home/gm/a.txt" -> "/home/gm"; "/" stays "/".
25
+ function dirpath(path) {
26
+ var text = String(path)
27
+ var cut = text.lastIndexOf("/")
28
+ if (cut < 0)
29
+ return text
30
+ return cut === 0 ? "/" : text.substring(0, cut)
31
+ }
32
+
33
+ function one(path, kind) {
34
+ if (kind === "name")
35
+ return leaf(path)
36
+ if (kind === "stem")
37
+ return stem(path)
38
+ if (kind === "dirpath")
39
+ return dirpath(path)
40
+ if (kind === "uri")
41
+ return Format.fileUri(String(path))
42
+ if (kind === "quoted")
43
+ return "'" + String(path).split("'").join("'\\''") + "'"
44
+ return String(path)
45
+ }
46
+
47
+ function lines(paths, kind) {
48
+ var out = []
49
+ for (var i = 0; i < paths.length; i++)
50
+ out.push(one(paths[i], kind))
51
+ return out.join("\n")
52
+ }
@@ -0,0 +1,178 @@
1
+ .pragma library
2
+
3
+ // The chrome's breadcrumb: one path as the pieces a click can land on, and what fits when the bar is
4
+ // narrower than the path. Split out of ui/js/Nav.js, which walks the tree; this only draws where it is.
5
+
6
+ // Issue 45: the chrome's path as the pieces a click can land on. text is what is drawn, including
7
+ // the separator that follows it, so the pieces concatenate to exactly the one line they replace;
8
+ // path is the directory the piece names, which is what ui/ChromeBar.qml hands to pathEntered. The
9
+ // home test is the whole-component one, home itself or home and a separator, which ui/js/Format.js
10
+ // tilde and ui/js/Search.js scopeRoot now both make too: a sibling like /home/gmx is not inside home.
11
+ function crumbs(path, home, rootAlias) {
12
+ var text = String(path)
13
+ if (text === "trash:///") return [{ text: text, path: text, last: true }]
14
+ var aliasRoot = rootAlias ? cleanRoot(rootAlias.path) : ""
15
+ var aliasLabel = rootAlias ? String(rootAlias.label || "") : ""
16
+ var aliased = aliasRoot.length > 0 && aliasLabel.length > 0 && inside(text, aliasRoot)
17
+ if (aliased) {
18
+ // The label is one crumb even when it holds a "/"; only the real path's suffix adds separators and targets.
19
+ var aliasedParts = text.substring(aliasRoot.length).split("/").filter(function (part) { return part.length > 0 })
20
+ var aliasedOut = [{ text: aliasLabel + (aliasedParts.length > 0 ? "/" : ""),
21
+ path: aliasRoot, last: false }]
22
+ var aliasedWalked = aliasRoot
23
+ for (var a = 0; a < aliasedParts.length; a++) {
24
+ aliasedWalked += "/" + aliasedParts[a]
25
+ aliasedOut.push({ text: aliasedParts[a] + "/", path: aliasedWalked, last: false })
26
+ }
27
+ var aliasedEnd = aliasedOut[aliasedOut.length - 1]
28
+ if (aliasedOut.length > 1)
29
+ aliasedEnd.text = aliasedEnd.text.substring(0, aliasedEnd.text.length - 1)
30
+ aliasedEnd.last = true
31
+ return aliasedOut
32
+ }
33
+
34
+ var base = String(home)
35
+ var inHome = base.length > 0 && inside(text, base)
36
+ var display = inHome ? "~" + text.substring(base.length) : text
37
+ var parts = display.split("/")
38
+ var walked = inHome ? base : ""
39
+ // The leading "~" and the leading "/" are each a crumb of their own: one names home and the
40
+ // other names the root, and neither is a component the split hands back.
41
+ var out = [{ text: parts.length > 1 ? parts[0] + "/" : parts[0],
42
+ path: walked.length > 0 ? walked : "/", last: false }]
43
+ for (var i = 1; i < parts.length; i++) {
44
+ if (parts[i].length === 0) {
45
+ continue
46
+ }
47
+ walked = walked + "/" + parts[i]
48
+ out.push({ text: parts[i] + "/", path: walked, last: false })
49
+ }
50
+ // Only a crumb with another after it carries a separator, so the last one gives its own back.
51
+ var end = out[out.length - 1]
52
+ if (out.length > 1) {
53
+ end.text = end.text.substring(0, end.text.length - 1)
54
+ }
55
+ end.last = true
56
+ return out
57
+ }
58
+
59
+ function cleanRoot(path) {
60
+ var text = String(path || "")
61
+ while (text.length > 1 && text.charAt(text.length - 1) === "/")
62
+ text = text.substring(0, text.length - 1)
63
+ return text
64
+ }
65
+
66
+ function inside(path, root) {
67
+ return path === root || path.indexOf(root + "/") === 0
68
+ }
69
+
70
+ // Issue 237: the deepest remembered display root wins, so nested WebDAV spaces on one host stay distinct.
71
+ function aliasAt(path, aliases) {
72
+ var text = String(path || "")
73
+ var best = null
74
+ for (var i = 0; aliases && i < aliases.length; i++) {
75
+ var root = cleanRoot(aliases[i].path)
76
+ if (root.length > 0 && inside(text, root) && (!best || root.length > best.path.length))
77
+ best = { path: root, label: String(aliases[i].label || ""), key: aliases[i].key }
78
+ }
79
+ return best && best.label.length > 0 ? best : null
80
+ }
81
+
82
+ function rememberAlias(aliases, path, label, key) {
83
+ var root = cleanRoot(path)
84
+ var name = String(label || "")
85
+ if (root.length === 0 || name.length === 0)
86
+ return aliases || []
87
+ var id = String(key || root)
88
+ var out = []
89
+ for (var i = 0; aliases && i < aliases.length; i++) {
90
+ if (aliases[i].key !== id && cleanRoot(aliases[i].path) !== root)
91
+ out.push(aliases[i])
92
+ }
93
+ out.push({ path: root, label: name, key: id })
94
+ return out
95
+ }
96
+
97
+ // Only a persisted source may rename an alias; a live mount's generated label is not a saved name.
98
+ function labelsByKey(entries, keyFor) {
99
+ var out = {}
100
+ for (var i = 0; entries && i < entries.length; i++) {
101
+ var address = entries[i].uri || entries[i].path
102
+ if (entries[i].saved === true && address && entries[i].label)
103
+ out[keyFor(address)] = entries[i].label
104
+ }
105
+ return out
106
+ }
107
+
108
+ // A saved-place rename changes the visible root without changing a real path or navigation target.
109
+ function relabelAliases(aliases, labels) {
110
+ var changed = false
111
+ var out = []
112
+ for (var i = 0; aliases && i < aliases.length; i++) {
113
+ var name = labels && labels[aliases[i].key] ? String(labels[aliases[i].key]) : aliases[i].label
114
+ changed = changed || name !== aliases[i].label
115
+ out.push(name === aliases[i].label ? aliases[i]
116
+ : { path: aliases[i].path, label: name, key: aliases[i].key })
117
+ }
118
+ return changed ? out : (aliases || [])
119
+ }
120
+
121
+ // Below this a leaf gives up more to the ellipsis than the ellipsis saves, so it is drawn whole.
122
+ var LEAF_FLOOR = 6
123
+
124
+ // What the crumbs before it leave the leaf, in characters.
125
+ function leafRoom(list, budget) {
126
+ return budget - (crumbChars(list) - list[list.length - 1].text.length)
127
+ }
128
+
129
+ // Chrome rule 2 collapses whole crumbs, but the leaf is the one crumb that cannot be dropped: when
130
+ // even it does not fit, it takes the ellipsis in its own middle rather than a cut at the strip's edge.
131
+ function elideLeaf(list, budget) {
132
+ var end = list[list.length - 1]
133
+ var room = leafRoom(list, budget)
134
+ if (room >= end.text.length || end.text.length <= LEAF_FLOOR) {
135
+ return list
136
+ }
137
+ // corner: a strip with less room than the floor draws the floor, which is short rather than cut.
138
+ var keep = Math.max(LEAF_FLOOR, room)
139
+ var head = Math.ceil((keep - 1) / 2)
140
+ var tail = keep - 1 - head
141
+ var cut = end.text.substring(0, head) + "\u2026" + (tail > 0 ? end.text.substring(end.text.length - tail) : "")
142
+ return list.slice(0, list.length - 1).concat([{ text: cut, path: end.path, last: true }])
143
+ }
144
+
145
+ // Chrome rule 2: a path too long for the strip reads as its root, one collapsed crumb and the segments nearest you, whole crumbs only, so the marker is a crumb of its own. budget is the strip's width in characters, monospace.
146
+ function fitCrumbs(list, budget) {
147
+ if (list.length < 4 || crumbChars(list) <= budget) {
148
+ return elideLeaf(list, budget)
149
+ }
150
+ var shown = [list[0], { text: "\u2026/", path: "", last: false, elided: true },
151
+ list[list.length - 2], list[list.length - 1]]
152
+ // Whatever room the marker leaves goes back to the crumbs nearest the root, in walking order.
153
+ for (var i = 1; i < list.length - 2; i++) {
154
+ var next = shown.slice()
155
+ next.splice(i, 0, list[i])
156
+ if (crumbChars(next) > budget) {
157
+ break
158
+ }
159
+ shown = next
160
+ }
161
+ // A parent that leaves the leaf less than it needs and less than its floor goes the way the
162
+ // middle went: rule 2 elides whole crumbs, and the leaf is the one that may not be the one to go.
163
+ if (shown.length === 4) {
164
+ var left = leafRoom(shown, budget)
165
+ if (left < shown[3].text.length && left < LEAF_FLOOR) {
166
+ shown = [shown[0], shown[1], shown[3]]
167
+ }
168
+ }
169
+ return elideLeaf(shown, budget)
170
+ }
171
+
172
+ function crumbChars(list) {
173
+ var chars = 0
174
+ for (var i = 0; i < list.length; i++) {
175
+ chars += list[i].text.length
176
+ }
177
+ return chars
178
+ }