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,212 @@
1
+ .pragma library
2
+ .import "Format.js" as Format
3
+ .import "Ops.js" as Ops
4
+ .import "Status.js" as Status
5
+ .import "Swap.js" as Swap
6
+
7
+ // The question a paste or a drop asks before it lands on names that exist, as decisions ui/CollideHost.qml and ui/CollideConfirm.qml wire.
8
+
9
+ // Whole sentences with "%1" for a value, filled by Format.fill so each translates as one; one per count, because the verb changes with it.
10
+ var WORDS = {
11
+ existsOne: "%1 already exists in %2",
12
+ existsMany: "%1 items already exist in %2"
13
+ }
14
+
15
+ // Left to right, the order h, l and Tab walk.
16
+ var BUTTONS = ["cancel", "skip", "keep", "merge", "replace"]
17
+ var LABELS = { cancel: "Cancel", skip: "Skip", keep: "Keep both", merge: "Merge", replace: "Replace" }
18
+ // Where the card opens, and so what a reflexive Enter takes: the one choice that changes nothing already there.
19
+ var START = "keep"
20
+ var EXPLAIN = "Replaced items go to Trash, and Undo restores them."
21
+ // What a transfer carries when nothing collided: any name that appears after the question is refused.
22
+ var NONE = "refuse"
23
+ var WAITING = "A transfer is already waiting on its question; try again once it is answered."
24
+
25
+ // One card geometry for CollideConfirm and FatNamesConfirm, so the two cards keep one size.
26
+ var CARD_REFERENCE_BODY = 13
27
+ var CARD_PAD = 16
28
+ var CARD_CONTENT_BASE = 368
29
+ function cardReferenceScale(bodySmall) { return bodySmall / CARD_REFERENCE_BODY }
30
+ function cardPadding(scale) { return Math.round(CARD_PAD * scale) }
31
+ function cardContentWidth(scale, ratio, buttonsWidth) {
32
+ return Math.max(Math.round(CARD_CONTENT_BASE * scale * ratio), buttonsWidth)
33
+ }
34
+
35
+ // The folder's own name, which is what the title says; the root has no leaf, so it says itself.
36
+ function folderName(dest) {
37
+ var path = String(dest || "")
38
+ var cut = path.lastIndexOf("/")
39
+ var leaf = cut >= 0 ? path.substring(cut + 1) : path
40
+ return leaf.length > 0 ? leaf : "/"
41
+ }
42
+
43
+ // "screenshot.png already exists in Pictures" for one, "3 items already exist in Downloads" for several.
44
+ function title(names, total, dest) {
45
+ if (total === 1 && names.length > 0)
46
+ return Format.fill(WORDS.existsOne, names[0].n, folderName(dest))
47
+ return Format.fill(WORDS.existsMany, Format.count(total), folderName(dest))
48
+ }
49
+
50
+ // The row under the list, empty when every collision is already on it.
51
+ function more(total, shown) {
52
+ return total > shown ? "and " + Format.count(total - shown) + " more" : ""
53
+ }
54
+
55
+ // Only the buttons the card shows take the ring; a hidden Merge never holds it.
56
+ function shownButtons(showMerge) {
57
+ return showMerge === true ? BUTTONS : BUTTONS.filter(function (b) { return b !== "merge" })
58
+ }
59
+
60
+ // h and l stop at the ends like TrashConfirm's pair; Tab and Backtab come round. A focus not in order starts from start.
61
+ function walk(order, focus, key, modifiers, start) {
62
+ var at = order.indexOf(focus)
63
+ if (at < 0)
64
+ at = Math.max(0, order.indexOf(start))
65
+ var last = order.length - 1
66
+ if (key === Qt.Key_H || key === Qt.Key_Left)
67
+ return order[Math.max(0, at - 1)]
68
+ if (key === Qt.Key_L || key === Qt.Key_Right)
69
+ return order[Math.min(last, at + 1)]
70
+ // Shift+Tab reaches a Keys handler as Backtab or as Tab with Shift held, depending on the input path.
71
+ if (key === Qt.Key_Backtab || key === Qt.Key_Tab && (modifiers & Qt.ShiftModifier))
72
+ return order[(at + last) % order.length]
73
+ if (key === Qt.Key_Tab)
74
+ return order[(at + 1) % order.length]
75
+ return order[at]
76
+ }
77
+
78
+ function moved(focus, key, showMerge, modifiers) {
79
+ return walk(shownButtons(showMerge), focus, key, modifiers, START)
80
+ }
81
+
82
+ function activates(key) {
83
+ return key === Qt.Key_Return || key === Qt.Key_Enter || key === Qt.Key_Space
84
+ }
85
+
86
+ // The transfer the card holds, its rows stamped in the numbering they were read in; a menu's is resolved from the menu's own capture.
87
+ function waiting(request, held) {
88
+ return request.menuId ? request : Swap.named(request, held)
89
+ }
90
+
91
+ // One question at a time, open or still in flight: a second is refused out loud rather than replacing the first.
92
+ function refusal(opened, pending) {
93
+ return opened || pending !== null ? WAITING : ""
94
+ }
95
+
96
+ // A refused question ends the wait the same way an answered one does: the card never opens, so nothing stays waiting.
97
+ function droppedPending(where, input) {
98
+ return where === "stale" && (input === "collisions" || input === "mergecollisions")
99
+ }
100
+
101
+ // The question names the same sources the transfer will, in the backend's order: a shelf drag's paths, a menu's selection, paths, rows.
102
+ function question(request, probe, id) {
103
+ var asked = { c: "collisions", id: id, dest: request.dest }
104
+ if (request.fat)
105
+ asked.fat = request.fat
106
+ if (probe && probe.length > 0)
107
+ asked.paths = probe
108
+ else if (request.menuId)
109
+ asked.menuId = request.menuId
110
+ else if (request.paths && request.paths.length > 0)
111
+ asked.paths = request.paths
112
+ else
113
+ asked.rows = request.rows || []
114
+ // Rows are asked about in the numbering the transfer will name, ui/js/Swap.js named().
115
+ if (asked.rows && request.listing !== undefined)
116
+ asked.listing = request.listing
117
+ return asked
118
+ }
119
+
120
+ // The waiting transfer with the answer on it; the id is what lets the backend cover only the names it listed.
121
+ function transfer(request, choice, id) {
122
+ return Object.assign({}, request, { collide: choice, collideId: id })
123
+ }
124
+
125
+ // Paste as links answers on the waiting request like a transfer; rows ride along only when named, so paths-only pastes skip listing checks.
126
+ function link(request, choice, id) {
127
+ var out = { c: "link", op: request.op, paths: request.paths || [],
128
+ dest: request.dest, collide: choice, collideId: id }
129
+ if (request.fat)
130
+ out.fat = request.fat
131
+ if (request.rows && request.rows.length > 0) out.rows = request.rows
132
+ if (request.listing !== undefined) out.listing = request.listing
133
+ return out
134
+ }
135
+
136
+ // After Merge, one walk of the sources against the destination, before anything is written.
137
+ function mergeQuestion(request, probe, id) {
138
+ var asked = { c: "mergecollisions", id: id, dest: request.dest }
139
+ if (probe && probe.length > 0)
140
+ asked.paths = probe
141
+ else if (request.menuId)
142
+ asked.menuId = request.menuId
143
+ else if (request.paths && request.paths.length > 0)
144
+ asked.paths = request.paths
145
+ else
146
+ asked.rows = request.rows || []
147
+ if (asked.rows && request.listing !== undefined)
148
+ asked.listing = request.listing
149
+ return asked
150
+ }
151
+
152
+ // The merge transfer with the second card's answer on it; the id names the walk it answers.
153
+ function mergeTransfer(request, inner, id) {
154
+ return Object.assign({}, request, { collide: "merge", collideId: id, inner: inner })
155
+ }
156
+
157
+ // The second card names the folder it merges into: the one merging folder when it was the only
158
+ // name the first card counted, else the destination, which every other name it lists lands in.
159
+ // Sample input: a first card of trip/ alone gives ".../trip"; trip/ beside a.txt gives the destination.
160
+ function mergeDest(request, outerNames, outerTotal) {
161
+ var folders = (outerNames || []).filter(function (n) { return n.d === true }).map(function (n) { return n.n })
162
+ if (folders.length === 1 && (outerTotal === undefined || outerTotal === 1))
163
+ return String(request.dest).replace(/\/$/, "") + "/" + folders[0]
164
+ return request.dest
165
+ }
166
+
167
+ // The board's merged line as whole sentences, one per count, joined once; the undo hint stays its suffix.
168
+ var MERGED_ONE = "Merged 1 item into %1"
169
+ var MERGED_MANY = "Merged %1 items into %2"
170
+ var MERGED_KEPT = "%1 kept both"
171
+ var MERGED_FAILED = "%1 failed"
172
+ var MERGED_SKIPPED = "%1 skipped"
173
+ function merged(count, keptBoth, leaf, failed, skipped, cancelled, note) {
174
+ var segments = [count === 1 ? MERGED_ONE.replace("%1", leaf) : MERGED_MANY.replace("%1", Format.count(count)).replace("%2", leaf)]
175
+ if (keptBoth > 0) segments.push(MERGED_KEPT.replace("%1", Format.count(keptBoth)))
176
+ if (failed > 0) segments.push(MERGED_FAILED.replace("%1", Format.count(failed)))
177
+ if (skipped > 0) segments.push(MERGED_SKIPPED.replace("%1", Format.count(skipped)))
178
+ if (cancelled) segments.push("cancelled")
179
+ if (count > 0 && String(note || "").length > 0) segments.push(note)
180
+ var line = segments.join(" · ")
181
+ return line + (count > 0 ? Status.undoHint() : "")
182
+ }
183
+
184
+ // The done line off the transferdone line itself, so a refused merge never mislabels the next copy.
185
+ function doneLine(t, r) {
186
+ if (r.into && r.into.length > 0)
187
+ return merged(r.merged || 0, r.keptBoth || 0, r.into, r.failed, r.skipped, r.cancelled, r.note)
188
+ return Ops.transferDone(t, r.ok, r.failed, r.skipped, r.cancelled, r.durable, r.note)
189
+ }
190
+
191
+ // Drops callout 3, the FAT names card: every string is one whole sentence with placeholders for its values.
192
+ var FAT_DEFAULT = "rename"
193
+ var FAT_BUTTONS = { cancel: "Cancel", skip: "Skip them", rename: "Rename and copy" }
194
+ var FAT_TITLE_ONE = "1 name cannot exist on %1 (%2)"
195
+ var FAT_TITLE_MANY = "%1 names cannot exist on %2 (%3)"
196
+ var FAT_NOTE = "%1 refuses : ? * \" < > | and trailing dots or spaces."
197
+ // The mount table's own word as the card spells it; vfat could be any FAT width, so it claims none.
198
+ var FAT_FILESYSTEMS = { exfat: "exFAT", vfat: "FAT", fat: "FAT", msdos: "FAT", fat12: "FAT12", fat16: "FAT16", fat32: "FAT32", ntfs: "NTFS", ntfs3: "NTFS" }
199
+ function filesystemLabel(fstype) {
200
+ return FAT_FILESYSTEMS[String(fstype).toLowerCase()] || String(fstype)
201
+ }
202
+ // One pass over the placeholders, so a value that holds a placeholder or a dollar sign is never read twice.
203
+ function fill(template, values) {
204
+ return template.replace(/%(\d)/g, function (whole, n) { return values[n - 1] })
205
+ }
206
+ function cardTitle(total, volume, fstype) {
207
+ var label = filesystemLabel(fstype)
208
+ return total === 1 ? fill(FAT_TITLE_ONE, [volume, label]) : fill(FAT_TITLE_MANY, [Format.count(total), volume, label])
209
+ }
210
+ function cardNote(fstype) {
211
+ return fill(FAT_NOTE, [filesystemLabel(fstype)])
212
+ }
@@ -0,0 +1,28 @@
1
+ .pragma library
2
+ .import "DirSizes.js" as DirSizes
3
+ .import "Format.js" as Format
4
+
5
+ // The strings an autofit measures, the same ones ui/Row.qml draws.
6
+ // Sample input: ("size", {p: 33188, d: false, s: 18000}) answers "18.0 kB".
7
+ var FIT_KEYS = ["mode", "size", "date", "kind"]
8
+
9
+ function cellText(key, row, kindNames, dirSize) {
10
+ if (key === "mode")
11
+ return Format.permissions(row.p)
12
+ if (key === "size") {
13
+ if (Format.isSymlink(row.p))
14
+ return "link"
15
+ if (!row.d)
16
+ return Format.size(row.s)
17
+ return DirSizes.folderText(dirSize, row)
18
+ }
19
+ if (key === "date")
20
+ return row.m === null ? "--" : Format.date(row.m)
21
+ var text = (kindNames || [])[row.k]
22
+ return text !== undefined ? text : ""
23
+ }
24
+
25
+ // The held index behind one held row, for the dirsize the row would draw.
26
+ function dirSizeFor(state, held, at) {
27
+ return DirSizes.sizeFor(state, held + at)
28
+ }
@@ -0,0 +1,111 @@
1
+ .pragma library
2
+
3
+ // Neighbour-column background menus: a peek's empty space navigates to its DRAWN directory (parent/ancestor or shownChildPath, never pending childPath) and opens the background menu once its rows land.
4
+
5
+ // A trailing slash trimmed except at the root itself.
6
+ // Sample input: trimSlash("/home/gm/") is "/home/gm".
7
+ function trimSlash(path) {
8
+ var text = String(path)
9
+ return text.length > 1 && text.charAt(text.length - 1) === "/" ? text.substring(0, text.length - 1) : text
10
+ }
11
+
12
+ // True when two paths name the same directory, trailing slash aside.
13
+ // Sample input: samePath("/a/", "/a") is true.
14
+ function samePath(a, b) {
15
+ return trimSlash(a) === trimSlash(b)
16
+ }
17
+
18
+ // "" when a background intent may arm, else the busy reason: rejects before any intent is stored, so a refused open never leaves one behind.
19
+ // Sample input: canArm({listInFlight: true}) is "loading".
20
+ function canArm(pane) {
21
+ if (!pane)
22
+ return "no pane"
23
+ if (pane.listInFlight === true)
24
+ return "loading"
25
+ if (pane.trash && (pane.trash.opened === true || pane.trash.confirming === true))
26
+ return "trash"
27
+ if (pane.searchMode && pane.searchMode.length > 0)
28
+ return "search"
29
+ if (pane.collide && (pane.collide.opened === true || pane.collide.pending !== null))
30
+ return "collide"
31
+ if (pane.menuVisible === true)
32
+ return "menu"
33
+ if (pane.menuActions && pane.menuActions.opened === true)
34
+ return "menu"
35
+ if (pane.renamingIndex >= 0 || pane.renamePending === true)
36
+ return "rename"
37
+ if (pane.filterTyping === true)
38
+ return "filter"
39
+ if (pane.selectionBand !== null && pane.selectionBand !== undefined)
40
+ return "band"
41
+ return ""
42
+ }
43
+
44
+ // True when the target is already shown: open the menu where it stands, no navigation.
45
+ // Sample input: directOpen("/a", "/a/") is true.
46
+ function directOpen(target, panePath) {
47
+ return target.length > 0 && samePath(target, panePath)
48
+ }
49
+
50
+ // True when landed rows may open the deferred menu: the pending target names this listing and it succeeded; empty counts because an empty directory is where the menu matters most, while locked, error and loading drop the intent.
51
+ // Sample input: shouldOpen("/a", "/a", "ready") is true.
52
+ function shouldOpen(panePath, pending, listingState) {
53
+ if (!pending || pending.length === 0)
54
+ return false
55
+ if (!samePath(panePath, pending))
56
+ return false
57
+ return listingState === "ready" || listingState === "empty"
58
+ }
59
+
60
+ // A failed listing drops the deferred menu, so no later rows open it.
61
+ function clearPendingBackground(pane) {
62
+ if (!pane)
63
+ return
64
+ pane.pendingBackground = ""
65
+ pane.pendingBackgroundAt = null
66
+ }
67
+
68
+ // The deferred neighbour background, consumed either way so later rows never open it: opens only a successful listing of the drawn target, at the stored point.
69
+ function applyPendingBackground(pane) {
70
+ if (!pane || !pane.pendingBackground || pane.pendingBackground.length === 0)
71
+ return
72
+ var target = pane.pendingBackground
73
+ var at = pane.pendingBackgroundAt
74
+ pane.pendingBackground = ""
75
+ pane.pendingBackgroundAt = null
76
+ if (!shouldOpen(pane.path, target, pane.listingState))
77
+ return
78
+ if (pane.searchMode && pane.searchMode.length > 0)
79
+ return
80
+ if (pane.trash && pane.trash.opened)
81
+ return
82
+ if (at === null || at === undefined)
83
+ return
84
+ pane.openBackgroundMenu(at)
85
+ }
86
+
87
+ // Routes one neighbour background for the columns view: busy refuses before any intent is stored, the shown folder opens its menu where it stands, and any other target navigates with the menu waiting on its rows. Answers opened, navigating, ignored or refused:<reason>.
88
+ // Sample input: routeBackground({path: "/a"}, "/a", {x: 1}, {openBackground: function () {}}) is "opened".
89
+ function routeBackground(pane, base, scenePoint, menu) {
90
+ if (!pane || !base || base.length === 0 || !scenePoint)
91
+ return "ignored"
92
+ var busy = canArm(pane)
93
+ if (busy.length > 0) {
94
+ if (busy === "loading")
95
+ pane.message("A directory is already loading.", false)
96
+ return "refused:" + busy
97
+ }
98
+ if (directOpen(base, pane.path)) {
99
+ menu.openBackground(scenePoint)
100
+ return "opened"
101
+ }
102
+ pane.pendingBackground = base
103
+ pane.pendingBackgroundAt = scenePoint
104
+ pane.open(base)
105
+ if (!pane.listInFlight) {
106
+ pane.pendingBackground = ""
107
+ pane.pendingBackgroundAt = null
108
+ return "refused:not-started"
109
+ }
110
+ return "navigating"
111
+ }
@@ -0,0 +1,298 @@
1
+ .pragma library
2
+
3
+ // Which columns a list row of a given width draws. The name is the one column a file manager
4
+ // cannot do without, so it is the one that never loses: each metadata column drops instead, at
5
+ // the width where keeping it would push the name under its floor. ui/Header.qml and ui/Row.qml
6
+ // both resolve their set here, from the same width, so the header can never head a column the
7
+ // rows below it are not drawing.
8
+
9
+ // The optional columns, widest first, which is the order they drop in. Kind goes first: the row
10
+ // already marks its kind with a glyph and most names carry the extension, so it is the most
11
+ // redundant column as well as the widest. Mode goes last, because it is the permanent column.
12
+ var DROP_ORDER = ["kind", "date", "size", "mode"]
13
+
14
+ // The row width each optional column needs before it is drawn, keyed by column. t carries the
15
+ // tokens ui/Theme.qml resolved: rowPaddingX, gap, iconSize, nameMin, and one width per column.
16
+ // A floor includes every column that outlives it, because they drop in order and a wider column
17
+ // never survives a narrower one, which is what makes the four floors nest.
18
+ function floors(t) {
19
+ // The name's own slot at its floor: the row padding either side, the mark and the gap after it.
20
+ var running = t.rowPaddingX + t.iconSize + t.gap + t.nameMin + t.rowPaddingX
21
+ var out = {}
22
+ for (var i = DROP_ORDER.length - 1; i >= 0; i--) {
23
+ var key = DROP_ORDER[i]
24
+ running += t[key] + t.gap
25
+ out[key] = running
26
+ }
27
+ return out
28
+ }
29
+
30
+ // One boolean per optional column, for a row of this width. hidden is the user's own set (keys
31
+ // "mode"/"size"/"date"/"kind", from qs module ViewState), subtracted from what the width
32
+ // affords: a hidden column never draws, and width still wins over a column the user wants back,
33
+ // so the name cannot be crowded out by a column the pane is too narrow to carry.
34
+ function set(width, t, hidden) {
35
+ var f = floors(t)
36
+ var h = {}
37
+ var list = hidden || []
38
+ for (var i = 0; i < list.length; i++) h[list[i]] = true
39
+ return {
40
+ location: false,
41
+ mode: width >= f.mode && !h["mode"],
42
+ size: width >= f.size && !h["size"],
43
+ date: width >= f.date && !h["date"],
44
+ kind: width >= f.kind && !h["kind"]
45
+ }
46
+ }
47
+
48
+ // DualPane protects its name floor without reserving absent Mode and Kind columns.
49
+ function dualSet(width, t, hidden) {
50
+ var base = 2 * t.rowPaddingX + t.iconSize + t.gap + t.nameMin
51
+ var showSize = (hidden || []).indexOf("size") < 0 && width >= base + t.size
52
+ var showDate = (hidden || []).indexOf("date") < 0
53
+ && width >= base + (showSize ? t.size : 0) + t.date
54
+ return {mode: false, kind: false, location: false, size: showSize, date: showDate}
55
+ }
56
+
57
+ // Recent protects its pane's name floor and reserves every non-hidden metadata width for Location.
58
+ function recentSet(width, t, hidden, dual) {
59
+ var base = 2 * t.rowPaddingX + t.iconSize + t.gap + t.nameMin
60
+ var metadataGap = dual ? 0 : t.gap
61
+ var h = hidden || []
62
+ var showSize = h.indexOf("size") < 0 && width >= base + t.size + metadataGap
63
+ var sizeSlot = showSize ? t.size + metadataGap : 0
64
+ var showDate = h.indexOf("date") < 0 && width >= base + sizeSlot + t.date + metadataGap
65
+ var locationFloor = base + (h.indexOf("size") < 0 ? t.size + metadataGap : 0)
66
+ + (h.indexOf("date") < 0 ? t.date + metadataGap : 0) + t.location + t.gap
67
+ return {mode: false, kind: false,
68
+ size: showSize,
69
+ date: showDate,
70
+ location: width >= locationFloor}
71
+ }
72
+
73
+ // A peeked reply is keyed by what ordered it, so a stale ancestor column never survives the hidden-last toggle: path plus hidden plus hiddenLast.
74
+ // Sample input: peekKey("/a", true, true) is "/a\n11".
75
+ function peekKey(path, hidden, hiddenLast) {
76
+ return String(path) + "\n" + (hidden === true ? "1" : "0") + (hiddenLast === true ? "1" : "0")
77
+ }
78
+
79
+ // The folder's own remembered order a column asks under and its reply echoes: "" for name order, else the key and 1 when descending.
80
+ // Sample input: orderTag("size", true) is "size1", orderTag("", false) is "".
81
+ function orderTag(by, desc) {
82
+ return by ? String(by) + (desc === true ? "1" : "0") : ""
83
+ }
84
+
85
+ // The row count and the folder order join the key only for an outstanding ask, so a resize or a re-sort never orphans a stored column.
86
+ // Sample input: sentKey("/a\n00", 35) is "/a\n00\n35", and sentKey("/a\n00", 35, "size1") is "/a\n00\n35\nsize1".
87
+ function sentKey(key, first, order) {
88
+ return String(key) + "\n" + Math.floor(Number(first)) + (order ? "\n" + String(order) : "")
89
+ }
90
+
91
+ // An ask this view made and still awaits, counted per sentKey (path, flags, row count, order), so another client's reply never lands in its column and a column re-asked in flight lands both replies.
92
+ // Sample input: trackAsk(trackAsk({}, "/a\n10\n35"), "/a\n10\n35") holds that key twice.
93
+ function trackAsk(pending, key) {
94
+ var next = {}
95
+ var src = pending || {}
96
+ for (var k in src) next[k] = src[k]
97
+ next[String(key)] = (next[String(key)] || 0) + 1
98
+ return next
99
+ }
100
+
101
+ // True only for a reply this view asked for; anything else is another client's.
102
+ // Sample input: hasAsk(trackAsk({}, "/a\n10"), "/a\n10") is true.
103
+ function hasAsk(pending, key) {
104
+ return ((pending || {})[String(key)] || 0) > 0
105
+ }
106
+
107
+ // One ask answered or superseded; a new listing drops them all.
108
+ // Sample input: dropAsk(trackAsk({}, "/a\n10"), "/a\n10") holds nothing, and dropAsk of a key asked twice holds it once.
109
+ function dropAsk(pending, key) {
110
+ var next = {}
111
+ var want = String(key)
112
+ var src = pending || {}
113
+ for (var k in src) {
114
+ var left = k === want ? src[k] - 1 : src[k]
115
+ if (left > 0) next[k] = left
116
+ }
117
+ return next
118
+ }
119
+
120
+ // The columns view's count follows the window width, capped by Settings View's limit.
121
+ // Sample input: (899, 5) answers 2.
122
+ var COUNT_4_AT = 1700
123
+ var COUNT_5_AT = 2300
124
+ var COUNT_NARROW_AT = 900
125
+ var COUNT_MIN = 2
126
+ var COUNT_MAX = 5
127
+ // The shipped View limit: a default install holds 3 columns from 900 px up.
128
+ var COUNT_DEFAULT = 3
129
+
130
+ // A stored number clamps to 2 to 5, anything else reads as the shipped default.
131
+ function cappedLimit(limit) {
132
+ if (typeof limit !== "number")
133
+ return COUNT_DEFAULT
134
+ var n = Math.floor(limit)
135
+ if (!(n >= COUNT_MIN) && !(n <= COUNT_MAX))
136
+ return COUNT_DEFAULT
137
+ if (n < COUNT_MIN)
138
+ return COUNT_MIN
139
+ if (n > COUNT_MAX)
140
+ return COUNT_MAX
141
+ return n
142
+ }
143
+
144
+ // One integer for a window of this width; resizing re-lays columns without re-reading.
145
+ function columnCountForWidth(width, limit) {
146
+ var count = width < COUNT_NARROW_AT ? 2 : width < COUNT_4_AT ? 3
147
+ : width < COUNT_5_AT ? 4 : 5
148
+ var cap = cappedLimit(limit)
149
+ if (count > cap)
150
+ count = cap
151
+ if (count < COUNT_MIN)
152
+ count = COUNT_MIN
153
+ return count
154
+ }
155
+
156
+ // Extra columns are ancestors, read with the same viewport-scoped peek as the parent today.
157
+ function ancestorsForCount(count) {
158
+ var n = Math.floor(Number(count))
159
+ if (!(n >= COUNT_MIN))
160
+ return 0
161
+ return Math.min(n, COUNT_MAX) - 2
162
+ }
163
+
164
+ // The parent one step up, with a trailing slash trimmed except at the root itself.
165
+ // Sample input: ancestorParent("/home/") is "/".
166
+ function ancestorParent(path) {
167
+ var text = String(path)
168
+ if (text.length > 1 && text.charAt(text.length - 1) === "/")
169
+ text = text.substring(0, text.length - 1)
170
+ var cut = text.lastIndexOf("/")
171
+ return cut <= 0 ? "/" : text.substring(0, cut)
172
+ }
173
+
174
+ // The nearest distinct ancestors of a path, oldest first, stopping where the climb stops.
175
+ // Sample input: ancestors("/home/gm", 3) is ["/", "/home"].
176
+ function ancestors(path, count) {
177
+ var n = Math.floor(Number(count))
178
+ if (!(n >= 1))
179
+ return []
180
+ var text = String(path)
181
+ if (text.length === 0)
182
+ return []
183
+ if (text.length > 1 && text.charAt(text.length - 1) === "/")
184
+ text = text.substring(0, text.length - 1)
185
+ var near = []
186
+ var cur = text
187
+ for (var i = 0; i < n; i++) {
188
+ var p = ancestorParent(cur)
189
+ if (p === cur || near.indexOf(p) >= 0)
190
+ break
191
+ near.push(p)
192
+ cur = p
193
+ }
194
+ return near.reverse()
195
+ }
196
+
197
+ // True while an ancestor column of this depth names a directory of its own.
198
+ // Sample input: ancestorShown("/home", 2) is false.
199
+ function ancestorShown(path, depth) {
200
+ var d = Math.floor(Number(depth))
201
+ if (!(d >= 1))
202
+ return false
203
+ return ancestors(path, d).length >= d
204
+ }
205
+
206
+ // Sample input: neighbourAsks("/home/gm", 1200, 5) is ["/home"], the shown ancestors oldest first.
207
+ function neighbourAsks(path, width, limit) {
208
+ var want = ancestorsForCount(columnCountForWidth(Number(width), limit))
209
+ if (!(want >= 1))
210
+ return []
211
+ return ancestors(path, want)
212
+ }
213
+
214
+ // Sample input: keepAsks({ drawn: ["/a"] }, ["/a"], "/a/b") answers [{path "/a", again false}, {path "/a/b", again true}] and leaves drawn ["/a", "/a/b"]; again names a column not drawn last refresh.
215
+ function keepAsks(keep, asks, child) {
216
+ var shown = child.length > 0 && asks.indexOf(child) < 0 ? asks.concat([child]) : asks.slice()
217
+ var plan = shown.map(function (path) { return { path: path, again: keep.drawn.indexOf(path) < 0 } })
218
+ keep.drawn = shown
219
+ return plan
220
+ }
221
+
222
+ // ui.json carries whatever a hand edit wrote, so only a finite number is a stored width; anything else keeps the measured one.
223
+ // Sample input: storedNumber("120") is NaN, storedNumber(120.6) is 121.
224
+ function storedNumber(raw) {
225
+ if (typeof raw !== "number" || !isFinite(raw) || raw < 0)
226
+ return NaN
227
+ return Math.round(raw)
228
+ }
229
+
230
+ // ListColumns040 board: a dragged edge clamps to the rails, and a double click fits the
231
+ // widest value the window holds, never a directory-wide scan. Sample input: 9999 clamps.
232
+ var MIN_LIST_WIDTH = 48
233
+ var MAX_LIST_WIDTH = 480
234
+
235
+ // One whole pixel inside the rails, whatever the drag handed in.
236
+ function clampListWidth(px) {
237
+ var n = Math.round(Number(px))
238
+ if (!(n >= 0))
239
+ return MIN_LIST_WIDTH
240
+ if (n < MIN_LIST_WIDTH)
241
+ return MIN_LIST_WIDTH
242
+ if (n > MAX_LIST_WIDTH)
243
+ return MAX_LIST_WIDTH
244
+ return n
245
+ }
246
+
247
+ // The widest held cell, clamped; an empty window keeps the column it has, so a fit can narrow as well as widen.
248
+ function autofitWidth(widths, fallback) {
249
+ var cells = widths || []
250
+ if (cells.length === 0)
251
+ return clampListWidth(fallback)
252
+ var best = MIN_LIST_WIDTH
253
+ for (var i = 0; i < cells.length; i++) {
254
+ var w = Math.round(Number(cells[i]))
255
+ if (w >= 0 && w > best)
256
+ best = w
257
+ }
258
+ return clampListWidth(best)
259
+ }
260
+
261
+ function names(s) {
262
+ var out = ["name"]
263
+ if (s.location) out.push("location")
264
+ for (var i = DROP_ORDER.length - 1; i >= 0; i--) {
265
+ var key = DROP_ORDER[i]
266
+ if (s[key])
267
+ out.push(key)
268
+ }
269
+ return out.join(",")
270
+ }
271
+
272
+ // An unanswered folder keeps the old column by data, never by picture.
273
+ // Sample input: folderDataHold(true, false) is true.
274
+ function folderDataHold(cursorIsDir, answered) {
275
+ return cursorIsDir === true && answered !== true
276
+ }
277
+
278
+ // A file load needs a real file row: null never loads and a folder waits by data.
279
+ // Sample input: isFileRow({d: false}) is true.
280
+ function isFileRow(row) {
281
+ return row !== null && row !== undefined && row.d !== true
282
+ }
283
+
284
+ // A landed peek shows the cursor folder while it is still the one waiting.
285
+ // Sample input: showFolderOnPeek("/a", "/b", true) is true.
286
+ function showFolderOnPeek(childPath, shownChildPath, answered) {
287
+ return answered === true && childPath.length > 0 && childPath !== shownChildPath
288
+ }
289
+
290
+ // A data-held empty folder lands settled, the whole frame the picture hold revealed.
291
+ // Sample input: shouldSettleHero(true, "/a", "/a", false, 0) is true.
292
+ function shouldSettleHero(cursorIsDir, path, childPath, readFailed, rowCount) {
293
+ if (cursorIsDir !== true || readFailed === true)
294
+ return false
295
+ if (String(path) !== String(childPath))
296
+ return false
297
+ return Math.floor(Number(rowCount)) === 0
298
+ }