flea-qml 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (625) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +478 -2
  3. package/THIRD-PARTY-NOTICES.md +29 -0
  4. package/demos/App.java +5 -0
  5. package/demos/Dockerfile +4 -0
  6. package/demos/Main.kt +3 -0
  7. package/demos/Program.cs +1 -0
  8. package/demos/README.md +12 -0
  9. package/demos/app.dart +3 -0
  10. package/demos/app.deb +0 -0
  11. package/demos/app.js +1 -0
  12. package/demos/backup.tar +0 -0
  13. package/demos/budget.xlsx +0 -0
  14. package/demos/build.sh +2 -0
  15. package/demos/bundle.zip +0 -0
  16. package/demos/clip.mp4 +0 -0
  17. package/demos/data.sqlite +0 -0
  18. package/demos/disk.iso +0 -0
  19. package/demos/engine.cpp +5 -0
  20. package/demos/firmware.bin +0 -0
  21. package/demos/flake.nix +4 -0
  22. package/demos/folder/inside.txt +1 -0
  23. package/demos/font.ttf +0 -0
  24. package/demos/index.html +5 -0
  25. package/demos/index.php +2 -0
  26. package/demos/init.lua +1 -0
  27. package/demos/letter.docx +0 -0
  28. package/demos/lib.rs +3 -0
  29. package/demos/main.c +6 -0
  30. package/demos/main.h +3 -0
  31. package/demos/math-and-diagrams.md +200 -0
  32. package/demos/notes.tar.gz +0 -0
  33. package/demos/notes.txt +3 -0
  34. package/demos/photo.png +0 -0
  35. package/demos/program +2 -0
  36. package/demos/report.pdf +32 -0
  37. package/demos/script.py +1 -0
  38. package/demos/server.go +7 -0
  39. package/demos/settings.json +4 -0
  40. package/demos/slides.pptx +0 -0
  41. package/demos/song.mp3 +0 -0
  42. package/demos/style.css +4 -0
  43. package/demos/tool.rb +1 -0
  44. package/demos/types.ts +2 -0
  45. package/docs/pele.md +23 -0
  46. package/docs/protocol.md +3420 -0
  47. package/docs/temml.md +63 -0
  48. package/index.js +107 -0
  49. package/package.json +34 -4
  50. package/src/archive.js +402 -0
  51. package/src/archiveops.js +697 -0
  52. package/src/backend.js +369 -0
  53. package/src/bulkrename.js +95 -0
  54. package/src/clip-host.js +76 -0
  55. package/src/clip.js +462 -0
  56. package/src/code.js +168 -0
  57. package/src/compare.js +74 -0
  58. package/src/create.js +128 -0
  59. package/src/dirsize.js +147 -0
  60. package/src/figure-svg.js +530 -0
  61. package/src/figure-thread.js +23 -0
  62. package/src/figure.js +132 -0
  63. package/src/find.js +55 -0
  64. package/src/flea.js +39 -0
  65. package/src/fsinfo.js +39 -0
  66. package/src/highlight.js +141 -0
  67. package/src/html.js +52 -0
  68. package/src/kinds.js +89 -0
  69. package/src/listing.js +130 -0
  70. package/src/markdown-html.js +317 -0
  71. package/src/mathml.js +186 -0
  72. package/src/menu.js +180 -0
  73. package/src/meta.js +129 -0
  74. package/src/office.js +810 -0
  75. package/src/order.js +100 -0
  76. package/src/peek.js +49 -0
  77. package/src/pele-wrapper.js +695 -0
  78. package/src/permissions.js +180 -0
  79. package/src/places.js +313 -0
  80. package/src/preview-language.js +10 -0
  81. package/src/transfer.js +669 -0
  82. package/src/trash-record.js +41 -0
  83. package/src/trash.js +210 -0
  84. package/src/trashbrowse.js +326 -0
  85. package/src/uistate.js +393 -0
  86. package/src/uistore.js +168 -0
  87. package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
  88. package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
  89. package/src/vendor/LICENSES/MIT-katex.txt +21 -0
  90. package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
  91. package/src/vendor/LICENSES/MIT-pele.txt +40 -0
  92. package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
  93. package/src/vendor/LICENSES/MIT-temml.txt +21 -0
  94. package/src/vendor/pele.js +145 -0
  95. package/src/vendor/temml.mjs +14708 -0
  96. package/src/watch.js +98 -0
  97. package/src/wayland/client.js +109 -0
  98. package/src/wayland/protocol.js +55 -0
  99. package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
  100. package/src/wayland/protocols/wayland.xml +3248 -0
  101. package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
  102. package/src/wayland/resource-io.js +6 -0
  103. package/src/wayland/socket-discovery.js +26 -0
  104. package/src/wayland/transport-posix.js +120 -0
  105. package/src/wayland/transport-win32.js +11 -0
  106. package/src/wayland/transport.js +3 -0
  107. package/src/wayland/win32-resources.js +80 -0
  108. package/src/wayland/win32-wire.js +62 -0
  109. package/test/archive.test.js +80 -0
  110. package/test/bench-markdown-scroll.mjs +190 -0
  111. package/test/clip-host.test.js +113 -0
  112. package/test/code-preview.test.js +35 -0
  113. package/test/compare-ui-paths.test.js +24 -0
  114. package/test/compare.test.js +54 -0
  115. package/test/delete-trash.test.js +67 -0
  116. package/test/dirsize.test.js +138 -0
  117. package/test/file-ops.test.js +241 -0
  118. package/test/find-contents.test.js +161 -0
  119. package/test/find-input.test.js +66 -0
  120. package/test/fixtures/pele-parity.json +1006 -0
  121. package/test/highlight-launcher.test.js +35 -0
  122. package/test/html-preview.test.js +22 -0
  123. package/test/input.test.js +15 -0
  124. package/test/keymap.test.js +26 -0
  125. package/test/language-icons.test.js +36 -0
  126. package/test/launcher.test.js +51 -0
  127. package/test/manual-code-scroll.mjs +28 -0
  128. package/test/manual-column-scroll.mjs +24 -0
  129. package/test/manual-compare-ui.mjs +20 -0
  130. package/test/manual-find-status.mjs +37 -0
  131. package/test/manual-html-security.mjs +23 -0
  132. package/test/manual-html-ui.mjs +30 -0
  133. package/test/manual-syntax-preview.mjs +26 -0
  134. package/test/manual-trash-ui.mjs +86 -0
  135. package/test/markdown-diagrams.test.js +93 -0
  136. package/test/markdown-html.test.js +105 -0
  137. package/test/mathml.test.js +92 -0
  138. package/test/menu-transfer.test.js +57 -0
  139. package/test/office-preview.test.js +154 -0
  140. package/test/pele-parity.test.js +28 -0
  141. package/test/places.test.js +134 -0
  142. package/test/preview-keys.test.js +60 -0
  143. package/test/preview-language.test.js +22 -0
  144. package/test/status-filename.test.js +20 -0
  145. package/test/transfer-replace-merge.test.js +187 -0
  146. package/test/trash-address.test.js +23 -0
  147. package/test/trash-view.test.js +37 -0
  148. package/test/trashbrowse.test.js +135 -0
  149. package/ui/AboutFacts.qml +78 -0
  150. package/ui/ArchiveCards.qml +68 -0
  151. package/ui/ArchiveCompressDialog.qml +378 -0
  152. package/ui/ArchivePasswordDialog.qml +257 -0
  153. package/ui/Backend.qml +771 -0
  154. package/ui/BulkOldNames.qml +47 -0
  155. package/ui/BulkRenameDialog.qml +380 -0
  156. package/ui/CardFrame.qml +67 -0
  157. package/ui/CardScroll.qml +79 -0
  158. package/ui/CheckBox.qml +73 -0
  159. package/ui/ChromeBar.qml +360 -0
  160. package/ui/ChromeButton.qml +131 -0
  161. package/ui/ChromeModes.qml +43 -0
  162. package/ui/CodeLines.qml +256 -0
  163. package/ui/CodeRefusal.qml +52 -0
  164. package/ui/CollideConfirm.qml +147 -0
  165. package/ui/CollideHost.qml +167 -0
  166. package/ui/ColumnPane.qml +523 -0
  167. package/ui/ColumnRow.qml +380 -0
  168. package/ui/ColumnsArea.qml +594 -0
  169. package/ui/ColumnsLanding.qml +147 -0
  170. package/ui/CompareView.qml +321 -0
  171. package/ui/ContextMenu.qml +743 -0
  172. package/ui/ConvertDialog.qml +456 -0
  173. package/ui/CountedWorker.qml +7 -0
  174. package/ui/Crumb.qml +64 -0
  175. package/ui/CrumbDrop.qml +25 -0
  176. package/ui/CsvTable.qml +394 -0
  177. package/ui/CursorMark.qml +41 -0
  178. package/ui/DefaultClaim.qml +130 -0
  179. package/ui/DeviceLock.qml +47 -0
  180. package/ui/DeviceMounts.qml +540 -0
  181. package/ui/DialogButton.qml +150 -0
  182. package/ui/DialogField.qml +147 -0
  183. package/ui/DialogHeader.qml +31 -0
  184. package/ui/DialogScrim.qml +20 -0
  185. package/ui/DialogTitle.qml +37 -0
  186. package/ui/Divider.qml +9 -0
  187. package/ui/DropInto.qml +126 -0
  188. package/ui/DropTarget.qml +35 -0
  189. package/ui/DropboxMark.qml +60 -0
  190. package/ui/EmptyState.qml +150 -0
  191. package/ui/EscapeHint.qml +11 -0
  192. package/ui/FactsTable.qml +54 -0
  193. package/ui/FastScrollHandler.qml +476 -0
  194. package/ui/FatNamesConfirm.qml +157 -0
  195. package/ui/Favourites.qml +143 -0
  196. package/ui/FigureService.qml +120 -0
  197. package/ui/FileDrag.qml +267 -0
  198. package/ui/FilterStrip.qml +133 -0
  199. package/ui/FitMetrics.qml +22 -0
  200. package/ui/FlashDriveRows.qml +137 -0
  201. package/ui/FlashHost.qml +72 -0
  202. package/ui/FlashImageRow.qml +104 -0
  203. package/ui/FlashRunner.qml +119 -0
  204. package/ui/FlashStepRow.qml +172 -0
  205. package/ui/FlashStrip.qml +38 -0
  206. package/ui/FlashView.qml +397 -0
  207. package/ui/FleaMark.qml +88 -0
  208. package/ui/FlyoutFade.qml +23 -0
  209. package/ui/FontPane.qml +170 -0
  210. package/ui/Glass.qml +114 -0
  211. package/ui/GlassTagger.qml +59 -0
  212. package/ui/Glyph.qml +64 -0
  213. package/ui/GlyphSolid.qml +22 -0
  214. package/ui/GridArea.qml +664 -0
  215. package/ui/GridTile.qml +325 -0
  216. package/ui/GvfsBridge.qml +164 -0
  217. package/ui/Header.qml +433 -0
  218. package/ui/HoverTimers.qml +39 -0
  219. package/ui/HtmlClip.qml +30 -0
  220. package/ui/HtmlPane.qml +63 -0
  221. package/ui/HyprlandMark.qml +45 -0
  222. package/ui/Ipc.qml +1005 -0
  223. package/ui/IpcControls.qml +7 -0
  224. package/ui/IpcMenuState.qml +48 -0
  225. package/ui/IpcPreviewState.qml +185 -0
  226. package/ui/JumpPath.qml +51 -0
  227. package/ui/KeymapSheet.qml +561 -0
  228. package/ui/KeymapSheetResult.qml +89 -0
  229. package/ui/KindStack.qml +40 -0
  230. package/ui/LangMark.qml +51 -0
  231. package/ui/LangMarkLoader.qml +26 -0
  232. package/ui/List.qml +480 -0
  233. package/ui/LoadingState.qml +54 -0
  234. package/ui/LocalSend.qml +56 -0
  235. package/ui/LocalSendMark.qml +73 -0
  236. package/ui/MarkdownBlockView.qml +311 -0
  237. package/ui/MarkdownBlocks.qml +35 -0
  238. package/ui/MarkdownFigure.qml +254 -0
  239. package/ui/MarkdownImages.qml +72 -0
  240. package/ui/MarkdownList.qml +81 -0
  241. package/ui/MarkdownMathsText.qml +97 -0
  242. package/ui/MarkdownPane.qml +83 -0
  243. package/ui/MarkdownPictures.qml +41 -0
  244. package/ui/MarkdownQuote.qml +52 -0
  245. package/ui/MarkdownRemote.qml +82 -0
  246. package/ui/MarkdownSource.qml +155 -0
  247. package/ui/MarkdownTable.qml +222 -0
  248. package/ui/MarkdownTableScroll.qml +64 -0
  249. package/ui/MarkdownTableWheel.qml +126 -0
  250. package/ui/MarkdownText.qml +87 -0
  251. package/ui/MarkdownWorker.js +132 -0
  252. package/ui/MatchText.qml +99 -0
  253. package/ui/MediaSession.qml +38 -0
  254. package/ui/MediaSound.qml +26 -0
  255. package/ui/MediaStrip.qml +191 -0
  256. package/ui/MediaTrack.qml +36 -0
  257. package/ui/MediaVolume.qml +54 -0
  258. package/ui/MenuActionDialog.qml +396 -0
  259. package/ui/MenuEdgeFade.qml +24 -0
  260. package/ui/MenuHost.qml +227 -0
  261. package/ui/MenuRow.qml +351 -0
  262. package/ui/MountListing.qml +100 -0
  263. package/ui/NetworkDialog.qml +435 -0
  264. package/ui/NetworkForm.qml +426 -0
  265. package/ui/NetworkMounts.qml +913 -0
  266. package/ui/NetworkPlaces.qml +127 -0
  267. package/ui/OpenWithDialog.qml +613 -0
  268. package/ui/Opener.qml +115 -0
  269. package/ui/Pane.qml +1296 -0
  270. package/ui/PaneMenuActions.qml +527 -0
  271. package/ui/PanePath.qml +90 -0
  272. package/ui/PaneRail.qml +239 -0
  273. package/ui/PaneStates.qml +88 -0
  274. package/ui/PaneSwap.qml +339 -0
  275. package/ui/PaneWire.qml +605 -0
  276. package/ui/ParkedWait.qml +9 -0
  277. package/ui/PathEntry.qml +186 -0
  278. package/ui/PathJump.qml +400 -0
  279. package/ui/PdfViewer.qml +297 -0
  280. package/ui/PermissionsDialog.qml +658 -0
  281. package/ui/PermissionsHeadings.qml +31 -0
  282. package/ui/PhoneMounts.qml +67 -0
  283. package/ui/PickerAnswers.qml +75 -0
  284. package/ui/PickerBox.qml +26 -0
  285. package/ui/PickerChrome.qml +295 -0
  286. package/ui/PickerFilter.qml +97 -0
  287. package/ui/PickerGrid.qml +308 -0
  288. package/ui/PickerHeader.qml +28 -0
  289. package/ui/PickerLifecycle.qml +27 -0
  290. package/ui/PickerList.qml +218 -0
  291. package/ui/PickerListing.qml +149 -0
  292. package/ui/PickerPathBar.qml +127 -0
  293. package/ui/PickerPlaces.qml +189 -0
  294. package/ui/PickerRecent.qml +92 -0
  295. package/ui/PickerSave.qml +101 -0
  296. package/ui/PickerSelection.qml +155 -0
  297. package/ui/PickerWindow.qml +846 -0
  298. package/ui/PowerSectorsReader.qml +10 -0
  299. package/ui/PrebuildDriver.qml +146 -0
  300. package/ui/Preview.qml +1004 -0
  301. package/ui/PreviewAnimation.qml +24 -0
  302. package/ui/PreviewArchive.qml +66 -0
  303. package/ui/PreviewColumn.qml +551 -0
  304. package/ui/PreviewEdge.qml +63 -0
  305. package/ui/PreviewFacts.qml +30 -0
  306. package/ui/PreviewFactsLine.qml +34 -0
  307. package/ui/PreviewHtml.qml +233 -0
  308. package/ui/PreviewImage.qml +253 -0
  309. package/ui/PreviewImagePan.qml +13 -0
  310. package/ui/PreviewImageSharp.qml +32 -0
  311. package/ui/PreviewLines.qml +106 -0
  312. package/ui/PreviewMarkdown.qml +706 -0
  313. package/ui/PreviewMedia.qml +250 -0
  314. package/ui/PreviewPdf.qml +482 -0
  315. package/ui/PreviewScroll.qml +201 -0
  316. package/ui/PreviewSwap.qml +335 -0
  317. package/ui/PreviewText.qml +149 -0
  318. package/ui/ProtocolChip.qml +18 -0
  319. package/ui/QuickLookArchive.qml +38 -0
  320. package/ui/QuickLookBar.qml +103 -0
  321. package/ui/QuickLookPrepare.qml +355 -0
  322. package/ui/QuickLookSwap.qml +10 -0
  323. package/ui/QuickLookWarm.qml +65 -0
  324. package/ui/RailDrop.qml +155 -0
  325. package/ui/RailHeading.qml +19 -0
  326. package/ui/RailPlaces.qml +38 -0
  327. package/ui/RailTrashRow.qml +67 -0
  328. package/ui/RenameField.qml +353 -0
  329. package/ui/RendererRetry.qml +11 -0
  330. package/ui/ResizeHandle.qml +52 -0
  331. package/ui/Reveal.qml +54 -0
  332. package/ui/Row.qml +476 -0
  333. package/ui/RowDrag.qml +213 -0
  334. package/ui/RowDropTarget.qml +27 -0
  335. package/ui/RunCard.qml +286 -0
  336. package/ui/Scripts.qml +65 -0
  337. package/ui/SearchStrip.qml +232 -0
  338. package/ui/SelectionBand.qml +140 -0
  339. package/ui/SelectionPreview.qml +370 -0
  340. package/ui/SettingsFavourite.qml +122 -0
  341. package/ui/SettingsGroup.qml +96 -0
  342. package/ui/SettingsHint.qml +12 -0
  343. package/ui/SettingsMetrics.qml +29 -0
  344. package/ui/SettingsPane.qml +178 -0
  345. package/ui/SettingsPanel.qml +547 -0
  346. package/ui/SettingsRail.qml +128 -0
  347. package/ui/SettingsRow.qml +409 -0
  348. package/ui/SettingsRuler.qml +85 -0
  349. package/ui/SettingsSegment.qml +85 -0
  350. package/ui/ShareBrowser.qml +113 -0
  351. package/ui/ShareLink.qml +67 -0
  352. package/ui/ShelfPins.qml +101 -0
  353. package/ui/Sidebar.qml +732 -0
  354. package/ui/SidebarRow.qml +358 -0
  355. package/ui/Spinner.qml +60 -0
  356. package/ui/StableModel.qml +89 -0
  357. package/ui/StateMessage.qml +84 -0
  358. package/ui/StatusBar.qml +512 -0
  359. package/ui/StatusFileName.qml +27 -0
  360. package/ui/TabBar.qml +673 -0
  361. package/ui/TabDragGeometry.qml +60 -0
  362. package/ui/TagMenuMark.qml +52 -0
  363. package/ui/TagRailSection.qml +53 -0
  364. package/ui/TagSlot.qml +40 -0
  365. package/ui/TagState.qml +150 -0
  366. package/ui/TagSwatch.qml +28 -0
  367. package/ui/Taildrop.qml +86 -0
  368. package/ui/TailscaleMark.qml +50 -0
  369. package/ui/Theme.qml +460 -0
  370. package/ui/ThemeColors.qml +43 -0
  371. package/ui/TransferCard.qml +239 -0
  372. package/ui/TrashConfirm.qml +129 -0
  373. package/ui/TrashDropHandler.qml +11 -0
  374. package/ui/TrashHost.qml +202 -0
  375. package/ui/TrashMonitor.qml +30 -0
  376. package/ui/TrashToolbar.qml +19 -0
  377. package/ui/TrashView.qml +492 -0
  378. package/ui/UnlockDialog.qml +450 -0
  379. package/ui/UnlockHost.qml +206 -0
  380. package/ui/UpdateCheck.qml +97 -0
  381. package/ui/UserDirs.qml +25 -0
  382. package/ui/ViewState.qml +565 -0
  383. package/ui/ViewportScrollBar.qml +195 -0
  384. package/ui/ViewportScrollBars.qml +25 -0
  385. package/ui/WebPreview.qml +33 -0
  386. package/ui/WebPreviewView.qml +26 -0
  387. package/ui/WindowBody.qml +827 -0
  388. package/ui/WindowDrag.qml +35 -0
  389. package/ui/boot/Commons/AudioNodes.qml +50 -0
  390. package/ui/boot/Commons/AudioNodesModel.js +96 -0
  391. package/ui/boot/Commons/Border.qml +243 -0
  392. package/ui/boot/Commons/BorderGeometry.js +373 -0
  393. package/ui/boot/Commons/Color.qml +258 -0
  394. package/ui/boot/Commons/I18n.qml +118 -0
  395. package/ui/boot/Commons/InputDevices.qml +112 -0
  396. package/ui/boot/Commons/InputMethodState.qml +38 -0
  397. package/ui/boot/Commons/IpcRegistry.qml +77 -0
  398. package/ui/boot/Commons/Numbers.js +19 -0
  399. package/ui/boot/Commons/Plural.js +91 -0
  400. package/ui/boot/Commons/ShellIpc.qml +12 -0
  401. package/ui/boot/Commons/Style.qml +561 -0
  402. package/ui/boot/Commons/Translations.qml +100 -0
  403. package/ui/boot/Commons/UntypedInput.qml +152 -0
  404. package/ui/boot/Commons/Util.qml +188 -0
  405. package/ui/boot/Commons/qmldir +13 -0
  406. package/ui/boot/LICENSE-omarchy +20 -0
  407. package/ui/boot/Ui/BackgroundMedia.qml +49 -0
  408. package/ui/boot/Ui/BarIconButton.qml +106 -0
  409. package/ui/boot/Ui/BarIconContent.qml +38 -0
  410. package/ui/boot/Ui/BarIndicator.qml +53 -0
  411. package/ui/boot/Ui/BarWidget.qml +50 -0
  412. package/ui/boot/Ui/BorderOverlay.qml +54 -0
  413. package/ui/boot/Ui/BorderSurface.qml +40 -0
  414. package/ui/boot/Ui/Button.qml +224 -0
  415. package/ui/boot/Ui/ButtonGroup.qml +131 -0
  416. package/ui/boot/Ui/ConfirmDialog.qml +134 -0
  417. package/ui/boot/Ui/CursorSurface.qml +42 -0
  418. package/ui/boot/Ui/Dropdown.qml +245 -0
  419. package/ui/boot/Ui/FilterInput.qml +26 -0
  420. package/ui/boot/Ui/IconContentBounds.qml +141 -0
  421. package/ui/boot/Ui/KeyboardPanel.qml +453 -0
  422. package/ui/boot/Ui/MultiSelect.qml +624 -0
  423. package/ui/boot/Ui/NumberField.qml +86 -0
  424. package/ui/boot/Ui/OpticalGlyph.qml +68 -0
  425. package/ui/boot/Ui/OverlayWindow.qml +102 -0
  426. package/ui/boot/Ui/Panel.qml +60 -0
  427. package/ui/boot/Ui/PanelActionButton.qml +105 -0
  428. package/ui/boot/Ui/PanelController.qml +16 -0
  429. package/ui/boot/Ui/PanelHero.qml +112 -0
  430. package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
  431. package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
  432. package/ui/boot/Ui/PanelSeparator.qml +19 -0
  433. package/ui/boot/Ui/PanelSlider.qml +156 -0
  434. package/ui/boot/Ui/PanelToolTip.qml +50 -0
  435. package/ui/boot/Ui/PluginBarApi.qml +89 -0
  436. package/ui/boot/Ui/PointerMoveGate.qml +54 -0
  437. package/ui/boot/Ui/PopupCard.qml +181 -0
  438. package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
  439. package/ui/boot/Ui/SearchableDropdown.qml +354 -0
  440. package/ui/boot/Ui/SizedImage.qml +125 -0
  441. package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
  442. package/ui/boot/Ui/TextField.qml +58 -0
  443. package/ui/boot/Ui/Toggle.qml +118 -0
  444. package/ui/boot/Ui/ToggleSwitch.qml +115 -0
  445. package/ui/boot/Ui/WidgetButton.qml +172 -0
  446. package/ui/boot/Ui/qmldir +41 -0
  447. package/ui/boot/fleatab.qml +50 -0
  448. package/ui/boot/picker.qml +39 -0
  449. package/ui/boot/shell.qml +122 -0
  450. package/ui/boot/tabtearoff.qml +51 -0
  451. package/ui/js/Anchor.js +379 -0
  452. package/ui/js/AnchorHold.js +162 -0
  453. package/ui/js/Archive.js +157 -0
  454. package/ui/js/ArchiveCard.js +44 -0
  455. package/ui/js/ArchiveOps.js +44 -0
  456. package/ui/js/BackReturn.js +118 -0
  457. package/ui/js/BulkRename.js +100 -0
  458. package/ui/js/Buttons.js +54 -0
  459. package/ui/js/ChromeKeys.js +116 -0
  460. package/ui/js/ClipMarks.js +73 -0
  461. package/ui/js/ClipSelection.js +67 -0
  462. package/ui/js/Clipboard.js +179 -0
  463. package/ui/js/Cloud.js +97 -0
  464. package/ui/js/CodeRuns.js +72 -0
  465. package/ui/js/Collide.js +212 -0
  466. package/ui/js/ColumnFit.js +28 -0
  467. package/ui/js/ColumnMenu.js +111 -0
  468. package/ui/js/Columns.js +298 -0
  469. package/ui/js/ColumnsCarry.js +103 -0
  470. package/ui/js/Compare.js +74 -0
  471. package/ui/js/Contrast.js +157 -0
  472. package/ui/js/ControlReader.js +42 -0
  473. package/ui/js/Convert.js +52 -0
  474. package/ui/js/CopyAs.js +52 -0
  475. package/ui/js/Crumbs.js +178 -0
  476. package/ui/js/Csv.js +231 -0
  477. package/ui/js/Density.js +44 -0
  478. package/ui/js/Devices.js +440 -0
  479. package/ui/js/DirSizes.js +180 -0
  480. package/ui/js/Drag.js +364 -0
  481. package/ui/js/DragOut.js +166 -0
  482. package/ui/js/DropDev.js +52 -0
  483. package/ui/js/Dropbox.js +41 -0
  484. package/ui/js/Eject.js +217 -0
  485. package/ui/js/Errors.js +188 -0
  486. package/ui/js/ExtThumbs.js +115 -0
  487. package/ui/js/Facts.js +402 -0
  488. package/ui/js/FigureDate.js +14 -0
  489. package/ui/js/Filter.js +285 -0
  490. package/ui/js/Find.js +46 -0
  491. package/ui/js/Flash.js +184 -0
  492. package/ui/js/FlashCard.js +79 -0
  493. package/ui/js/FlashEndings.js +125 -0
  494. package/ui/js/FlashPane.js +116 -0
  495. package/ui/js/FleaBin.js +12 -0
  496. package/ui/js/Focus.js +502 -0
  497. package/ui/js/FolderSorts.js +108 -0
  498. package/ui/js/FolderViews.js +44 -0
  499. package/ui/js/Format.js +305 -0
  500. package/ui/js/Fuzzy.js +141 -0
  501. package/ui/js/GlassTag.js +72 -0
  502. package/ui/js/Grid.js +33 -0
  503. package/ui/js/GridGeometry.js +90 -0
  504. package/ui/js/GridNames.js +153 -0
  505. package/ui/js/GvfsBridge.js +200 -0
  506. package/ui/js/HostClipboard.js +29 -0
  507. package/ui/js/Icons.js +218 -0
  508. package/ui/js/Input.js +50 -0
  509. package/ui/js/Jump.js +200 -0
  510. package/ui/js/KeyName.js +64 -0
  511. package/ui/js/Keymap.js +401 -0
  512. package/ui/js/Kinds.js +164 -0
  513. package/ui/js/LICENSES/ISC-lucide.txt +43 -0
  514. package/ui/js/LangMarkPaths.js +47 -0
  515. package/ui/js/LangMarks.js +120 -0
  516. package/ui/js/Lists.js +11 -0
  517. package/ui/js/LocalSend.js +39 -0
  518. package/ui/js/LockedMenu.js +63 -0
  519. package/ui/js/MakeDefault.js +186 -0
  520. package/ui/js/MarkBox.js +7 -0
  521. package/ui/js/Markdown.js +119 -0
  522. package/ui/js/MarkdownLists.js +86 -0
  523. package/ui/js/MarkdownMaths.js +58 -0
  524. package/ui/js/MarkdownPictures.js +32 -0
  525. package/ui/js/MarkdownPrepared.js +139 -0
  526. package/ui/js/MarkdownTableFit.js +34 -0
  527. package/ui/js/Marks.js +148 -0
  528. package/ui/js/Marquee.js +96 -0
  529. package/ui/js/Match.js +93 -0
  530. package/ui/js/Material.js +109 -0
  531. package/ui/js/MdBlocks.js +437 -0
  532. package/ui/js/MdBreak.js +71 -0
  533. package/ui/js/MdChunks.js +70 -0
  534. package/ui/js/MdContainer.js +137 -0
  535. package/ui/js/MdDocument.js +337 -0
  536. package/ui/js/MdEmph.js +97 -0
  537. package/ui/js/MdEntity.js +108 -0
  538. package/ui/js/MdEntityTable.js +223 -0
  539. package/ui/js/MdEscape.js +59 -0
  540. package/ui/js/MdFront.js +37 -0
  541. package/ui/js/MdHold.js +32 -0
  542. package/ui/js/MdHtml.js +307 -0
  543. package/ui/js/MdHtmlBlock.js +290 -0
  544. package/ui/js/MdHtmlHeading.js +53 -0
  545. package/ui/js/MdHtmlImage.js +179 -0
  546. package/ui/js/MdInline.js +154 -0
  547. package/ui/js/MdItems.js +212 -0
  548. package/ui/js/MdLeaf.js +309 -0
  549. package/ui/js/MdLink.js +196 -0
  550. package/ui/js/MdMath.js +67 -0
  551. package/ui/js/MdParagraphs.js +138 -0
  552. package/ui/js/MdRefs.js +232 -0
  553. package/ui/js/MdResolve.js +226 -0
  554. package/ui/js/MdRun.js +300 -0
  555. package/ui/js/MdUrl.js +226 -0
  556. package/ui/js/Menu.js +514 -0
  557. package/ui/js/MenuContext.js +85 -0
  558. package/ui/js/MenuFit.js +13 -0
  559. package/ui/js/MenuRefresh.js +74 -0
  560. package/ui/js/MenuWheel.js +35 -0
  561. package/ui/js/Messages.js +186 -0
  562. package/ui/js/Motion.js +16 -0
  563. package/ui/js/Mounts.js +320 -0
  564. package/ui/js/MouseNav.js +13 -0
  565. package/ui/js/Nav.js +329 -0
  566. package/ui/js/NetFs.js +26 -0
  567. package/ui/js/OpenWith.js +83 -0
  568. package/ui/js/Ops.js +585 -0
  569. package/ui/js/Palette.js +33 -0
  570. package/ui/js/PathBar.js +260 -0
  571. package/ui/js/Permissions.js +179 -0
  572. package/ui/js/Phones.js +112 -0
  573. package/ui/js/Picker.js +353 -0
  574. package/ui/js/PlaceMenu.js +96 -0
  575. package/ui/js/Places.js +265 -0
  576. package/ui/js/PreviewAsk.js +21 -0
  577. package/ui/js/PreviewKeys.js +155 -0
  578. package/ui/js/PreviewSettle.js +29 -0
  579. package/ui/js/PreviewSwap.js +101 -0
  580. package/ui/js/PropertyFacts.js +144 -0
  581. package/ui/js/Protocols.js +296 -0
  582. package/ui/js/QuickLookKinds.js +27 -0
  583. package/ui/js/QuickLookRect.js +24 -0
  584. package/ui/js/RailDrop.js +51 -0
  585. package/ui/js/RailKeys.js +87 -0
  586. package/ui/js/RailMenu.js +133 -0
  587. package/ui/js/Recent.js +135 -0
  588. package/ui/js/RecentMode.js +156 -0
  589. package/ui/js/Reload.js +60 -0
  590. package/ui/js/Renderer.js +9 -0
  591. package/ui/js/RunFile.js +143 -0
  592. package/ui/js/Scripts.js +28 -0
  593. package/ui/js/Scroll.js +304 -0
  594. package/ui/js/ScrollOff.js +69 -0
  595. package/ui/js/Search.js +478 -0
  596. package/ui/js/Selection.js +97 -0
  597. package/ui/js/Settings.js +476 -0
  598. package/ui/js/SettingsAbout.js +97 -0
  599. package/ui/js/SettingsShelf.js +52 -0
  600. package/ui/js/SheetKeys.js +42 -0
  601. package/ui/js/SheetQuery.js +281 -0
  602. package/ui/js/ShelfPile.js +27 -0
  603. package/ui/js/SlowClick.js +53 -0
  604. package/ui/js/SlowOp.js +6 -0
  605. package/ui/js/Sort.js +134 -0
  606. package/ui/js/Startup.js +63 -0
  607. package/ui/js/StateWords.js +17 -0
  608. package/ui/js/Status.js +238 -0
  609. package/ui/js/Swap.js +166 -0
  610. package/ui/js/TabMove.js +39 -0
  611. package/ui/js/Tabs.js +736 -0
  612. package/ui/js/Tags.js +134 -0
  613. package/ui/js/Taildrop.js +128 -0
  614. package/ui/js/Tap.js +174 -0
  615. package/ui/js/TextSize.js +107 -0
  616. package/ui/js/Thumbs.js +158 -0
  617. package/ui/js/Transfer.js +172 -0
  618. package/ui/js/Trash.js +81 -0
  619. package/ui/js/TrashDates.js +47 -0
  620. package/ui/js/TrashDrop.js +64 -0
  621. package/ui/js/UiState.js +438 -0
  622. package/ui/js/Unlock.js +152 -0
  623. package/ui/js/Update.js +130 -0
  624. package/ui/js/UserDirs.js +56 -0
  625. package/ui/qmldir +228 -0
