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,353 @@
1
+ .pragma library
2
+
3
+ .import "Format.js" as Format
4
+ .import "Thumbs.js" as Thumbs
5
+
6
+ // Whole sentences with "%1" for a value, filled by fill so each translates as one.
7
+ var WORDS = {
8
+ requestedBy: "Requested by %1",
9
+ selectedWithSize: "%1 selected · %2",
10
+ hintsEsc: "%1 · Esc cancel"
11
+ }
12
+
13
+ // The portal request tools/flea-portal puts in FLEA_PICKER, and the answer ui/picker.qml writes
14
+ // back. Everything here is pure so tests/js/picker.js can drive it without a window.
15
+
16
+ // The portal's own response codes, mirrored from tools/flea-portal: 1 is the user's no, and this
17
+ // front end never sends 2, because a window that opened at all can only pick or refuse.
18
+ var RESPONSE_OK = 0
19
+ var RESPONSE_CANCELLED = 1
20
+
21
+ var ALL_FILES = "All files"
22
+
23
+ // The rail's Recent row is a location and not a directory, so it is named by a token no listing
24
+ // path can equal: every path this window holds is absolute, and this one does not start with "/".
25
+ // SendPicker.html draws it first in the rail and draws this word where the path would be.
26
+ var RECENT = "flea:recent"
27
+ var RECENT_LABEL = "Recent"
28
+
29
+ function isRecent(location) {
30
+ return location === RECENT
31
+ }
32
+
33
+ // SendPicker.html draws a chooser row as the name, a 70px size and an 80px date, so the two columns
34
+ // the window's rows also carry are hidden here at every width rather than at some of them.
35
+ var HIDDEN_COLS = ["mode", "kind"]
36
+
37
+ // The chooser's s-step order: only columns it draws, since an order no header can mark has no feedback.
38
+ var SORT_ORDERS = ["name", "size", "mtime"]
39
+
40
+ // Every field defaulted, because a request that arrived short must still open a window.
41
+ function request(text) {
42
+ var read = {}
43
+ try {
44
+ read = JSON.parse(String(text || "{}")) || {}
45
+ } catch (e) {
46
+ read = {}
47
+ }
48
+ return {
49
+ mode: read.mode === "save" || read.mode === "savefiles" ? read.mode : "open",
50
+ title: String(read.title || ""),
51
+ app: String(read.app || ""),
52
+ accept: String(read.accept || ""),
53
+ multiple: read.multiple === true,
54
+ directory: read.directory === true,
55
+ hidden: typeof read.hidden === "boolean" ? read.hidden : undefined,
56
+ folder: String(read.folder || ""),
57
+ file: String(read.file || ""),
58
+ name: String(read.name || ""),
59
+ files: Array.isArray(read.files) ? read.files : [],
60
+ filters: Array.isArray(read.filters) ? read.filters : [],
61
+ current: String(read.current || ""),
62
+ currentIndex: typeof read.currentIndex === "number" ? read.currentIndex : -1
63
+ }
64
+ }
65
+
66
+ // The caller's own title wins; the fallback says what the window is for rather than naming Flea.
67
+ function title(req) {
68
+ if (req.title.length > 0) {
69
+ return req.title
70
+ }
71
+ if (req.mode === "save" || req.mode === "savefiles") {
72
+ return "Save file"
73
+ }
74
+ return req.directory ? "Choose folder" : "Choose file"
75
+ }
76
+
77
+ // Only a portal identity is ever shown here. A host application has none, and inventing one from
78
+ // the window title would put a name the desktop never vouched for under a trusted-looking label.
79
+ function subtitle(req) {
80
+ return req.app.length > 0 ? Format.fill(WORDS.requestedBy, req.app) : ""
81
+ }
82
+
83
+ // The primary button. The count rides on it in the multiple case, which is the board's "Send 3".
84
+ function acceptLabel(req, count) {
85
+ var base = req.accept.length > 0 ? req.accept : defaultAccept(req)
86
+ // The count goes in first and the caller's own text last, so a placeholder in it is never filled in.
87
+ if (req.multiple && count > 1) {
88
+ return "%2 %1".arg(Format.count(count)).arg(base)
89
+ }
90
+ return base
91
+ }
92
+
93
+ function defaultAccept(req) {
94
+ if (req.mode === "save") {
95
+ return "Save"
96
+ }
97
+ if (req.mode === "savefiles" || req.directory) {
98
+ return "Choose folder"
99
+ }
100
+ return "Open"
101
+ }
102
+
103
+ // The footer's left half: what is checked, and what it weighs.
104
+ function statusLine(count, bytes) {
105
+ if (count === 0) {
106
+ return "0 selected"
107
+ }
108
+ return Format.fill(WORDS.selectedWithSize, Format.count(count), Format.size(bytes))
109
+ }
110
+
111
+ // The footer's right half, which says only the keys this mode actually answers.
112
+ function hints(req) {
113
+ if (req.mode === "save") {
114
+ return "Enter save · Esc cancel"
115
+ }
116
+ var pick = req.multiple ? (req.directory ? "Enter open · Space mark folder" : "Space select · Enter open/send") : "Enter open"
117
+ return Format.fill(WORDS.hintsEsc, pick)
118
+ }
119
+
120
+ // The collision review's error line, one template so a placeholder inside the name is never filled in.
121
+ function collisionLine(name) {
122
+ return "%1 already exists here.".arg(name)
123
+ }
124
+
125
+ // Where a name's stem ends: at its last dot, and a leading dot belongs to the stem.
126
+ function stemEnd(name) {
127
+ var dot = String(name).lastIndexOf(".")
128
+ return dot > 0 ? dot : String(name).length
129
+ }
130
+
131
+ // Callout 12: Back, Up, the rail, the list, Filename, the filter, Cancel and the answer; a hidden or disabled stop is skipped.
132
+ function tabOrder(stops) {
133
+ return [].concat(stops.chrome, [stops.rail, stops.view], stops.save, stops.answers)
134
+ .filter(function(item) { return item.visible && item.enabled && item.activeFocusOnTab })
135
+ }
136
+
137
+ // The filter menu's rows: the caller's filters, then All files, which is always explicit. No filters is no
138
+ // dropdown at all, because a chooser with one filter is a chooser with nothing to choose between.
139
+ function chips(req) {
140
+ if (req.filters.length === 0) {
141
+ return []
142
+ }
143
+ var out = []
144
+ for (var i = 0; i < req.filters.length; i++) {
145
+ out.push({ label: String(req.filters[i].label || ""), index: i })
146
+ }
147
+ out.push({ label: ALL_FILES, index: -1 })
148
+ return out
149
+ }
150
+
151
+ // Which filter starts current: the caller's current_filter when it names one of them, else the first.
152
+ function currentChip(req) {
153
+ if (req.filters.length === 0) {
154
+ return -1
155
+ }
156
+ if (req.currentIndex >= 0 && req.currentIndex < req.filters.length) return req.currentIndex
157
+ for (var i = 0; i < req.filters.length; i++) {
158
+ if (String(req.filters[i].label || "") === req.current) {
159
+ return i
160
+ }
161
+ }
162
+ return 0
163
+ }
164
+
165
+ // A mark is a path, never a row number: the board's rule is that a checked identity survives Back
166
+ // and Parent, and a row number rebinds to whatever else lands in that position.
167
+ function marked(marks, path) {
168
+ for (var i = 0; i < marks.length; i++) {
169
+ if (marks[i].path === path) {
170
+ return true
171
+ }
172
+ }
173
+ return false
174
+ }
175
+
176
+ function totalBytes(marks) {
177
+ var sum = 0
178
+ for (var i = 0; i < marks.length; i++) {
179
+ sum += marks[i].bytes
180
+ }
181
+ return sum
182
+ }
183
+
184
+ function paths(marks) {
185
+ var out = []
186
+ for (var i = 0; i < marks.length; i++) {
187
+ out.push(marks[i].path)
188
+ }
189
+ return out
190
+ }
191
+
192
+ function reviewedMarks(previous, reviewed) {
193
+ return reviewed.map(function(item) {
194
+ var old = previous.find(function(mark) { return mark.path === item.path })
195
+ return {path: item.path, bytes: item.bytes, uri: old && old.uri ? old.uri : Format.fileUri(item.path)}
196
+ })
197
+ }
198
+
199
+ // The save name is the one filename a client hands this window, so it is a trust boundary and it
200
+ // gets the rule the rest of the product already applies. Mirrored from src/backend/ops.rs
201
+ // valid_name() and kept identical to it, character for character, so the two cannot drift.
202
+ function validName(name) {
203
+ var text = String(name)
204
+ return text.length > 0 && text !== "." && text !== ".."
205
+ && text.indexOf("/") < 0 && text.indexOf("\0") < 0
206
+ }
207
+
208
+ // What both the strip and the status line say about a name validName() refuses, in ops.rs's words.
209
+ var NAME_REFUSED = "a name cannot be empty, . or .., or contain /"
210
+ // Status lines are whole sentences with placeholders, filled by Format.fill.
211
+ var SAVE_REFUSED = "%1 cannot be used: %2"
212
+ var SAVE_EXISTS = "%1 already exists here. Review it before you continue."
213
+
214
+ // Whole sentences for the selection check, filled by Format.fill; singular and plural are two sentences.
215
+ var NOTES = {
216
+ skippedOne: "Selected %1 of %2. 1 was left out: %3 (%4).",
217
+ skippedMany: "Selected %1 of %2. %3 were left out: %4 (%5) and %6 more."
218
+ }
219
+
220
+ // A name is one token to the wrapper, so its segment joints carry zero-width breaks; zero width keeps one-line draws identical.
221
+ function jointName(name) {
222
+ return String(name).replace(/([._-])/g, "$1\u200b")
223
+ }
224
+
225
+ var DOUBLE_OPEN = "open"
226
+ var DOUBLE_MARK = "mark"
227
+ var DOUBLE_ACCEPT = "accept"
228
+ var DOUBLE_MARK_ACCEPT = "markAccept"
229
+ var DOUBLE_NONE = "none"
230
+
231
+ // Sample input: sameTap("/a/b.txt", "/a/b.txt") answers true, sameTap("/a/b.txt", "/a/c.txt") answers false.
232
+ function sameTap(firstPath, rowPath) {
233
+ return !!rowPath && rowPath === firstPath
234
+ }
235
+
236
+ // Sample input: doubleAction({mode:"open",multiple:false}, {d:false}, "/a/b.txt", "/a/b.txt", []) answers "markAccept"; multiple:true answers "mark" for either mark state.
237
+ function doubleAction(req, row, rowPath, firstPath, marks) {
238
+ if (!row) {
239
+ return DOUBLE_NONE
240
+ }
241
+ if (directory(row)) {
242
+ return DOUBLE_OPEN
243
+ }
244
+ // Save mode and folder requests keep their own rules, so a file double click changes nothing there.
245
+ if (req.mode === "save" || req.directory || req.mode === "savefiles") {
246
+ return DOUBLE_NONE
247
+ }
248
+ // The row path names the file, so a list rebuilt between the taps never marks or sends another row.
249
+ if (!sameTap(firstPath, rowPath)) {
250
+ return DOUBLE_NONE
251
+ }
252
+ return req.multiple ? DOUBLE_MARK : marked(marks, rowPath) ? DOUBLE_ACCEPT : DOUBLE_MARK_ACCEPT
253
+ }
254
+
255
+ // The picker never renames, so Return/Enter still activates and other rename keys stay unhandled.
256
+ function activates(action, key) {
257
+ if (action === "open" || action === "pageForward") {
258
+ return true
259
+ }
260
+ if (action !== "rename") {
261
+ return false
262
+ }
263
+ return key === Qt.Key_Return || key === Qt.Key_Enter
264
+ }
265
+
266
+ function join(dir, name) {
267
+ return dir === "/" ? "/" + name : dir + "/" + name
268
+ }
269
+
270
+ // A row's own identity, which is what a mark holds and what the caller is answered with. A Recent
271
+ // listing's base is "/" and its rows are named by their path under it, so the row's path is that
272
+ // name and never a join onto the location token; see docs/protocol.md "listpaths".
273
+ function rowPath(location, name) {
274
+ return isRecent(location) ? "/" + name : join(location, name)
275
+ }
276
+
277
+ function directory(row) {
278
+ return !!row && (row.d === true || (Format.isSymlink(row.p) && row.i === "folder"))
279
+ }
280
+
281
+ // A launch opens only a view the picker draws; anything else opens the list.
282
+ function rememberedView(stored) {
283
+ return stored === "grid" ? "grid" : "list"
284
+ }
285
+
286
+ // Only a switch that moves the view owes the state file a write.
287
+ function viewSwitch(current, next) {
288
+ return (next === "list" || next === "grid") && next !== current ? next : ""
289
+ }
290
+
291
+ // Visible tiles as listing rows, the same multiplication GridArea.visibleRange does.
292
+ function tileRange(contentY, cellH, tileRows, columns, total) {
293
+ var view = Thumbs.viewport(contentY, cellH, tileRows, Math.max(1, Math.ceil(total / Math.max(1, columns))))
294
+ return {
295
+ first: view.first * columns,
296
+ last: Math.min(total - 1, (view.last + 1) * columns - 1)
297
+ }
298
+ }
299
+
300
+ // One grid step keeps the main grid's edge rule: off its row or past an end stays.
301
+ function gridTarget(index, delta, columns, total) {
302
+ var next = index + delta
303
+ if (next < 0 || next >= total) {
304
+ return Math.max(0, Math.min(total - 1, index))
305
+ }
306
+ if ((delta === -1 && index % columns === 0) || (delta === 1 && next % columns === 0)) {
307
+ return index
308
+ }
309
+ return next
310
+ }
311
+
312
+ // Page steps clamp to the nearer end; single steps refuse instead, see gridTarget.
313
+ function pageTarget(index, delta, total) {
314
+ return Math.max(0, Math.min(total - 1, index + delta))
315
+ }
316
+ // Twice the wider view's screen plus slack, so the screen still fits after the quarter lead.
317
+ var WINDOW_COVER = 2
318
+ var WINDOW_SLACK = 60
319
+ // Sample input: windowSize(10, 4, 5) is 100, windowSize(30, 2, 5) is 120.
320
+ function windowSize(listRows, tileRows, columns) {
321
+ var tiles = Math.max(1, tileRows) * Math.max(1, columns)
322
+ return WINDOW_COVER * Math.max(listRows, tiles) + WINDOW_SLACK
323
+ }
324
+
325
+ function parentOf(path) {
326
+ var cut = String(path).lastIndexOf("/")
327
+ if (cut <= 0) {
328
+ return "/"
329
+ }
330
+ return String(path).substring(0, cut)
331
+ }
332
+
333
+ // The one place a path becomes a URI: xdg-desktop-portal drops anything that is not file://, and
334
+ // omarchy-file-select turns what comes back into a path with GLib, which refuses a bad encoding.
335
+ function uris(list) {
336
+ var out = []
337
+ for (var i = 0; i < list.length; i++) {
338
+ out.push(Format.fileUri(list[i]))
339
+ }
340
+ return out
341
+ }
342
+
343
+ // What tools/flea-portal reads out of the reply file. A refusal carries no URI at all.
344
+ function reply(response, list, filterIndex) {
345
+ if (response !== RESPONSE_OK) {
346
+ return JSON.stringify({ response: response })
347
+ }
348
+ var answer = { response: RESPONSE_OK, uris: list.map(function(item) {
349
+ return typeof item === "string" ? Format.fileUri(item) : item.uri
350
+ }) }
351
+ if (typeof filterIndex === "number") answer.filter = filterIndex
352
+ return JSON.stringify(answer)
353
+ }
@@ -0,0 +1,96 @@
1
+ .pragma library
2
+
3
+ .import "Format.js" as Format
4
+ .import "Menu.js" as Menu
5
+ .import "Nav.js" as Nav
6
+ .import "RailKeys.js" as RailKeys
7
+ .import "Places.js" as Places
8
+ .import "Tabs.js" as Tabs
9
+
10
+ // The sentence a remote favourite answers a new-tab open with, filled by Format.fill.
11
+ var WORDS = {
12
+ opensHere: "%1 opens in this tab only"
13
+ }
14
+
15
+ // MenuAdditions rule 3: the folder menu, opened from a Places or Favorites row and acting on that
16
+ // row's own path. The key carries the path because the rail rebuilds on a five second poll and an
17
+ // index taken when the menu opened can name another row by the time a row inside it is chosen, the
18
+ // same reason ui/js/Mounts.js keys a share's menu by its uri.
19
+ function key(entry, favouriteIndex) {
20
+ return "place:" + favouriteIndex + ":" + entry.path
21
+ }
22
+
23
+ // The hidden list is ui/ViewState.qml "menuHidden", handed in by the caller: it is the one reader
24
+ // that falls back to the shipped defaults, and a list derived any other way is empty before the
25
+ // state file lands, which switched this menu on in a fresh home. Anything else fails closed.
26
+ function entries(entry, favouriteIndex, hidden) {
27
+ if (!Array.isArray(hidden))
28
+ return []
29
+ return Menu.placeEntries({ hiddenActions: hidden, hasRow: true, placeFavourite: favouriteIndex >= 0 })
30
+ }
31
+
32
+ // Every row here takes the path the key carries. Properties is not among them: the dialog snapshots
33
+ // row indices through the backend's own menuaction op, which a place has none of, so the board's
34
+ // sixth row waits for that protocol rather than being faked from the listing's cursor.
35
+ function perform(action, key, sidebar, favourites) {
36
+ // The rail's older key, which only ever carried Remove: kept exactly, identity check included,
37
+ // because it is what a favourite's menu still is while the Places row menu is switched off.
38
+ if (key.indexOf("favourite:") === 0) {
39
+ var end = key.indexOf(":", 10)
40
+ var at = Number(key.substring(10, end))
41
+ if (action !== "removeFavourite") return
42
+ if (JSON.stringify(favourites.records[at]) === key.substring(end + 1)) favourites.remove(at)
43
+ else sidebar.message("Favorites changed; reopen the menu before removing this row.", true)
44
+ return
45
+ }
46
+ var rest = key.substring("place:".length)
47
+ var cut = rest.indexOf(":")
48
+ var index = Number(rest.substring(0, cut))
49
+ var path = rest.substring(cut + 1)
50
+ var pane = sidebar.navigationPane
51
+ if (!pane || path.length === 0)
52
+ return
53
+ if (action === "open") { openPath(path, sidebar, pane); return }
54
+ else if (action === "openTab") Tabs.openNew(pane, path)
55
+ else if (action === "openTerminal") pane.openTerminal(path)
56
+ // The Places row's Copy path row acts on its own path, the way the Locked
57
+ // tile's does: MenuAdditions040 replaced the file menu's row, not this one.
58
+ else if (action === "copypath") pane.performMenu("copypath", 0, [path])
59
+ else if (action === "addFavourite") favourites.add(path, leaf(path))
60
+ else if (action === "removeFavourite") removeAt(sidebar, favourites, index, path)
61
+ }
62
+
63
+ // Open reuses the rail's own activation handoff: focus follows a ready folder or a started listing, and a refused busy open stays on the rail.
64
+ function openPath(path, sidebar, pane) {
65
+ if (pane.listInFlight === true) { Nav.openPlace(pane, path); return }
66
+ sidebar.focusOnOpen = true
67
+ RailKeys.openFrom(pane, path, sidebar)
68
+ }
69
+
70
+ // A favourite is removed by index, so the index is checked against the path the menu was opened on:
71
+ // the rail rebuilds on a five second poll and Favourites can be rewritten by the other front end.
72
+ function removeAt(sidebar, favourites, index, path) {
73
+ var record = favourites.records[index]
74
+ if (record && String(record.path) === path) favourites.remove(index)
75
+ else sidebar.message("Favorites changed; reopen the menu before removing this row.", true)
76
+ }
77
+
78
+ function leaf(path) {
79
+ var cut = String(path).replace(/\/+$/, "").lastIndexOf("/")
80
+ return cut < 0 ? path : path.substring(cut + 1)
81
+ }
82
+
83
+ // A middle click on a Places or Favorites row: its folder in a new tab, the listing's own middle click
84
+ // (ui/js/Tap.js tappedTab). A favourite resolves as ui/Sidebar.qml openFavourite does, and a remote
85
+ // one, which has to mount before it has a path, says so rather than opening somewhere else.
86
+ function openTabAt(sidebar, index) {
87
+ var entry = sidebar.entries[index]
88
+ var pane = sidebar.navigationPane
89
+ if (!entry || !pane || (entry.kind !== "home" && entry.kind !== "favourite"))
90
+ return
91
+ // Places.openEntry with a new-tab port: same record check, message and file:// decode; a remote entry answers through the network port.
92
+ Places.openEntry(entry, { pane: pane,
93
+ opened: function (path) { Tabs.openNew(pane, path) },
94
+ networkHost: function () { sidebar.message(Format.fill(WORDS.opensHere, entry.label), false); return null },
95
+ message: sidebar.message })
96
+ }