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
package/ui/MenuRow.qml ADDED
@@ -0,0 +1,351 @@
1
+ // Bound: the brand-mark Components below read this row's root, and are only ever built by this row's own Loaders.
2
+ pragma ComponentBehavior: Bound
3
+
4
+ import QtQuick
5
+ import Quickshell
6
+ import qs.Commons
7
+ import "." as Flea
8
+ import "js/Keymap.js" as Keymap
9
+ import "js/Menu.js" as Menu
10
+
11
+ // One context-menu row: the glyph slot, the label, and the disclosure a submenu row carries.
12
+ Item {
13
+ id: root
14
+
15
+ // {label, action, glyph, danger?, submenu?} or {separator: true}; see ui/ContextMenu.qml's buildEntries.
16
+ property var entry: ({})
17
+ property bool current: false
18
+ // A pick list's chosen row, drawn as the canvas draws the convert popup and the share list:
19
+ // accent ink over an accent tint, where a plain menu row only takes the foreground lift below.
20
+ property bool picked: false
21
+
22
+ signal activated()
23
+ readonly property bool pressed: tap.pressed
24
+ // The parent owns the cursor, so a pointer that moves onto the row asks for it; a menu opened under a resting pointer asks nothing, or Enter would fire the pointer's row (0d626ed).
25
+ signal pointerMoved()
26
+ // For a parent that lights the pointer's row without moving its own cursor, as ui/ShareBrowser.qml does.
27
+ readonly property bool hovered: pointer.hovered
28
+ // For ui/Ipc.qml's contextMenuRowProbe: whether the pointer is over this row and where, before a test judges a move.
29
+ function probe() { return pointer.hovered + " " + Math.round(pointer.point.scenePosition.x) + " " + Math.round(pointer.point.scenePosition.y) + " " + Math.round(pointer.restingAt.x) + " " + Math.round(pointer.restingAt.y) }
30
+ // The scene point (despite the name) the host's rows or ground last saw, or -1 when unseen since it opened; the host owns it.
31
+ property point lastPointerGlobal: Qt.point(-1, -1)
32
+ // A first report is motion only a pixel or more from a point the host saw: Qt rounds the point a ground takes on appearing under the pointer.
33
+ function awayFrom(position, x, y) { return x >= 0 && (Math.abs(position.x - x) >= 1 || Math.abs(position.y - y) >= 1) }
34
+ signal pointerSeen(point at)
35
+
36
+ readonly property bool available: root.entry.disabled !== true
37
+ readonly property bool isSeparator: root.entry.separator === true
38
+ // Menu.hasSubmenu and not a local test, because a local one read submenu === true and the menu sets an array.
39
+ readonly property bool isSubmenu: Menu.hasSubmenu(root.entry)
40
+ // A danger row takes the theme's error role for both its mark and its label, never a hardcoded red.
41
+ readonly property bool danger: root.entry.danger === true
42
+ // Unavailable app rows use the theme's error role without a state word (GM 2026-10-29).
43
+ readonly property bool errored: root.entry.errored === true
44
+ // The key this row's action answers to, right-aligned per Menus.html. Derived from keys.toml
45
+ // through the generated map, so an unbound action leaves the slot empty rather than guessing.
46
+ // Empty with the Menus section's hints row off, which takes the slot's width with it.
47
+ readonly property string hint: root.isSeparator ? "" : root.entry.hint !== undefined ? root.entry.hint
48
+ : ViewState.keyHints ? Keymap.hintFor(root.entry.action) : ""
49
+ // A Tags flyout row's box and swatch are built only for those rows (ui/TagMenuMark.qml), so every other row builds none.
50
+ property var tagItem: null
51
+ function mountTag() {
52
+ if (root.entry.tagRow === undefined || root.tagItem !== null) return
53
+ root.tagItem = Qt.createComponent("TagMenuMark.qml").createObject(root, { row: root, mark: markSlot, hint: hintText })
54
+ }
55
+ Component.onCompleted: root.mountTag()
56
+ onEntryChanged: root.mountTag()
57
+ readonly property color markColor: root.errored ? Theme.color.error
58
+ : !root.available ? Theme.color.mutedFrame : root.danger ? Theme.color.error
59
+ : root.picked ? Theme.color.accent : Theme.color.mutedFrame
60
+ readonly property color labelColor: root.errored ? Theme.color.error
61
+ : !root.available ? Theme.color.muted : root.danger ? Theme.color.error
62
+ : root.entry.labelColor !== undefined ? root.entry.labelColor
63
+ : root.picked ? Theme.color.accent : Theme.color.foreground
64
+
65
+ // The hover lift Row.qml uses, so a menu row and a list row read alike.
66
+ readonly property real hoverOpacity: Theme.washHover
67
+ // The rail's mount-status square and the gap the Update Flea board puts between it and the version.
68
+ readonly property int statusSquareSize: 6
69
+ readonly property int statusSquareGap: 7
70
+ // Menus.html resolves the separator to rowGap + hairline, 10 px at base size 14.
71
+ readonly property int separatorHeight: Theme.spacing.gap + Theme.spacing.hairline
72
+ readonly property real separatorOpacity: 0.4
73
+
74
+ // Every menu row uses the listing's own mark slot and row height, so a rail menu reads as the main menu.
75
+ readonly property int slotSize: Theme.markSize
76
+ // OpenWith.html: an application's own Icon= rides in the mark slot, full colour and no plate.
77
+ // The ladder is AppLibrary.qml's iconSource: the backend's app and device index has already
78
+ // answered with a path where it could, and only a name it could not place reaches the themed
79
+ // lookup here. Where that service falls back to application-x-executable, the board rules the
80
+ // muted app-window glyph instead, so an unresolved name leaves the mark below standing.
81
+ readonly property string appIcon: root.entry.icon !== undefined ? String(root.entry.icon) : ""
82
+ readonly property string appIconSource: root.appIcon.length === 0 ? ""
83
+ : root.appIcon.indexOf("file://") === 0 ? root.appIcon
84
+ : root.appIcon.charAt(0) === "/" ? Util.fileUrl(root.appIcon)
85
+ : Quickshell.iconPath(root.appIcon, true)
86
+ // That board draws the mark at 16 of the slot's 19 units, where a stroked glyph takes the slot whole.
87
+ readonly property int appIconSize: Math.round(root.slotSize * 16 / 19)
88
+
89
+ height: root.isSeparator ? root.separatorHeight : Theme.rowHeight
90
+
91
+ // The width this row needs to draw whole, from the layout's own terms below; a wrapped caption takes what the label leaves.
92
+ readonly property real wantedWidth: root.isSeparator ? 0
93
+ : Math.ceil(2 * Theme.spacing.rowPaddingX + root.slotSize + 2 * Theme.spacing.gap + label.implicitWidth
94
+ + (root.entry.hintWrap === true ? 0 : hintText.implicitWidth)
95
+ + (statusSquare.visible ? statusSquare.width + statusSquare.anchors.rightMargin : 0)
96
+ + chevronSlot.width + hintText.anchors.rightMargin)
97
+
98
+ // What this row laid out, read off its items and not off wantedWidth: ui/IpcMenuState.qml's width oracle sums these.
99
+ function parts() {
100
+ if (root.isSeparator) return {separator: true}
101
+ return {separator: false, markLeft: markSlot.anchors.leftMargin, slot: markSlot.width,
102
+ labelLeft: label.anchors.leftMargin, label: label.implicitWidth, labelRight: label.anchors.rightMargin,
103
+ labelTruncated: label.truncated, hint: hintText.implicitWidth, hintWrap: root.entry.hintWrap === true,
104
+ hintRight: hintText.anchors.rightMargin, status: statusSquare.visible ? statusSquare.width + statusSquare.anchors.rightMargin : 0,
105
+ chevron: chevronSlot.width, chevronRight: chevronSlot.anchors.rightMargin}
106
+ }
107
+
108
+ Rectangle {
109
+ objectName: "menuWash"
110
+ anchors.fill: parent
111
+ visible: !root.isSeparator
112
+ // selectedAccentFill already carries the theme's own selected alpha, so the tint is a
113
+ // colour here and an opacity for the plain lift, never both at once.
114
+ color: root.picked ? Style.selectedAccentFill : Theme.color.foreground
115
+ opacity: root.picked ? 1 : (root.current ? root.hoverOpacity : 0)
116
+ }
117
+
118
+ Rectangle {
119
+ visible: root.isSeparator
120
+ anchors.left: parent.left
121
+ anchors.right: parent.right
122
+ anchors.verticalCenter: parent.verticalCenter
123
+ height: Theme.spacing.hairline
124
+ color: Theme.color.mutedFrame
125
+ opacity: root.separatorOpacity
126
+ }
127
+
128
+ // Every action row carries a mark: a menu where some rows are marked and some are not reads broken.
129
+ // The slot sets the label's indent too, which the canvas draws at rowPaddingX + slot + gap.
130
+ // ui/Glyph.qml already caps every mark at its slot, so the slot is the only size to set here.
131
+ Item {
132
+ id: markSlot
133
+ visible: !root.isSeparator
134
+ opacity: root.available ? 1 : Theme.disabledOpacity
135
+ anchors.left: parent.left
136
+ anchors.leftMargin: Theme.spacing.rowPaddingX
137
+ anchors.verticalCenter: parent.verticalCenter
138
+ width: root.slotSize
139
+ height: root.slotSize
140
+
141
+ // A brand mark is a reproduction and takes its own component; every other row is a cut glyph.
142
+ Flea.Glyph {
143
+ anchors.fill: parent
144
+ visible: root.entry.mark === undefined && !appMark.visible && root.entry.tagRow === undefined
145
+ name: root.entry.glyph !== undefined ? root.entry.glyph : "file"
146
+ color: root.markColor
147
+ }
148
+
149
+ // The theme that cannot name the entry leaves the glyph above standing in its muted role.
150
+ Image {
151
+ id: appMark
152
+ anchors.centerIn: parent
153
+ width: root.appIconSize
154
+ height: root.appIconSize
155
+ visible: root.appIconSource.length > 0 && appMark.status === Image.Ready
156
+ source: root.appIconSource
157
+ sourceSize.width: root.appIconSize
158
+ sourceSize.height: root.appIconSize
159
+ fillMode: Image.PreserveAspectFit
160
+ asynchronous: true
161
+ }
162
+
163
+ // Each brand mark is built only on the row whose entry names it: carried hidden by every row, the
164
+ // four were most of a menu's build, and a Loader has no pointer semantics to lose (rows stay eager).
165
+ Loader {
166
+ anchors.centerIn: parent
167
+ active: root.entry.mark === "tailscale"
168
+ sourceComponent: Component {
169
+ Flea.TailscaleMark {
170
+ iconSize: root.slotSize
171
+ color: root.markColor
172
+ }
173
+ }
174
+ }
175
+
176
+ Loader {
177
+ anchors.centerIn: parent
178
+ active: root.entry.mark === "dropbox"
179
+ sourceComponent: Component {
180
+ Flea.DropboxMark {
181
+ iconSize: root.slotSize
182
+ color: root.markColor
183
+ }
184
+ }
185
+ }
186
+
187
+ Loader {
188
+ anchors.centerIn: parent
189
+ active: root.entry.mark === "localsend"
190
+ sourceComponent: Component {
191
+ Flea.LocalSendMark {
192
+ iconSize: root.slotSize
193
+ color: root.markColor
194
+ }
195
+ }
196
+ }
197
+
198
+ // The shelf is Flea's own destination, so it carries Flea's own mark rather than a cut glyph.
199
+ Loader {
200
+ anchors.centerIn: parent
201
+ active: root.entry.mark === "flea"
202
+ sourceComponent: Component {
203
+ Flea.FleaMark {
204
+ width: root.slotSize
205
+ height: root.slotSize
206
+ color: root.markColor
207
+ }
208
+ }
209
+ }
210
+ }
211
+
212
+ // flea-qml: a row that carries a mnemonic draws that letter of its label bold, the same case first
213
+ // and then either case; a letter the label lacks leaves it plain. Sample input: "Path", "p"
214
+ // -> "<b>P</b>ath".
215
+ readonly property string markedLabel: {
216
+ var text = root.entry.label !== undefined ? String(root.entry.label) : ""
217
+ var letter = root.isSeparator || root.entry.mnemonic === undefined ? "" : String(root.entry.mnemonic)
218
+ if (letter.length !== 1) return ""
219
+ var at = text.indexOf(letter)
220
+ if (at < 0) at = text.toLowerCase().indexOf(letter.toLowerCase())
221
+ if (at < 0) return ""
222
+ var escape = function (t) { return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") }
223
+ return escape(text.substring(0, at)) + "<b>" + escape(text.charAt(at)) + "</b>" + escape(text.substring(at + 1))
224
+ }
225
+
226
+ Text {
227
+ id: label
228
+ visible: !root.isSeparator
229
+ anchors.left: markSlot.right
230
+ anchors.leftMargin: Theme.spacing.gap
231
+ anchors.right: root.tagItem !== null && root.entry.tagRow !== undefined ? root.tagItem.left : statusSquare.visible ? statusSquare.left : hintText.left
232
+ anchors.rightMargin: Theme.spacing.gap
233
+ anchors.verticalCenter: parent.verticalCenter
234
+ text: root.markedLabel !== "" ? root.markedLabel : root.entry.label !== undefined ? root.entry.label : ""
235
+ opacity: root.available ? 1 : Theme.disabledOpacity
236
+ color: root.labelColor
237
+ font.family: Theme.font.family
238
+ font.pixelSize: Theme.font.body
239
+ textFormat: root.markedLabel !== "" ? Text.StyledText : Text.PlainText
240
+ elide: Text.ElideRight
241
+ }
242
+
243
+ // The rail's 6 px mount-status square, borrowed by a row whose hint is a state rather than a key: Update Flea's newer version.
244
+ Rectangle {
245
+ id: statusSquare
246
+ visible: root.entry.hintSquare === true && root.hint.length > 0
247
+ anchors.right: hintText.left
248
+ anchors.rightMargin: root.statusSquareGap
249
+ anchors.verticalCenter: parent.verticalCenter
250
+ width: root.statusSquareSize
251
+ height: root.statusSquareSize
252
+ color: Theme.color.accent
253
+ }
254
+
255
+ // The shortcut hint. An unbound row draws nothing and takes no width, so a menu of unbound rows
256
+ // reads exactly as it did before this slot existed.
257
+ Text {
258
+ id: hintText
259
+ visible: root.hint.length > 0
260
+ anchors.right: chevronSlot.left
261
+ anchors.rightMargin: root.isSubmenu ? Theme.spacing.gap : 0
262
+ anchors.verticalCenter: parent.verticalCenter
263
+ text: root.hint
264
+ // Permissions.html alone leaves its refusal span wrappable, and it asks for that by name. The
265
+ // constraint subtracts the label's unelided width, so a short caption beside a long label
266
+ // collapsed to nothing: the flyout's own "default" is the caption that has to survive.
267
+ width: root.entry.hintWrap === true
268
+ ? Math.max(0, Math.min(implicitWidth, root.width - 2 * Theme.spacing.rowPaddingX
269
+ - root.slotSize - 2 * Theme.spacing.gap - label.implicitWidth))
270
+ : implicitWidth
271
+ wrapMode: root.entry.hintWrap === true ? Text.WordWrap : Text.NoWrap
272
+ horizontalAlignment: Text.AlignRight
273
+ // MenuAdditions040: every key hint is muted on a live, lit or dead row; a dead row dims it with the label, a wrapped reason stays readable.
274
+ color: root.entry.hintSquare === true ? root.labelColor
275
+ : root.available || root.entry.hintWrap !== true ? Theme.color.muted : Theme.color.foreground
276
+ opacity: root.available || root.entry.hintWrap === true ? 1 : label.opacity
277
+ font.family: Theme.font.family
278
+ font.pixelSize: Theme.font.caption
279
+ // A version beside the status square is a number, so its digits keep one width the way the rail's sizes do.
280
+ font.features: root.entry.hintSquare === true ? { "tnum": 1 } : ({})
281
+ textFormat: Text.PlainText
282
+ }
283
+
284
+ // The disclosure is a cut glyph, not the "▸" font dingbat the menu used to mix into a path language.
285
+ Item {
286
+ id: chevronSlot
287
+ anchors.right: parent.right
288
+ anchors.rightMargin: Theme.spacing.rowPaddingX
289
+ anchors.verticalCenter: parent.verticalCenter
290
+ width: root.isSubmenu ? Theme.font.caption : 0
291
+ height: Theme.font.caption
292
+
293
+ Flea.Glyph {
294
+ anchors.fill: parent
295
+ visible: root.isSubmenu
296
+ name: "chevron-right"
297
+ color: Theme.color.mutedFrame
298
+ }
299
+ }
300
+
301
+ HoverHandler {
302
+ id: pointer
303
+ enabled: !root.isSeparator && root.available
304
+ // Scene coordinates distinguish actual motion from a row moving beneath the resting pointer.
305
+ property bool armed: false
306
+ property point restingAt
307
+ // A first hover at the menu's last point, or at one unseen since it opened (Qt 6.12 hovers up to 100 ms late), is a still pointer.
308
+ onHoveredChanged: {
309
+ if (!pointer.hovered) {
310
+ pointer.armed = false
311
+ return
312
+ }
313
+ var position = pointer.point.scenePosition
314
+ pointer.armed = true
315
+ pointer.restingAt = position
316
+ // Read the coordinates out before reporting the new one: the shared property is live, so
317
+ // holding it would compare the new position against itself and lose the move.
318
+ var knownX = root.lastPointerGlobal.x, knownY = root.lastPointerGlobal.y
319
+ root.pointerSeen(position)
320
+ if (root.awayFrom(position, knownX, knownY))
321
+ root.pointerMoved()
322
+ }
323
+ onPointChanged: {
324
+ if (!pointer.hovered)
325
+ return
326
+ var position = pointer.point.scenePosition
327
+ if (!pointer.armed) {
328
+ var firstX = root.lastPointerGlobal.x, firstY = root.lastPointerGlobal.y
329
+ pointer.armed = true
330
+ pointer.restingAt = position
331
+ root.pointerSeen(position)
332
+ if (root.awayFrom(position, firstX, firstY))
333
+ root.pointerMoved()
334
+ return
335
+ }
336
+ var moved = position.x !== pointer.restingAt.x || position.y !== pointer.restingAt.y
337
+ pointer.restingAt = position
338
+ root.pointerSeen(position)
339
+ if (moved)
340
+ root.pointerMoved()
341
+ }
342
+ }
343
+
344
+ TapHandler {
345
+ id: tap
346
+ enabled: !root.isSeparator && root.available
347
+ acceptedButtons: Qt.LeftButton
348
+ gesturePolicy: TapHandler.ReleaseWithinBounds
349
+ onTapped: root.activated()
350
+ }
351
+ }
@@ -0,0 +1,100 @@
1
+ import QtQuick
2
+ import Quickshell.Io
3
+
4
+ // The five second "gio mount -li" poll, lifted out of ui/NetworkMounts.qml whole so that file has
5
+ // room in the 0.1.4 composition. The Service reads "text" when "listed" fires, and its own
6
+ // pollMounts() is the only thing outside this file that calls poll().
7
+ // -i rides along for ui/js/Phones.js: a phone volume's activation_root and can_mount print only
8
+ // under it, and both spellings measured half a second on this box over three interleaved runs, with
9
+ // no separation between the arms, because the cost is walking the volume monitors and not printing.
10
+ Item {
11
+ id: root
12
+
13
+ // Nothing filesystem-watchable tells us when a share appears or drops: a mount materialises a
14
+ // directory under /run/user/1000/gvfs that inotify never reports an event for, measured on this box.
15
+ readonly property int pollMs: 5000
16
+ // A listing is bounded the same way a mount is in ui/NetworkMounts.qml. "gio mount -l" against a
17
+ // share whose server has stopped answering never returns, and an unbounded one froze the rail.
18
+ readonly property int timeoutMs: 10000
19
+ // The C locale ui/NetworkMounts.qml pins on its own gio calls, passed in so one property sets it.
20
+ property var environment: ({})
21
+ // The last listing that finished on time; a listing this component ended never replaces it.
22
+ property string text: ""
23
+
24
+ // The rail's NETWORK gate: true once the first listing answered, timed out or not, without replacing anything.
25
+ property bool answered: false
26
+
27
+ // The window-long host sets this: the 5 s poll runs only while a rail is loaded or an
28
+ // open or wait is in flight, so a hidden rail costs no gio and no mountinfo read. The
29
+ // last listing stands while it is off, the way 0.3.5 ran none.
30
+ property bool active: true
31
+
32
+ // Raised once "text" holds the new listing, so a handler that rebuilds reads it and not the last.
33
+ signal listed()
34
+
35
+ // A Process's own onExited can race its StdioCollector's text property, so the listing is also
36
+ // captured via onStreamFinished as a fallback; poll() clears it, because a fallback held over
37
+ // from the last listing would answer an empty one with the shares it found the time before.
38
+ property string _output: ""
39
+ // A re-read asked for mid-listing used to be dropped, leaving a just-mounted share to wait out
40
+ // the poll; this remembers it instead, and listProcess runs it the moment the listing ends.
41
+ property bool _pollAgain: false
42
+ // Cleared only when the next listing starts, never in onExited, so it still reads true while the
43
+ // ended listing's own stream finishes and cannot overwrite the last good listing with nothing.
44
+ property bool _timedOut: false
45
+
46
+ Timer {
47
+ interval: root.pollMs
48
+ running: root.active
49
+ repeat: true
50
+ triggeredOnStart: true
51
+ onTriggered: root.poll()
52
+ }
53
+
54
+ function poll() {
55
+ if (!root.active) return
56
+ if (listProcess.running) {
57
+ root._pollAgain = true
58
+ return
59
+ }
60
+ root._timedOut = false
61
+ root._output = ""
62
+ listProcess.running = true
63
+ listTimeout.restart()
64
+ }
65
+
66
+ Timer {
67
+ id: listTimeout
68
+ interval: root.timeoutMs
69
+ repeat: false
70
+ onTriggered: {
71
+ if (!listProcess.running)
72
+ return
73
+ // Ending it is what lets the next poll run at all; a listing nobody can end froze the rail.
74
+ root._timedOut = true
75
+ listProcess.running = false
76
+ }
77
+ }
78
+
79
+ Process {
80
+ id: listProcess
81
+ environment: root.environment
82
+ command: ["gio", "mount", "-li"]
83
+ stdout: StdioCollector { id: listOut; waitForEnd: true; onStreamFinished: if (!root._timedOut) root._output = listOut.text }
84
+ onExited: function () {
85
+ listTimeout.stop()
86
+ // A listing this timer ended collected nothing, and reading that as "no shares" would
87
+ // empty the rail, taking the Unmount action with it exactly when a server is misbehaving.
88
+ if (!root._timedOut) {
89
+ root.text = listOut.text || root._output || ""
90
+ root.listed()
91
+ }
92
+ // Last, so anything waiting on the answer reads the listing it answered with.
93
+ root.answered = true
94
+ if (root._pollAgain) {
95
+ root._pollAgain = false
96
+ root.poll()
97
+ }
98
+ }
99
+ }
100
+ }