@@ -0,0 +1,435 @@
1
+ import QtQuick
2
+ import Quickshell
3
+ import Quickshell.Io
4
+ import qs.Commons
5
+ import qs.Ui
6
+ import "." as Flea
7
+ import "js/Mounts.js" as Mounts
8
+ import "js/Protocols.js" as Protocols
9
+
10
+ // A new favourite is saved only after its identified mount succeeds; credentials stay in this session.
11
+ Item {
12
+ id: root
13
+
14
+ property bool opened: false
15
+ property string statusText: ""
16
+ property bool dropboxInstalled: false
17
+ property bool retrying: false
18
+ property bool failedConnect: false
19
+ property int requestSerial: 0
20
+ property string requestId: ""
21
+ property string mountedUri: ""
22
+ property string pendingUri: ""
23
+ property string pendingLabel: ""
24
+ property bool connecting: false
25
+ property bool saving: false
26
+ property bool saveCommitted: false
27
+ property bool saveNewPlace: true
28
+ readonly property bool busy: root.connecting || root.saving
29
+ readonly property string dialogTitle: root.failedConnect ? "Could not connect to the network share" : root.baseTitle()
30
+ // The card keeps this much window above and below it when the window is shorter than the card.
31
+ readonly property int clampMargin: 8
32
+ // var, not Item: BorderSurface is a qs.Ui type qmllint cannot resolve, and Item would read as incompatible.
33
+ readonly property var cardItem: card
34
+ readonly property var bodyItem: body
35
+
36
+ signal closed()
37
+ signal mountRequested(string requestId, string uri, string label, string password)
38
+ signal cancelRequested(string requestId)
39
+
40
+ // A plain overlay, not a QQC Popup, the same call ui/ContextMenu.qml already made.
41
+ anchors.fill: parent
42
+ // opened flips at once so no caller races the close fade; visible holds until the fade ends, and a closed dialog takes no input.
43
+ visible: root.opened || root.opacity > 0
44
+ enabled: root.opened
45
+ opacity: 0
46
+
47
+ function open() {
48
+ if (root.opened || root.busy) return
49
+ root.unacknowledgedUri = ""
50
+ root.unacknowledgedReason = ""
51
+ root.statusText = ""
52
+ root.retrying = false
53
+ root.failedConnect = false
54
+ root.mountedUri = ""
55
+ root.saveNewPlace = true
56
+ root.saveCommitted = false
57
+ form.reset()
58
+ root.present()
59
+ }
60
+
61
+ // The reason a mount actually failed with, kept across a close so reopening the same location
62
+ // cannot answer for it. 0.1.6 never completed a missing-credential request, so its dialog kept
63
+ // the real cause; here the row is reopened for the same uri a second later and the generic
64
+ // "Enter the password" prompt was landing on top of "authentication helper is unavailable".
65
+ property string unacknowledgedUri: ""
66
+ property string unacknowledgedReason: ""
67
+
68
+ function openLocation(uri, label, password, reason, failed) {
69
+ if (root.opened || root.busy) return
70
+ form.load(root.valuesFor(uri, label, password))
71
+ var known = root.unacknowledgedUri === Mounts.normalize(uri) && root.unacknowledgedReason.length > 0
72
+ root.statusText = known && failed !== true ? root.unacknowledgedReason : (reason || "")
73
+ root.retrying = true
74
+ root.failedConnect = known && failed !== true ? true : failed === true
75
+ // Showing it is what acknowledges it. Left standing it answered the next genuine credential
76
+ // prompt for the same location with a connect failure from minutes earlier.
77
+ if (known) { root.unacknowledgedUri = ""; root.unacknowledgedReason = "" }
78
+ root.mountedUri = ""
79
+ root.saveNewPlace = false
80
+ root.saveCommitted = false
81
+ root.present()
82
+ }
83
+
84
+ // The card is kept between opens, so a body scrolled last time would open scrolled.
85
+ function present() {
86
+ body.contentY = 0
87
+ root.checkDropbox()
88
+ root.opened = true
89
+ // The host is the one field the form actually needs, so it takes the caret on open.
90
+ form.focusHost()
91
+ }
92
+
93
+ function close() {
94
+ if (root.saving) return
95
+ if (root.connecting) root.cancelRequested(root.requestId)
96
+ root.connecting = false
97
+ root.requestId = ""
98
+ root.mountedUri = ""
99
+ form.takePassword()
100
+ root.opened = false
101
+ root.closed()
102
+ }
103
+
104
+ // The URI the form built, which is the same one the Mounts-as line showed.
105
+ function submitLocation() {
106
+ if (!root.opened || root.busy) return
107
+ if (root.saveCommitted) { root.close(); return }
108
+ if (!form.complete) {
109
+ root.statusText = "Enter a valid host and port."
110
+ return
111
+ }
112
+ if (form.spec.credentials && form.user.trim().length > 0 && form.password.length === 0) {
113
+ root.statusText = "Enter the password to mount this location."
114
+ root.retrying = true
115
+ root.failedConnect = false
116
+ return
117
+ }
118
+ root.pendingUri = Mounts.normalize(form.uri)
119
+ root.pendingLabel = form.labelText()
120
+ root.unacknowledgedUri = ""
121
+ root.unacknowledgedReason = ""
122
+ root.statusText = ""
123
+ root.requestId = "network-" + (++root.requestSerial)
124
+ if (root.mountedUri === root.pendingUri) { root.saveFavourite(); return }
125
+ pendingFocus.forceActiveFocus()
126
+ root.connecting = true
127
+ root.mountRequested(root.requestId, root.pendingUri, root.pendingLabel, form.password)
128
+ }
129
+
130
+ function mountFinished(requestId, uri, success, reason, connectFailed) {
131
+ if (!root.opened || !root.connecting || requestId !== root.requestId || uri !== root.pendingUri) return
132
+ root.connecting = false
133
+ if (!success) { root.saveFailed(reason, connectFailed === true); return }
134
+ // The location answered, so nothing about it is left unacknowledged.
135
+ root.unacknowledgedUri = ""
136
+ root.unacknowledgedReason = ""
137
+ root.mountedUri = uri
138
+ root.saveFavourite()
139
+ }
140
+
141
+ function saveFavourite() {
142
+ if (!root.saveNewPlace) { root.close(); return }
143
+ pendingFocus.forceActiveFocus()
144
+ root.saving = true
145
+ if (!Favourites.add(root.pendingUri, root.pendingLabel, root.requestId))
146
+ root.saveFailed("A Favorites change is still being saved. Retry to save this location.", false)
147
+ }
148
+
149
+ // connect is true when the connection itself failed, which the mount service says and this dialog never works out from the sentence.
150
+ function saveFailed(message, connect) {
151
+ root.saving = false
152
+ root.statusText = message
153
+ if (connect) {
154
+ root.unacknowledgedUri = Mounts.normalize(root.pendingUri)
155
+ root.unacknowledgedReason = message
156
+ }
157
+ root.retrying = true
158
+ root.failedConnect = connect
159
+ form.focusHost()
160
+ }
161
+
162
+ Connections {
163
+ target: Favourites
164
+ function onCompleted(requestId, success, message) {
165
+ if (!root.opened || !root.saving || requestId !== root.requestId) return
166
+ if (!success) { root.saveFailed(message, false); return }
167
+ root.saving = false
168
+ if (message) {
169
+ root.saveCommitted = true
170
+ root.statusText = message
171
+ pendingFocus.forceActiveFocus()
172
+ return
173
+ }
174
+ root.close()
175
+ }
176
+ }
177
+
178
+ Item {
179
+ id: pendingFocus
180
+ Keys.onTabPressed: function(event) { event.accepted = true }
181
+ Keys.onBacktabPressed: function(event) { event.accepted = true }
182
+ Keys.onEscapePressed: root.close()
183
+ Keys.onReturnPressed: if (root.saveCommitted) root.close()
184
+ Keys.onEnterPressed: if (root.saveCommitted) root.close()
185
+ }
186
+
187
+ // Read back by shell.qml's IPC so a test asserts the protocol swap without OCR.
188
+ function formProtocol() { return form.protocol }
189
+ function formPort() { return form.port }
190
+ function formUri() { return form.uri }
191
+ function formPathLabel() { return form.spec.pathLabel }
192
+ function formChip(name) { return form.chipFor(name) }
193
+ function formFields() { return form.visibleFields() }
194
+ function formFocus() { return form.focusName() }
195
+ function formHostPortWidths() { return form.hostPortWidths() }
196
+ function formPasswordState() { return form.passwordState() }
197
+ function formPasswordEyeCentre() { return form.passwordEyeCentre() }
198
+ function formPasswordHint() { return form.passwordHintText }
199
+ function formNote() { return form.protocol === "NFS" ? "No password needed. The NFS server trusts this computer." : "" }
200
+ function formAction() {
201
+ if (root.saveCommitted) return "Close"
202
+ if (root.saving) return "Saving…"
203
+ if (root.connecting) return "Connecting…"
204
+ return root.retrying ? "Retry" : "Connect and save"
205
+ }
206
+ function formMetrics() { return Math.round(card.padding) + "|" + Math.round(body.spacing) }
207
+ // "contentY|contentHeight|height" of the scroller between the pinned title and buttons, so a test sees the clamp and the scroll.
208
+ function bodyScroll() { return Math.round(body.contentY) + "|" + Math.round(body.contentHeight) + "|" + Math.round(body.scrollItem.height) }
209
+ function formMetricTargets() { return Style.space(16) + "|" + Style.space(12) }
210
+
211
+ // Dialogs rule 6: the title says what you are doing, so it survives a chip swap; the two entry
212
+ // points are two tasks, open() adding a place and openLocation() connecting to one already saved.
213
+ function baseTitle() {
214
+ return root.retrying ? "Connect to a network share" : "Add a network share"
215
+ }
216
+
217
+ function decoded(text) {
218
+ try { return decodeURIComponent(text) } catch (e) { return text }
219
+ }
220
+
221
+ // Sample input: ftps://user@host:2121/path, decomposed only to repopulate the approved form.
222
+ function valuesFor(uri, label, password) {
223
+ var match = String(uri || "").match(/^([a-z][a-z0-9+.-]*):\/\/(.*)$/i)
224
+ if (!match) return { protocol: "SMB", label: label, password: password }
225
+ var schemes = { smb: "SMB", sftp: "SFTP", ftp: "FTPS", ftps: "FTPS",
226
+ dav: "WebDAV", davs: "WebDAV", nfs: "NFS" }
227
+ var scheme = match[1].toLowerCase()
228
+ var protocol = schemes[scheme] || "SMB"
229
+ var tls = scheme !== "ftp" && scheme !== "dav"
230
+ var rest = match[2]
231
+ var slash = rest.indexOf("/")
232
+ var authority = slash < 0 ? rest : rest.substring(0, slash)
233
+ var path = slash < 0 ? "" : root.decoded(rest.substring(slash + 1))
234
+ var at = authority.lastIndexOf("@")
235
+ var userInfo = at < 0 ? "" : authority.substring(0, at)
236
+ var hostPort = at < 0 ? authority : authority.substring(at + 1)
237
+ var host = hostPort
238
+ var port = String(Protocols.defaultPort(protocol, tls))
239
+ if (hostPort.charAt(0) === "[") {
240
+ var bracket = hostPort.indexOf("]")
241
+ if (bracket >= 0 && hostPort.charAt(bracket + 1) === ":") {
242
+ host = hostPort.substring(0, bracket + 1)
243
+ port = hostPort.substring(bracket + 2)
244
+ }
245
+ } else if (hostPort.lastIndexOf(":") >= 0) {
246
+ var colon = hostPort.lastIndexOf(":")
247
+ host = hostPort.substring(0, colon)
248
+ port = hostPort.substring(colon + 1)
249
+ }
250
+ var domain = ""
251
+ var user = root.decoded(userInfo)
252
+ if (protocol === "SMB" && userInfo.indexOf(";") >= 0) {
253
+ var semi = userInfo.indexOf(";")
254
+ domain = root.decoded(userInfo.substring(0, semi))
255
+ user = root.decoded(userInfo.substring(semi + 1))
256
+ }
257
+ return { protocol: protocol, label: label || "", host: host, port: port, path: path,
258
+ domain: domain, user: user, password: password || "",
259
+ tls: tls }
260
+ }
261
+
262
+ function checkDropbox() {
263
+ if (dropboxCheck.running) return
264
+ dropboxCheck.command = ["which", "dropbox-cli"]
265
+ dropboxCheck.running = true
266
+ }
267
+
268
+ // omarchy-launch-terminal runs its argv directly in a real terminal, so the sudo prompt
269
+ // omarchy-pkg-add may need and the install's own progress are both visible to the user.
270
+ function installDropbox() {
271
+ Quickshell.execDetached(["omarchy-launch-terminal", "omarchy", "install", "service", "dropbox"])
272
+ root.close()
273
+ }
274
+
275
+
276
+ Process {
277
+ id: dropboxCheck
278
+ onExited: function (exitCode) { root.dropboxInstalled = exitCode === 0 }
279
+ }
280
+
281
+ // The fade and the rise are the shared reveal of ui/Reveal.qml.
282
+ Flea.Reveal { target: root; shown: root.opened; lift: root.cardItem }
283
+
284
+ Rectangle {
285
+ id: scrim
286
+ anchors.fill: parent
287
+ // Util.alpha bakes the 0.7 scrim strength into the colour, the house idiom ConfirmDialog uses.
288
+ color: Util.alpha(Theme.color.background, 0.7)
289
+
290
+ MouseArea {
291
+ anchors.fill: parent
292
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
293
+ hoverEnabled: true
294
+ onClicked: root.close()
295
+ onWheel: function (wheel) { wheel.accepted = true }
296
+ }
297
+ }
298
+
299
+ // The house dialog shape read off ConfirmDialog.qml: BorderSurface, an accent border, cornerRadius.
300
+ BorderSurface {
301
+ id: card
302
+ width: Theme.cardSpan(Theme.space(380) * Theme.dialogWidthRatio, root.width - 2 * root.clampMargin)
303
+ // Clamped to the window; the body scrolls whatever the clamp cut, see ui/CardScroll.qml.
304
+ height: Theme.cardSpan(body.wanted + contentTopInset + contentBottomInset, root.height - 2 * root.clampMargin)
305
+ x: Theme.cardOrigin(root.width, width)
306
+ y: Theme.cardOrigin(root.height, height)
307
+ color: Theme.color.surface
308
+ borderSpec: Border.flat(Theme.color.accent, Style.normalBorderWidth)
309
+ radius: Style.cornerRadius
310
+ padding: Style.space(16)
311
+
312
+ MouseArea {
313
+ anchors.fill: parent
314
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
315
+ onClicked: {}
316
+ onWheel: function (wheel) { wheel.accepted = true }
317
+ }
318
+
319
+ Flea.CardFrame {
320
+ id: body
321
+ anchors.fill: parent
322
+ anchors.topMargin: card.contentTopInset - Theme.focusClearance
323
+ anchors.bottomMargin: card.contentBottomInset - Theme.focusClearance
324
+ bleed: Theme.focusClearance
325
+ anchors.leftMargin: card.contentLeftInset - Theme.focusClearance
326
+ anchors.rightMargin: card.contentRightInset - Theme.focusClearance
327
+ Keys.onEscapePressed: root.close()
328
+ // Outer rhythm and each section's own header-to-content gap read exact off tailscale/dropbox Panel.qml.
329
+ spacing: Style.space(12)
330
+
331
+ title: Flea.DialogTitle {
332
+ width: parent.width
333
+ text: root.dialogTitle
334
+ }
335
+
336
+ // Network.html places Cancel before the primary action at the card's right edge; the Dropbox install route stays pinned beneath.
337
+ buttons: Column {
338
+ width: parent.width
339
+ spacing: Style.space(12)
340
+
341
+ Row {
342
+ anchors.right: parent.right
343
+ spacing: Theme.spacing.gap
344
+
345
+ Flea.DialogButton {
346
+ id: cancelButton
347
+ label: "Cancel"
348
+ available: !root.saving
349
+ tabHandle: true
350
+ onTabbed: function (from, back) { form.step(from, back ? -1 : 1) }
351
+ onActivated: root.close()
352
+ }
353
+
354
+ Flea.DialogButton {
355
+ id: actionButton
356
+ label: root.formAction()
357
+ primary: true
358
+ available: !root.busy
359
+ tabHandle: true
360
+ onTabbed: function (from, back) { form.step(from, back ? -1 : 1) }
361
+ onActivated: root.submitLocation()
362
+ }
363
+ }
364
+
365
+ PanelSeparator { visible: !root.dropboxInstalled }
366
+
367
+ // Dialogs rule 4: the section is a live install route while Dropbox is absent, and it is
368
+ // held here until providers have a home of their own; installed, it has nothing to say
369
+ // and is not drawn, where it used to draw a button that could never be pressed.
370
+ Column {
371
+ width: parent.width
372
+ visible: !root.dropboxInstalled
373
+ spacing: Style.space(10)
374
+
375
+ PanelSectionHeader {
376
+ text: "DROPBOX"
377
+ }
378
+
379
+ Flea.DialogButton {
380
+ id: dropboxButton
381
+ label: "Install Dropbox"
382
+ available: !root.busy
383
+ tabHandle: true
384
+ onTabbed: function (from, back) { form.step(from, back ? -1 : 1) }
385
+ onActivated: root.installDropbox()
386
+ }
387
+ }
388
+ }
389
+
390
+ Column {
391
+ width: parent.width
392
+ spacing: Style.space(12)
393
+
394
+ NetworkForm {
395
+ id: form
396
+ width: parent.width
397
+ enabled: !root.busy && !root.saveCommitted
398
+ trailing: [cancelButton, actionButton, dropboxButton]
399
+ onSubmitted: root.submitLocation()
400
+
401
+ function labelText() {
402
+ return Protocols.label({ label: form.label, host: form.host, path: form.path })
403
+ }
404
+ }
405
+
406
+ // The slot is always there, two caption lines tall, so an error appearing never moves the buttons.
407
+ Row {
408
+ width: parent.width
409
+ height: Theme.rowHeight
410
+ spacing: Theme.spacing.gap
411
+
412
+ Flea.Glyph {
413
+ visible: root.statusText.length > 0
414
+ width: Theme.font.caption
415
+ height: Theme.font.caption
416
+ name: "alert"
417
+ color: Theme.color.errorOnSurface
418
+ }
419
+
420
+ Text {
421
+ width: parent.width - Theme.font.caption - parent.spacing
422
+ text: root.statusText
423
+ color: Theme.color.errorOnSurface
424
+ font.family: Theme.font.family
425
+ font.pixelSize: Theme.font.caption
426
+ wrapMode: Text.Wrap
427
+ maximumLineCount: 2
428
+ elide: Text.ElideRight
429
+ textFormat: Text.PlainText
430
+ }
431
+ }
432
+ }
433
+ }
434
+ }
435
+ }