flea-qml 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (637) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +511 -2
  3. package/THIRD-PARTY-NOTICES.md +29 -0
  4. package/demos/App.java +5 -0
  5. package/demos/Dockerfile +4 -0
  6. package/demos/Main.kt +3 -0
  7. package/demos/Program.cs +1 -0
  8. package/demos/README.md +12 -0
  9. package/demos/app.dart +3 -0
  10. package/demos/app.deb +0 -0
  11. package/demos/app.js +1 -0
  12. package/demos/backup.tar +0 -0
  13. package/demos/budget.xlsx +0 -0
  14. package/demos/build.sh +2 -0
  15. package/demos/bundle.zip +0 -0
  16. package/demos/clip.mp4 +0 -0
  17. package/demos/data.sqlite +0 -0
  18. package/demos/disk.iso +0 -0
  19. package/demos/engine.cpp +5 -0
  20. package/demos/firmware.bin +0 -0
  21. package/demos/flake.nix +4 -0
  22. package/demos/folder/inside.txt +1 -0
  23. package/demos/font.ttf +0 -0
  24. package/demos/index.html +5 -0
  25. package/demos/index.php +2 -0
  26. package/demos/init.lua +1 -0
  27. package/demos/letter.docx +0 -0
  28. package/demos/lib.rs +3 -0
  29. package/demos/main.c +6 -0
  30. package/demos/main.h +3 -0
  31. package/demos/math-and-diagrams.md +200 -0
  32. package/demos/notes.tar.gz +0 -0
  33. package/demos/notes.txt +3 -0
  34. package/demos/photo.png +0 -0
  35. package/demos/program +2 -0
  36. package/demos/report.pdf +32 -0
  37. package/demos/script.py +1 -0
  38. package/demos/server.go +7 -0
  39. package/demos/settings.json +4 -0
  40. package/demos/slides.pptx +0 -0
  41. package/demos/song.mp3 +0 -0
  42. package/demos/style.css +4 -0
  43. package/demos/tool.rb +1 -0
  44. package/demos/types.ts +2 -0
  45. package/docs/pele.md +23 -0
  46. package/docs/protocol.md +3420 -0
  47. package/docs/temml.md +63 -0
  48. package/index.js +107 -0
  49. package/package.json +34 -4
  50. package/src/archive.js +407 -0
  51. package/src/archiveops.js +728 -0
  52. package/src/backend.js +369 -0
  53. package/src/bulkrename.js +95 -0
  54. package/src/clip-host.js +76 -0
  55. package/src/clip.js +462 -0
  56. package/src/code.js +168 -0
  57. package/src/compare.js +74 -0
  58. package/src/create.js +128 -0
  59. package/src/dirsize.js +147 -0
  60. package/src/figure-svg.js +530 -0
  61. package/src/figure-thread.js +23 -0
  62. package/src/figure.js +132 -0
  63. package/src/find.js +55 -0
  64. package/src/flea.js +39 -0
  65. package/src/fsinfo.js +39 -0
  66. package/src/highlight.js +141 -0
  67. package/src/html.js +52 -0
  68. package/src/kinds.js +89 -0
  69. package/src/listing.js +130 -0
  70. package/src/markdown-html.js +317 -0
  71. package/src/mathml.js +186 -0
  72. package/src/menu.js +180 -0
  73. package/src/meta.js +135 -0
  74. package/src/office.js +810 -0
  75. package/src/order.js +100 -0
  76. package/src/peek.js +49 -0
  77. package/src/pele-wrapper.js +695 -0
  78. package/src/permissions.js +180 -0
  79. package/src/places.js +313 -0
  80. package/src/preview-language.js +10 -0
  81. package/src/terminal-server.js +95 -0
  82. package/src/terminal-shell.js +26 -0
  83. package/src/transfer.js +669 -0
  84. package/src/trash-record.js +41 -0
  85. package/src/trash.js +210 -0
  86. package/src/trashbrowse.js +327 -0
  87. package/src/uistate.js +393 -0
  88. package/src/uistore.js +168 -0
  89. package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
  90. package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
  91. package/src/vendor/LICENSES/MIT-katex.txt +21 -0
  92. package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
  93. package/src/vendor/LICENSES/MIT-pele.txt +40 -0
  94. package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
  95. package/src/vendor/LICENSES/MIT-temml.txt +21 -0
  96. package/src/vendor/pele.js +145 -0
  97. package/src/vendor/temml.mjs +14708 -0
  98. package/src/watch.js +98 -0
  99. package/src/wayland/client.js +109 -0
  100. package/src/wayland/protocol.js +55 -0
  101. package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
  102. package/src/wayland/protocols/wayland.xml +3248 -0
  103. package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
  104. package/src/wayland/resource-io.js +6 -0
  105. package/src/wayland/socket-discovery.js +26 -0
  106. package/src/wayland/transport-posix.js +120 -0
  107. package/src/wayland/transport-win32.js +11 -0
  108. package/src/wayland/transport.js +3 -0
  109. package/src/wayland/win32-resources.js +80 -0
  110. package/src/wayland/win32-wire.js +62 -0
  111. package/test/archive.test.js +80 -0
  112. package/test/bench-markdown-scroll.mjs +190 -0
  113. package/test/clip-host.test.js +113 -0
  114. package/test/code-preview.test.js +35 -0
  115. package/test/compare-ui-paths.test.js +24 -0
  116. package/test/compare.test.js +54 -0
  117. package/test/delete-trash.test.js +67 -0
  118. package/test/dirsize.test.js +138 -0
  119. package/test/file-ops.test.js +307 -0
  120. package/test/file-url.test.js +24 -0
  121. package/test/find-contents.test.js +161 -0
  122. package/test/find-input.test.js +66 -0
  123. package/test/fixtures/pele-parity.json +1006 -0
  124. package/test/highlight-launcher.test.js +35 -0
  125. package/test/html-preview.test.js +22 -0
  126. package/test/input.test.js +15 -0
  127. package/test/keymap.test.js +26 -0
  128. package/test/language-icons.test.js +36 -0
  129. package/test/launcher.test.js +51 -0
  130. package/test/manual-archive-here-ui.mjs +47 -0
  131. package/test/manual-code-scroll.mjs +28 -0
  132. package/test/manual-column-scroll.mjs +24 -0
  133. package/test/manual-compare-ui.mjs +20 -0
  134. package/test/manual-find-status.mjs +37 -0
  135. package/test/manual-folder-focus.mjs +63 -0
  136. package/test/manual-html-security.mjs +23 -0
  137. package/test/manual-html-ui.mjs +30 -0
  138. package/test/manual-syntax-preview.mjs +26 -0
  139. package/test/manual-terminal-lifecycle.mjs +42 -0
  140. package/test/manual-terminal-navigation.mjs +48 -0
  141. package/test/manual-terminal-ui.mjs +47 -0
  142. package/test/manual-trash-ui.mjs +86 -0
  143. package/test/markdown-diagrams.test.js +93 -0
  144. package/test/markdown-html.test.js +105 -0
  145. package/test/mathml.test.js +92 -0
  146. package/test/menu-transfer.test.js +57 -0
  147. package/test/office-preview.test.js +154 -0
  148. package/test/pele-parity.test.js +28 -0
  149. package/test/places.test.js +134 -0
  150. package/test/preview-keys.test.js +60 -0
  151. package/test/preview-language.test.js +22 -0
  152. package/test/status-filename.test.js +20 -0
  153. package/test/transfer-replace-merge.test.js +187 -0
  154. package/test/trash-address.test.js +23 -0
  155. package/test/trash-view.test.js +37 -0
  156. package/test/trashbrowse.test.js +135 -0
  157. package/ui/AboutFacts.qml +78 -0
  158. package/ui/ArchiveCards.qml +95 -0
  159. package/ui/ArchiveCompressDialog.qml +378 -0
  160. package/ui/ArchiveHereConfirm.qml +127 -0
  161. package/ui/ArchivePasswordDialog.qml +257 -0
  162. package/ui/Backend.qml +775 -0
  163. package/ui/BulkOldNames.qml +47 -0
  164. package/ui/BulkRenameDialog.qml +380 -0
  165. package/ui/CardFrame.qml +67 -0
  166. package/ui/CardScroll.qml +79 -0
  167. package/ui/CheckBox.qml +73 -0
  168. package/ui/ChromeBar.qml +360 -0
  169. package/ui/ChromeButton.qml +131 -0
  170. package/ui/ChromeModes.qml +43 -0
  171. package/ui/CodeLines.qml +256 -0
  172. package/ui/CodeRefusal.qml +52 -0
  173. package/ui/CollideConfirm.qml +147 -0
  174. package/ui/CollideHost.qml +167 -0
  175. package/ui/ColumnPane.qml +525 -0
  176. package/ui/ColumnRow.qml +380 -0
  177. package/ui/ColumnsArea.qml +594 -0
  178. package/ui/ColumnsLanding.qml +147 -0
  179. package/ui/CompareView.qml +321 -0
  180. package/ui/ContextMenu.qml +743 -0
  181. package/ui/ConvertDialog.qml +456 -0
  182. package/ui/CountedWorker.qml +7 -0
  183. package/ui/Crumb.qml +64 -0
  184. package/ui/CrumbDrop.qml +25 -0
  185. package/ui/CsvTable.qml +394 -0
  186. package/ui/CursorMark.qml +41 -0
  187. package/ui/DefaultClaim.qml +130 -0
  188. package/ui/DeviceLock.qml +47 -0
  189. package/ui/DeviceMounts.qml +540 -0
  190. package/ui/DialogButton.qml +150 -0
  191. package/ui/DialogField.qml +147 -0
  192. package/ui/DialogHeader.qml +31 -0
  193. package/ui/DialogScrim.qml +20 -0
  194. package/ui/DialogTitle.qml +37 -0
  195. package/ui/Divider.qml +9 -0
  196. package/ui/DropInto.qml +126 -0
  197. package/ui/DropTarget.qml +35 -0
  198. package/ui/DropboxMark.qml +60 -0
  199. package/ui/EmptyState.qml +150 -0
  200. package/ui/EscapeHint.qml +11 -0
  201. package/ui/FactsTable.qml +54 -0
  202. package/ui/FastScrollHandler.qml +476 -0
  203. package/ui/FatNamesConfirm.qml +157 -0
  204. package/ui/Favourites.qml +143 -0
  205. package/ui/FigureService.qml +120 -0
  206. package/ui/FileDrag.qml +267 -0
  207. package/ui/FilterStrip.qml +133 -0
  208. package/ui/FitMetrics.qml +22 -0
  209. package/ui/FlashDriveRows.qml +137 -0
  210. package/ui/FlashHost.qml +72 -0
  211. package/ui/FlashImageRow.qml +104 -0
  212. package/ui/FlashRunner.qml +119 -0
  213. package/ui/FlashStepRow.qml +172 -0
  214. package/ui/FlashStrip.qml +38 -0
  215. package/ui/FlashView.qml +397 -0
  216. package/ui/FleaMark.qml +88 -0
  217. package/ui/FlyoutFade.qml +23 -0
  218. package/ui/FontPane.qml +170 -0
  219. package/ui/Glass.qml +114 -0
  220. package/ui/GlassTagger.qml +59 -0
  221. package/ui/Glyph.qml +64 -0
  222. package/ui/GlyphSolid.qml +22 -0
  223. package/ui/GridArea.qml +664 -0
  224. package/ui/GridTile.qml +325 -0
  225. package/ui/GvfsBridge.qml +164 -0
  226. package/ui/Header.qml +433 -0
  227. package/ui/HoverTimers.qml +39 -0
  228. package/ui/HtmlClip.qml +30 -0
  229. package/ui/HtmlPane.qml +63 -0
  230. package/ui/HyprlandMark.qml +45 -0
  231. package/ui/Ipc.qml +1005 -0
  232. package/ui/IpcControls.qml +7 -0
  233. package/ui/IpcMenuState.qml +48 -0
  234. package/ui/IpcPreviewState.qml +185 -0
  235. package/ui/JumpPath.qml +51 -0
  236. package/ui/KeymapSheet.qml +561 -0
  237. package/ui/KeymapSheetResult.qml +89 -0
  238. package/ui/KindStack.qml +40 -0
  239. package/ui/LangMark.qml +51 -0
  240. package/ui/LangMarkLoader.qml +26 -0
  241. package/ui/List.qml +480 -0
  242. package/ui/LoadingState.qml +54 -0
  243. package/ui/LocalSend.qml +56 -0
  244. package/ui/LocalSendMark.qml +73 -0
  245. package/ui/MarkdownBlockView.qml +311 -0
  246. package/ui/MarkdownBlocks.qml +35 -0
  247. package/ui/MarkdownFigure.qml +254 -0
  248. package/ui/MarkdownImages.qml +72 -0
  249. package/ui/MarkdownList.qml +81 -0
  250. package/ui/MarkdownMathsText.qml +97 -0
  251. package/ui/MarkdownPane.qml +83 -0
  252. package/ui/MarkdownPictures.qml +41 -0
  253. package/ui/MarkdownQuote.qml +52 -0
  254. package/ui/MarkdownRemote.qml +82 -0
  255. package/ui/MarkdownSource.qml +155 -0
  256. package/ui/MarkdownTable.qml +222 -0
  257. package/ui/MarkdownTableScroll.qml +64 -0
  258. package/ui/MarkdownTableWheel.qml +126 -0
  259. package/ui/MarkdownText.qml +87 -0
  260. package/ui/MarkdownWorker.js +132 -0
  261. package/ui/MatchText.qml +99 -0
  262. package/ui/MediaSession.qml +38 -0
  263. package/ui/MediaSound.qml +26 -0
  264. package/ui/MediaStrip.qml +191 -0
  265. package/ui/MediaTrack.qml +36 -0
  266. package/ui/MediaVolume.qml +54 -0
  267. package/ui/MenuActionDialog.qml +396 -0
  268. package/ui/MenuEdgeFade.qml +24 -0
  269. package/ui/MenuHost.qml +227 -0
  270. package/ui/MenuRow.qml +351 -0
  271. package/ui/MountListing.qml +100 -0
  272. package/ui/NetworkDialog.qml +435 -0
  273. package/ui/NetworkForm.qml +426 -0
  274. package/ui/NetworkMounts.qml +913 -0
  275. package/ui/NetworkPlaces.qml +127 -0
  276. package/ui/OpenWithDialog.qml +613 -0
  277. package/ui/Opener.qml +95 -0
  278. package/ui/Pane.qml +1320 -0
  279. package/ui/PaneMenuActions.qml +527 -0
  280. package/ui/PanePath.qml +90 -0
  281. package/ui/PaneRail.qml +268 -0
  282. package/ui/PaneStates.qml +88 -0
  283. package/ui/PaneSwap.qml +339 -0
  284. package/ui/PaneWire.qml +601 -0
  285. package/ui/ParkedWait.qml +9 -0
  286. package/ui/PathEntry.qml +186 -0
  287. package/ui/PathJump.qml +400 -0
  288. package/ui/PdfViewer.qml +297 -0
  289. package/ui/PermissionsDialog.qml +658 -0
  290. package/ui/PermissionsHeadings.qml +31 -0
  291. package/ui/PhoneMounts.qml +67 -0
  292. package/ui/PickerAnswers.qml +75 -0
  293. package/ui/PickerBox.qml +26 -0
  294. package/ui/PickerChrome.qml +295 -0
  295. package/ui/PickerFilter.qml +97 -0
  296. package/ui/PickerGrid.qml +308 -0
  297. package/ui/PickerHeader.qml +28 -0
  298. package/ui/PickerLifecycle.qml +27 -0
  299. package/ui/PickerList.qml +218 -0
  300. package/ui/PickerListing.qml +149 -0
  301. package/ui/PickerPathBar.qml +127 -0
  302. package/ui/PickerPlaces.qml +189 -0
  303. package/ui/PickerRecent.qml +92 -0
  304. package/ui/PickerSave.qml +101 -0
  305. package/ui/PickerSelection.qml +155 -0
  306. package/ui/PickerWindow.qml +846 -0
  307. package/ui/PowerSectorsReader.qml +10 -0
  308. package/ui/PrebuildDriver.qml +146 -0
  309. package/ui/Preview.qml +1005 -0
  310. package/ui/PreviewAnimation.qml +24 -0
  311. package/ui/PreviewArchive.qml +91 -0
  312. package/ui/PreviewColumn.qml +553 -0
  313. package/ui/PreviewEdge.qml +63 -0
  314. package/ui/PreviewFacts.qml +30 -0
  315. package/ui/PreviewFactsLine.qml +34 -0
  316. package/ui/PreviewHtml.qml +233 -0
  317. package/ui/PreviewImage.qml +253 -0
  318. package/ui/PreviewImagePan.qml +13 -0
  319. package/ui/PreviewImageSharp.qml +32 -0
  320. package/ui/PreviewLines.qml +106 -0
  321. package/ui/PreviewMarkdown.qml +706 -0
  322. package/ui/PreviewMedia.qml +250 -0
  323. package/ui/PreviewPdf.qml +482 -0
  324. package/ui/PreviewScroll.qml +201 -0
  325. package/ui/PreviewSwap.qml +335 -0
  326. package/ui/PreviewText.qml +149 -0
  327. package/ui/ProtocolChip.qml +18 -0
  328. package/ui/QuickLookArchive.qml +41 -0
  329. package/ui/QuickLookBar.qml +103 -0
  330. package/ui/QuickLookPrepare.qml +355 -0
  331. package/ui/QuickLookSwap.qml +10 -0
  332. package/ui/QuickLookWarm.qml +65 -0
  333. package/ui/RailDrop.qml +155 -0
  334. package/ui/RailHeading.qml +19 -0
  335. package/ui/RailPlaces.qml +38 -0
  336. package/ui/RailTrashRow.qml +67 -0
  337. package/ui/RenameField.qml +353 -0
  338. package/ui/RendererRetry.qml +11 -0
  339. package/ui/ResizeHandle.qml +52 -0
  340. package/ui/Reveal.qml +54 -0
  341. package/ui/Row.qml +476 -0
  342. package/ui/RowDrag.qml +213 -0
  343. package/ui/RowDropTarget.qml +27 -0
  344. package/ui/RunCard.qml +286 -0
  345. package/ui/Scripts.qml +65 -0
  346. package/ui/SearchStrip.qml +232 -0
  347. package/ui/SelectionBand.qml +140 -0
  348. package/ui/SelectionPreview.qml +370 -0
  349. package/ui/SettingsFavourite.qml +122 -0
  350. package/ui/SettingsGroup.qml +96 -0
  351. package/ui/SettingsHint.qml +12 -0
  352. package/ui/SettingsMetrics.qml +29 -0
  353. package/ui/SettingsPane.qml +178 -0
  354. package/ui/SettingsPanel.qml +547 -0
  355. package/ui/SettingsRail.qml +128 -0
  356. package/ui/SettingsRow.qml +409 -0
  357. package/ui/SettingsRuler.qml +85 -0
  358. package/ui/SettingsSegment.qml +85 -0
  359. package/ui/ShareBrowser.qml +113 -0
  360. package/ui/ShareLink.qml +67 -0
  361. package/ui/ShelfPins.qml +101 -0
  362. package/ui/Sidebar.qml +728 -0
  363. package/ui/SidebarRow.qml +358 -0
  364. package/ui/Spinner.qml +60 -0
  365. package/ui/StableModel.qml +89 -0
  366. package/ui/StateMessage.qml +84 -0
  367. package/ui/StatusBar.qml +512 -0
  368. package/ui/StatusFileName.qml +27 -0
  369. package/ui/TabBar.qml +673 -0
  370. package/ui/TabDragGeometry.qml +60 -0
  371. package/ui/TagMenuMark.qml +52 -0
  372. package/ui/TagRailSection.qml +53 -0
  373. package/ui/TagSlot.qml +40 -0
  374. package/ui/TagState.qml +150 -0
  375. package/ui/TagSwatch.qml +28 -0
  376. package/ui/Taildrop.qml +86 -0
  377. package/ui/TailscaleMark.qml +50 -0
  378. package/ui/TerminalService.qml +69 -0
  379. package/ui/TerminalTab.qml +48 -0
  380. package/ui/TerminalTabs.qml +27 -0
  381. package/ui/Theme.qml +460 -0
  382. package/ui/ThemeColors.qml +43 -0
  383. package/ui/TransferCard.qml +239 -0
  384. package/ui/TrashConfirm.qml +129 -0
  385. package/ui/TrashDropHandler.qml +11 -0
  386. package/ui/TrashHost.qml +202 -0
  387. package/ui/TrashMonitor.qml +30 -0
  388. package/ui/TrashToolbar.qml +19 -0
  389. package/ui/TrashView.qml +492 -0
  390. package/ui/UnlockDialog.qml +450 -0
  391. package/ui/UnlockHost.qml +206 -0
  392. package/ui/UpdateCheck.qml +97 -0
  393. package/ui/UserDirs.qml +25 -0
  394. package/ui/ViewState.qml +565 -0
  395. package/ui/ViewportScrollBar.qml +195 -0
  396. package/ui/ViewportScrollBars.qml +25 -0
  397. package/ui/WebPreview.qml +33 -0
  398. package/ui/WebPreviewView.qml +26 -0
  399. package/ui/WindowBody.qml +829 -0
  400. package/ui/WindowDrag.qml +35 -0
  401. package/ui/boot/Commons/AudioNodes.qml +50 -0
  402. package/ui/boot/Commons/AudioNodesModel.js +96 -0
  403. package/ui/boot/Commons/Border.qml +243 -0
  404. package/ui/boot/Commons/BorderGeometry.js +373 -0
  405. package/ui/boot/Commons/Color.qml +258 -0
  406. package/ui/boot/Commons/I18n.qml +118 -0
  407. package/ui/boot/Commons/InputDevices.qml +112 -0
  408. package/ui/boot/Commons/InputMethodState.qml +38 -0
  409. package/ui/boot/Commons/IpcRegistry.qml +77 -0
  410. package/ui/boot/Commons/Numbers.js +19 -0
  411. package/ui/boot/Commons/Plural.js +91 -0
  412. package/ui/boot/Commons/ShellIpc.qml +12 -0
  413. package/ui/boot/Commons/Style.qml +561 -0
  414. package/ui/boot/Commons/Translations.qml +100 -0
  415. package/ui/boot/Commons/UntypedInput.qml +152 -0
  416. package/ui/boot/Commons/Util.qml +188 -0
  417. package/ui/boot/Commons/qmldir +13 -0
  418. package/ui/boot/LICENSE-omarchy +20 -0
  419. package/ui/boot/Ui/BackgroundMedia.qml +49 -0
  420. package/ui/boot/Ui/BarIconButton.qml +106 -0
  421. package/ui/boot/Ui/BarIconContent.qml +38 -0
  422. package/ui/boot/Ui/BarIndicator.qml +53 -0
  423. package/ui/boot/Ui/BarWidget.qml +50 -0
  424. package/ui/boot/Ui/BorderOverlay.qml +54 -0
  425. package/ui/boot/Ui/BorderSurface.qml +40 -0
  426. package/ui/boot/Ui/Button.qml +224 -0
  427. package/ui/boot/Ui/ButtonGroup.qml +131 -0
  428. package/ui/boot/Ui/ConfirmDialog.qml +134 -0
  429. package/ui/boot/Ui/CursorSurface.qml +42 -0
  430. package/ui/boot/Ui/Dropdown.qml +245 -0
  431. package/ui/boot/Ui/FilterInput.qml +26 -0
  432. package/ui/boot/Ui/IconContentBounds.qml +141 -0
  433. package/ui/boot/Ui/KeyboardPanel.qml +453 -0
  434. package/ui/boot/Ui/MultiSelect.qml +624 -0
  435. package/ui/boot/Ui/NumberField.qml +86 -0
  436. package/ui/boot/Ui/OpticalGlyph.qml +68 -0
  437. package/ui/boot/Ui/OverlayWindow.qml +102 -0
  438. package/ui/boot/Ui/Panel.qml +60 -0
  439. package/ui/boot/Ui/PanelActionButton.qml +105 -0
  440. package/ui/boot/Ui/PanelController.qml +16 -0
  441. package/ui/boot/Ui/PanelHero.qml +112 -0
  442. package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
  443. package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
  444. package/ui/boot/Ui/PanelSeparator.qml +19 -0
  445. package/ui/boot/Ui/PanelSlider.qml +156 -0
  446. package/ui/boot/Ui/PanelToolTip.qml +50 -0
  447. package/ui/boot/Ui/PluginBarApi.qml +89 -0
  448. package/ui/boot/Ui/PointerMoveGate.qml +54 -0
  449. package/ui/boot/Ui/PopupCard.qml +181 -0
  450. package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
  451. package/ui/boot/Ui/SearchableDropdown.qml +354 -0
  452. package/ui/boot/Ui/SizedImage.qml +125 -0
  453. package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
  454. package/ui/boot/Ui/TextField.qml +58 -0
  455. package/ui/boot/Ui/Toggle.qml +118 -0
  456. package/ui/boot/Ui/ToggleSwitch.qml +115 -0
  457. package/ui/boot/Ui/WidgetButton.qml +172 -0
  458. package/ui/boot/Ui/qmldir +41 -0
  459. package/ui/boot/fleatab.qml +50 -0
  460. package/ui/boot/picker.qml +39 -0
  461. package/ui/boot/shell.qml +131 -0
  462. package/ui/boot/tabtearoff.qml +51 -0
  463. package/ui/js/Anchor.js +379 -0
  464. package/ui/js/AnchorHold.js +162 -0
  465. package/ui/js/Archive.js +157 -0
  466. package/ui/js/ArchiveCard.js +44 -0
  467. package/ui/js/ArchiveOps.js +44 -0
  468. package/ui/js/BackReturn.js +118 -0
  469. package/ui/js/BulkRename.js +100 -0
  470. package/ui/js/Buttons.js +54 -0
  471. package/ui/js/ChromeKeys.js +116 -0
  472. package/ui/js/ClipMarks.js +73 -0
  473. package/ui/js/ClipSelection.js +67 -0
  474. package/ui/js/Clipboard.js +179 -0
  475. package/ui/js/Cloud.js +97 -0
  476. package/ui/js/CodeRuns.js +72 -0
  477. package/ui/js/Collide.js +212 -0
  478. package/ui/js/ColumnFit.js +28 -0
  479. package/ui/js/ColumnMenu.js +111 -0
  480. package/ui/js/Columns.js +298 -0
  481. package/ui/js/ColumnsCarry.js +103 -0
  482. package/ui/js/Compare.js +74 -0
  483. package/ui/js/Contrast.js +157 -0
  484. package/ui/js/ControlReader.js +42 -0
  485. package/ui/js/Convert.js +52 -0
  486. package/ui/js/CopyAs.js +52 -0
  487. package/ui/js/Crumbs.js +178 -0
  488. package/ui/js/Csv.js +231 -0
  489. package/ui/js/Density.js +44 -0
  490. package/ui/js/Devices.js +440 -0
  491. package/ui/js/DirSizes.js +180 -0
  492. package/ui/js/Drag.js +360 -0
  493. package/ui/js/DragOut.js +166 -0
  494. package/ui/js/DropDev.js +52 -0
  495. package/ui/js/Dropbox.js +41 -0
  496. package/ui/js/Eject.js +217 -0
  497. package/ui/js/Errors.js +188 -0
  498. package/ui/js/ExtThumbs.js +115 -0
  499. package/ui/js/Facts.js +402 -0
  500. package/ui/js/FigureDate.js +14 -0
  501. package/ui/js/Filter.js +285 -0
  502. package/ui/js/Find.js +46 -0
  503. package/ui/js/Flash.js +184 -0
  504. package/ui/js/FlashCard.js +79 -0
  505. package/ui/js/FlashEndings.js +125 -0
  506. package/ui/js/FlashPane.js +116 -0
  507. package/ui/js/FleaBin.js +12 -0
  508. package/ui/js/Focus.js +504 -0
  509. package/ui/js/FolderSorts.js +108 -0
  510. package/ui/js/FolderViews.js +44 -0
  511. package/ui/js/Format.js +314 -0
  512. package/ui/js/Fuzzy.js +141 -0
  513. package/ui/js/GlassTag.js +72 -0
  514. package/ui/js/Grid.js +33 -0
  515. package/ui/js/GridGeometry.js +90 -0
  516. package/ui/js/GridNames.js +153 -0
  517. package/ui/js/GvfsBridge.js +200 -0
  518. package/ui/js/HostClipboard.js +29 -0
  519. package/ui/js/Icons.js +218 -0
  520. package/ui/js/Input.js +50 -0
  521. package/ui/js/Jump.js +200 -0
  522. package/ui/js/KeyName.js +64 -0
  523. package/ui/js/Keymap.js +401 -0
  524. package/ui/js/Kinds.js +164 -0
  525. package/ui/js/LICENSES/ISC-lucide.txt +43 -0
  526. package/ui/js/LangMarkPaths.js +47 -0
  527. package/ui/js/LangMarks.js +120 -0
  528. package/ui/js/Lists.js +11 -0
  529. package/ui/js/LocalSend.js +39 -0
  530. package/ui/js/LockedMenu.js +63 -0
  531. package/ui/js/MakeDefault.js +186 -0
  532. package/ui/js/MarkBox.js +7 -0
  533. package/ui/js/Markdown.js +119 -0
  534. package/ui/js/MarkdownLists.js +86 -0
  535. package/ui/js/MarkdownMaths.js +58 -0
  536. package/ui/js/MarkdownPictures.js +32 -0
  537. package/ui/js/MarkdownPrepared.js +139 -0
  538. package/ui/js/MarkdownTableFit.js +34 -0
  539. package/ui/js/Marks.js +148 -0
  540. package/ui/js/Marquee.js +96 -0
  541. package/ui/js/Match.js +93 -0
  542. package/ui/js/Material.js +109 -0
  543. package/ui/js/MdBlocks.js +437 -0
  544. package/ui/js/MdBreak.js +71 -0
  545. package/ui/js/MdChunks.js +70 -0
  546. package/ui/js/MdContainer.js +137 -0
  547. package/ui/js/MdDocument.js +337 -0
  548. package/ui/js/MdEmph.js +97 -0
  549. package/ui/js/MdEntity.js +108 -0
  550. package/ui/js/MdEntityTable.js +223 -0
  551. package/ui/js/MdEscape.js +59 -0
  552. package/ui/js/MdFront.js +37 -0
  553. package/ui/js/MdHold.js +32 -0
  554. package/ui/js/MdHtml.js +307 -0
  555. package/ui/js/MdHtmlBlock.js +290 -0
  556. package/ui/js/MdHtmlHeading.js +53 -0
  557. package/ui/js/MdHtmlImage.js +179 -0
  558. package/ui/js/MdInline.js +154 -0
  559. package/ui/js/MdItems.js +212 -0
  560. package/ui/js/MdLeaf.js +309 -0
  561. package/ui/js/MdLink.js +196 -0
  562. package/ui/js/MdMath.js +67 -0
  563. package/ui/js/MdParagraphs.js +138 -0
  564. package/ui/js/MdRefs.js +232 -0
  565. package/ui/js/MdResolve.js +226 -0
  566. package/ui/js/MdRun.js +300 -0
  567. package/ui/js/MdUrl.js +226 -0
  568. package/ui/js/Menu.js +514 -0
  569. package/ui/js/MenuContext.js +85 -0
  570. package/ui/js/MenuFit.js +13 -0
  571. package/ui/js/MenuRefresh.js +74 -0
  572. package/ui/js/MenuWheel.js +35 -0
  573. package/ui/js/Messages.js +186 -0
  574. package/ui/js/Motion.js +16 -0
  575. package/ui/js/Mounts.js +320 -0
  576. package/ui/js/MouseNav.js +13 -0
  577. package/ui/js/Nav.js +329 -0
  578. package/ui/js/NetFs.js +26 -0
  579. package/ui/js/OpenWith.js +83 -0
  580. package/ui/js/Ops.js +585 -0
  581. package/ui/js/Palette.js +33 -0
  582. package/ui/js/PathBar.js +260 -0
  583. package/ui/js/Permissions.js +179 -0
  584. package/ui/js/Phones.js +112 -0
  585. package/ui/js/Picker.js +353 -0
  586. package/ui/js/PlaceMenu.js +96 -0
  587. package/ui/js/Places.js +265 -0
  588. package/ui/js/PreviewAsk.js +21 -0
  589. package/ui/js/PreviewKeys.js +155 -0
  590. package/ui/js/PreviewSettle.js +29 -0
  591. package/ui/js/PreviewSwap.js +101 -0
  592. package/ui/js/PropertyFacts.js +144 -0
  593. package/ui/js/Protocols.js +296 -0
  594. package/ui/js/QuickLookKinds.js +27 -0
  595. package/ui/js/QuickLookRect.js +24 -0
  596. package/ui/js/RailDrop.js +51 -0
  597. package/ui/js/RailKeys.js +87 -0
  598. package/ui/js/RailMenu.js +133 -0
  599. package/ui/js/Recent.js +135 -0
  600. package/ui/js/RecentMode.js +156 -0
  601. package/ui/js/Reload.js +60 -0
  602. package/ui/js/Renderer.js +9 -0
  603. package/ui/js/RunFile.js +143 -0
  604. package/ui/js/Scripts.js +28 -0
  605. package/ui/js/Scroll.js +304 -0
  606. package/ui/js/ScrollOff.js +69 -0
  607. package/ui/js/Search.js +478 -0
  608. package/ui/js/Selection.js +97 -0
  609. package/ui/js/Settings.js +476 -0
  610. package/ui/js/SettingsAbout.js +97 -0
  611. package/ui/js/SettingsShelf.js +52 -0
  612. package/ui/js/SheetKeys.js +42 -0
  613. package/ui/js/SheetQuery.js +281 -0
  614. package/ui/js/ShelfPile.js +27 -0
  615. package/ui/js/SlowClick.js +53 -0
  616. package/ui/js/SlowOp.js +6 -0
  617. package/ui/js/Sort.js +134 -0
  618. package/ui/js/Startup.js +63 -0
  619. package/ui/js/StateWords.js +17 -0
  620. package/ui/js/Status.js +238 -0
  621. package/ui/js/Swap.js +166 -0
  622. package/ui/js/TabMove.js +39 -0
  623. package/ui/js/Tabs.js +751 -0
  624. package/ui/js/Tags.js +134 -0
  625. package/ui/js/Taildrop.js +128 -0
  626. package/ui/js/Tap.js +180 -0
  627. package/ui/js/TextSize.js +107 -0
  628. package/ui/js/Thumbs.js +158 -0
  629. package/ui/js/Transfer.js +172 -0
  630. package/ui/js/Trash.js +84 -0
  631. package/ui/js/TrashDates.js +47 -0
  632. package/ui/js/TrashDrop.js +64 -0
  633. package/ui/js/UiState.js +438 -0
  634. package/ui/js/Unlock.js +152 -0
  635. package/ui/js/Update.js +130 -0
  636. package/ui/js/UserDirs.js +56 -0
  637. package/ui/qmldir +230 -0
@@ -0,0 +1,438 @@
1
+ .pragma library
2
+
3
+ // ui/ViewState.qml's one-writer bookkeeping: saved/inflight/pending are patch bytes, pinned by tests/js/uistate.js.
4
+
5
+ // The window's own read of ui.json: an unreadable document stays as written and says so, while no file at all is a first launch.
6
+ function fromFile(text) {
7
+ try {
8
+ var found = JSON.parse(text)
9
+ if (found && typeof found === "object" && !Array.isArray(found)) {
10
+ return { state: found, unreadable: false }
11
+ }
12
+ } catch (e) {
13
+ // A hand edit this cannot parse, which is the ordinary way in and is not an error here.
14
+ }
15
+ return { state: {}, unreadable: text.length > 0 }
16
+ }
17
+
18
+ // The one sentence for a ui.json that could not be read when favorites were refreshed, said by this module and by ViewState.
19
+ var FAVOURITES_UNREAD = "Favorites could not be refreshed because ui.json could not be read. The old list stays."
20
+
21
+ // External favourites update independently of this window's settings drafts and pending patches.
22
+ function refreshedFavourites(state, text) {
23
+ var read = fromFile(text)
24
+ var places = read.state.places
25
+ if (text.length === 0 || read.unreadable || (places !== undefined && (!places || typeof places !== "object" || Array.isArray(places)))
26
+ || (places && places.favourites !== undefined && !Array.isArray(places.favourites)))
27
+ return { state: state, error: FAVOURITES_UNREAD }
28
+ var records = places && places.favourites || []
29
+ if (JSON.stringify((state.places || {}).favourites || []) === JSON.stringify(records))
30
+ return { state: state, error: "" }
31
+ return { state: withGroup(state, "places", { favourites: records }), error: "" }
32
+ }
33
+
34
+ // Compare a save with this window's intent, because the writer response can include concurrent edits.
35
+ function favouritesAfter(records, operation) {
36
+ var next = records.slice()
37
+ if (operation.op === "add") next.push(operation.record)
38
+ else if (operation.op === "remove") next.splice(operation.index, 1)
39
+ else if (operation.op === "move") next.splice(operation.to, 0, next.splice(operation.index, 1)[0])
40
+ else if (operation.op === "rename") next[operation.index] = Object.assign({}, next[operation.index], { label: operation.label })
41
+ return next
42
+ }
43
+
44
+ // Per-window keys name where a window is rather than how Flea behaves, so no window ever takes them from the file.
45
+ var WINDOW_KEYS = ["view", "pickerView", "columnWidths", "dual", "lastPath", "lastTabs",
46
+ "trashSweptOn", "stateVersion", "sort", "previewFacts"]
47
+
48
+ function isWindowKey(key) {
49
+ return WINDOW_KEYS.indexOf(key) >= 0
50
+ }
51
+
52
+ // Per-window leaves stay per window like the sidebar: a change still writes the file, but open windows keep their own.
53
+ var WINDOW_LEAF_KEYS = ["places.rail", "preview.column", "preview.thumbSize"]
54
+
55
+ function isWindowLeaf(key, leaf) {
56
+ return WINDOW_LEAF_KEYS.indexOf(key + "." + leaf) >= 0
57
+ }
58
+
59
+ // Sample patch: {"columns":["name","bogus"]} is refused whole while {"columns":["name","size"]} retries; only schema-invalid shapes prune.
60
+ function isPatchInvalid(patchText) {
61
+ return invalidKeys(patchText).length > 0
62
+ }
63
+
64
+ // Sample patch: {"columns":["name","bogus"],"density":"normal"} refuses ["columns"] alone, so a valid key beside it is never pruned.
65
+ function invalidKeys(patchText) {
66
+ var refused = []
67
+ var patch = null
68
+ try {
69
+ patch = JSON.parse(patchText)
70
+ } catch (e) {
71
+ return refused
72
+ }
73
+ if (!patch || typeof patch !== "object" || Array.isArray(patch))
74
+ return refused
75
+ if (patch.columns !== undefined) {
76
+ var cols = patch.columns
77
+ var bad = !Array.isArray(cols) || cols.indexOf("name") < 0
78
+ if (!bad) {
79
+ var seen = {}
80
+ var keys = ["name", "mode", "size", "date", "kind"]
81
+ for (var i = 0; i < cols.length; i++) {
82
+ if (keys.indexOf(cols[i]) < 0 || seen[cols[i]]) { bad = true; break }
83
+ }
84
+ }
85
+ if (bad)
86
+ refused.push("columns")
87
+ }
88
+ if (patch.places !== undefined && (patch.places === null || typeof patch.places !== "object" || Array.isArray(patch.places)))
89
+ refused.push("places")
90
+ return refused
91
+ }
92
+
93
+ // True when text parses as a JSON object; empty or garbage is ignored until the next valid write.
94
+ function parsesAsObject(text) {
95
+ try {
96
+ var found = JSON.parse(text)
97
+ return found && typeof found === "object" && !Array.isArray(found)
98
+ } catch (e) {
99
+ return false
100
+ }
101
+ }
102
+
103
+ // A settler's exit and its collected text land in either order, so only a whole answer is ever read.
104
+ function landed(answer, half) {
105
+ return Object.assign({}, answer, half)
106
+ }
107
+
108
+ // An empty text is an answer too: a run that says nothing has still finished saying it.
109
+ function whole(answer) {
110
+ return answer.code !== undefined && answer.text !== undefined
111
+ }
112
+
113
+ // The whole answer a settler that never started is given: no real exit status is negative.
114
+ var NEVER_RAN = { code: -1, text: "" }
115
+
116
+ // A settler that cannot start raises no exited, only running going false, and a real exit lands its status before that false.
117
+ function neverRan(answer, running) {
118
+ return !running && answer.code === undefined
119
+ }
120
+
121
+ // A refused write queues its prune behind a running settle instead of hijacking that settle's mode.
122
+ function pruneAsk(running, failedPatch) {
123
+ return running ? { queue: failedPatch, start: "" } : { queue: "", start: failedPatch }
124
+ }
125
+
126
+ // A settle stays pending until both halves land, so one half landed still counts as running.
127
+ function settleBusy(running, mode, answer) {
128
+ return running || (mode.length > 0 && !whole(answer))
129
+ }
130
+
131
+ // A settle's end spends a queued prune before a dirty re-read, keeping the dirty flag across the prune so the re-read still runs after it.
132
+ function settleNext(dirty, pruneQueued) {
133
+ if (pruneQueued.length > 0)
134
+ return "prune"
135
+ if (dirty)
136
+ return "apply"
137
+ return "idle"
138
+ }
139
+
140
+ // Drops only refused keys a retry can never land, keeping a valid key and a newer owed value the refused writer never carried.
141
+ function dropInvalid(unsaved, inflightText) {
142
+ var refused = invalidKeys(inflightText)
143
+ if (refused.length === 0)
144
+ return unsaved
145
+ var inflight = JSON.parse(inflightText)
146
+ var out = {}
147
+ for (var k in unsaved)
148
+ out[k] = unsaved[k]
149
+ for (var r = 0; r < refused.length; r++) {
150
+ var key = refused[r]
151
+ if (out[key] === undefined)
152
+ continue
153
+ if (isGroup(out[key]) && isGroup(inflight[key])) {
154
+ var kept = {}
155
+ var any = false
156
+ for (var leaf in out[key]) {
157
+ if (inflight[key][leaf] !== undefined
158
+ && JSON.stringify(out[key][leaf]) === JSON.stringify(inflight[key][leaf]))
159
+ continue
160
+ kept[leaf] = out[key][leaf]
161
+ any = true
162
+ }
163
+ if (any)
164
+ out[key] = kept
165
+ else
166
+ delete out[key]
167
+ } else if (JSON.stringify(out[key]) === JSON.stringify(inflight[key])) {
168
+ delete out[key]
169
+ }
170
+ }
171
+ return out
172
+ }
173
+
174
+ // Reverts only refused keys still showing the refused value, so a newer change made behind the refused writer survives.
175
+ function revertedState(state, inflightText, settled) {
176
+ var refused = invalidKeys(inflightText)
177
+ if (refused.length === 0)
178
+ return state
179
+ var inflight = null
180
+ try {
181
+ inflight = JSON.parse(inflightText)
182
+ } catch (e) {
183
+ return state
184
+ }
185
+ if (!inflight || typeof inflight !== "object" || !settled)
186
+ return state
187
+ var out = {}
188
+ for (var s in state)
189
+ out[s] = state[s]
190
+ for (var r = 0; r < refused.length; r++) {
191
+ var key = refused[r]
192
+ if (settled[key] === undefined || inflight[key] === undefined)
193
+ continue
194
+ if (isGroup(inflight[key]) && isGroup(settled[key]) && isGroup(out[key])) {
195
+ var group = {}
196
+ for (var h in out[key])
197
+ group[h] = out[key][h]
198
+ for (var leaf in inflight[key]) {
199
+ if (JSON.stringify(group[leaf]) !== JSON.stringify(inflight[key][leaf]))
200
+ continue
201
+ if (settled[key][leaf] !== undefined)
202
+ group[leaf] = settled[key][leaf]
203
+ else
204
+ delete group[leaf]
205
+ }
206
+ out[key] = group
207
+ } else if (JSON.stringify(out[key]) === JSON.stringify(inflight[key])) {
208
+ out[key] = settled[key]
209
+ }
210
+ }
211
+ return out
212
+ }
213
+
214
+ // A change another window saved: preference keys the file names and this window does not owe take the file's value, never clobbering owed leaves or in-flight writes.
215
+ function applyExternal(state, unsaved, text) {
216
+ var read = fromFile(text)
217
+ if (read.unreadable)
218
+ return { state: state, changed: false }
219
+ var file = read.state
220
+ var out = {}
221
+ for (var s in state)
222
+ out[s] = state[s]
223
+ var changed = false
224
+ for (var key in file) {
225
+ if (isWindowKey(key))
226
+ continue
227
+ var value = file[key]
228
+ if (key === "places" && isGroup(value)) {
229
+ var merged = {}
230
+ for (var f in value) {
231
+ if (f !== "favourites")
232
+ merged[f] = value[f]
233
+ }
234
+ var held = state.places || {}
235
+ if (held.favourites !== undefined)
236
+ merged.favourites = held.favourites
237
+ var owedPlaces = unsaved ? unsaved.places : undefined
238
+ if (isGroup(owedPlaces)) {
239
+ for (var leaf in owedPlaces) {
240
+ if (leaf === "favourites")
241
+ continue
242
+ if (held[leaf] !== undefined)
243
+ merged[leaf] = held[leaf]
244
+ else
245
+ delete merged[leaf]
246
+ }
247
+ }
248
+ if (held.rail !== undefined)
249
+ merged.rail = held.rail
250
+ if (JSON.stringify(merged) !== JSON.stringify(state.places)) {
251
+ out.places = merged
252
+ changed = true
253
+ }
254
+ continue
255
+ }
256
+ var owed = unsaved ? unsaved[key] : undefined
257
+ if (owed !== undefined) {
258
+ if (isGroup(owed) && isGroup(value) && !isWholeKey(key)) {
259
+ var group = {}
260
+ for (var g in value)
261
+ group[g] = value[g]
262
+ var current = state[key] || {}
263
+ for (var o in owed) {
264
+ if (current[o] !== undefined)
265
+ group[o] = current[o]
266
+ else
267
+ delete group[o]
268
+ }
269
+ for (var w in group) {
270
+ if (isWindowLeaf(key, w)) {
271
+ if (current[w] !== undefined)
272
+ group[w] = current[w]
273
+ else
274
+ delete group[w]
275
+ }
276
+ }
277
+ if (JSON.stringify(group) !== JSON.stringify(state[key])) {
278
+ out[key] = group
279
+ changed = true
280
+ }
281
+ }
282
+ continue
283
+ }
284
+ if (isGroup(value) && isGroup(state[key])) {
285
+ var anyLeafWindow = false
286
+ for (var vl in value) {
287
+ if (isWindowLeaf(key, vl)) {
288
+ anyLeafWindow = true
289
+ break
290
+ }
291
+ }
292
+ if (anyLeafWindow) {
293
+ var leafGroup = {}
294
+ for (var vg in value) {
295
+ if (!isWindowLeaf(key, vg))
296
+ leafGroup[vg] = value[vg]
297
+ }
298
+ var heldGroup = state[key] || {}
299
+ for (var hg in heldGroup) {
300
+ if (isWindowLeaf(key, hg))
301
+ leafGroup[hg] = heldGroup[hg]
302
+ }
303
+ if (JSON.stringify(leafGroup) !== JSON.stringify(state[key])) {
304
+ out[key] = leafGroup
305
+ changed = true
306
+ }
307
+ continue
308
+ }
309
+ }
310
+ if (JSON.stringify(value) !== JSON.stringify(state[key])) {
311
+ out[key] = value
312
+ changed = true
313
+ }
314
+ }
315
+ return { state: changed ? out : state, changed: changed }
316
+ }
317
+
318
+ // A copy of the document with one top-level key replaced, and the nested version of the same. QML
319
+ // notifies on assignment and not on a mutation, so every writer rebuilds rather than reaching in;
320
+ // the nested one merges into the group beside it, because a whole-group assignment would take the
321
+ // half a writer holds as the whole of it. ui/ViewState.qml runs both over two documents at once:
322
+ // the state it draws from, and the patch it owes the state file.
323
+ function withKey(state, key, value) {
324
+ var out = {}
325
+ for (var s in state)
326
+ out[s] = state[s]
327
+ out[key] = value
328
+ return out
329
+ }
330
+
331
+ function withGroup(state, key, next) {
332
+ var group = {}
333
+ var held = state[key] || {}
334
+ for (var h in held)
335
+ group[h] = held[h]
336
+ for (var n in next)
337
+ group[n] = next[n]
338
+ return withKey(state, key, group)
339
+ }
340
+
341
+ // The book a window starts with: nothing of its own written yet, and no writer running. Its own read
342
+ // of the file is not a patch it sent, so `saved` starts empty rather than holding what it read.
343
+ function book() {
344
+ return { saved: "", inflight: "", pending: "" }
345
+ }
346
+
347
+ // A change asks for a write. The answer is the next book plus `start`, the patch to launch now.
348
+ function asked(b, patch) {
349
+ // The newest patch this window has landed or has on its way, so asking for exactly those bytes
350
+ // again sends nothing and a refused one is never short-circuited.
351
+ if (patch === (b.pending || b.inflight || b.saved)) {
352
+ return { saved: b.saved, inflight: b.inflight, pending: b.pending, start: "" }
353
+ }
354
+ // One writer at a time, and the newest patch waits rather than being dropped on the floor.
355
+ if (b.inflight.length > 0) {
356
+ return { saved: b.saved, inflight: b.inflight, pending: patch, start: "" }
357
+ }
358
+ return { saved: b.saved, inflight: patch, pending: "", start: patch }
359
+ }
360
+
361
+ // The writer exited. The answer is the next book plus `start`, and `failed` for the pane to report.
362
+ // `owed` is what the window still owes NOW and is what a queued writer launches with, because the
363
+ // bytes waiting in `pending` were built before this writer landed: they still name the settings it
364
+ // just stored, and re-sending one writes this window's own copy of it over whatever another window
365
+ // or the CLI put there in between. A refusal changes nothing, so there `owed` is those same bytes.
366
+ function exited(b, code, owed) {
367
+ // Nothing waiting, or nothing left owed once this writer's own settings came out of it, which a
368
+ // value changed and changed back under one writer produces: an empty patch is a process and a
369
+ // rename spent on a document that would come out byte for byte the same.
370
+ var next = (b.pending.length > 0 && owed !== "{}") ? owed : ""
371
+ return {
372
+ // Only a zero status proves the patch reached the file: src/main.rs exits 2 on a refused
373
+ // patch and on a state directory it could not write, and the change is on screen either way.
374
+ saved: code === 0 ? b.inflight : b.saved,
375
+ inflight: next,
376
+ pending: "",
377
+ start: next,
378
+ failed: code !== 0
379
+ }
380
+ }
381
+
382
+ // What is still owed once the patch a writer landed is taken out of it. A setting is only cleared
383
+ // when what the window owes for it now is what that writer carried: a change made while the writer
384
+ // ran is a newer value for the same setting, and the file does not have that one yet.
385
+ function acknowledged(unsaved, patch) {
386
+ var landed
387
+ try {
388
+ landed = JSON.parse(patch)
389
+ } catch (e) {
390
+ // Bytes this file built itself, so a parse failure clears nothing rather than clearing wrong.
391
+ return unsaved
392
+ }
393
+ if (!landed || typeof landed !== "object" || Array.isArray(landed))
394
+ return unsaved
395
+ var out = {}
396
+ for (var key in unsaved) {
397
+ var still = stillOwed(unsaved[key], landed[key], key)
398
+ if (still !== undefined)
399
+ out[key] = still
400
+ }
401
+ return out
402
+ }
403
+
404
+ // One key of the owed patch against the same key of the landed one: `undefined` when the writer took
405
+ // all of it, and otherwise what is left. Two objects are a settings group and are walked leaf by
406
+ // leaf, because changeLeaf owes the leaf alone and clearing the group would drop a leaf beside it
407
+ // that no writer has taken yet. A map (changeMapEntries) owes entry by entry, which is the same
408
+ // walk. A whole-value object key below is the exception: it is compared and cleared whole, because
409
+ // src/uischema.rs Rule::LastTabs stands or falls together and a half value is refused whole.
410
+ function stillOwed(owed, landed, key) {
411
+ if (landed === undefined)
412
+ return owed
413
+ if (isWholeKey(key) && isGroup(owed) && isGroup(landed))
414
+ return JSON.stringify(owed) === JSON.stringify(landed) ? undefined : owed
415
+ if (isGroup(owed) && isGroup(landed)) {
416
+ var kept = {}
417
+ var any = false
418
+ for (var leaf in owed) {
419
+ if (JSON.stringify(owed[leaf]) === JSON.stringify(landed[leaf]))
420
+ continue
421
+ kept[leaf] = owed[leaf]
422
+ any = true
423
+ }
424
+ return any ? kept : undefined
425
+ }
426
+ return JSON.stringify(owed) === JSON.stringify(landed) ? undefined : owed
427
+ }
428
+
429
+ // A settings group, which is the only shape withGroup builds: an array is a whole key's value.
430
+ function isGroup(value) {
431
+ return value !== null && typeof value === "object" && !Array.isArray(value)
432
+ }
433
+
434
+ // Whole-value object keys: owed and cleared whole, never leaf by leaf. Today only lastTabs, whose
435
+ // src/uischema.rs Rule::LastTabs takes exactly paths plus index together.
436
+ function isWholeKey(key) {
437
+ return key === "lastTabs"
438
+ }
@@ -0,0 +1,152 @@
1
+ .pragma library
2
+ .import "Devices.js" as Devices
3
+ .import "Format.js" as Format
4
+
5
+ // Unlock (U039): the dialog's sentences and the udisks answers it parses; a passphrase goes only to the child's stdin.
6
+
7
+ // Whole sentences with "%1" for the drive's label, filled by Format.fill.
8
+ var WORDS = {
9
+ title: "Unlock %1",
10
+ unlocking: "Unlocking %1…",
11
+ wrong: "That passphrase did not unlock %1.",
12
+ unlocked: "Unlocked and mounted %1.",
13
+ lockFailed: "%1 was unmounted but could not be locked; close what is using it.",
14
+ mountFailed: "%1 was unlocked but could not be mounted.",
15
+ unlockFailed: "%1 could not be unlocked."
16
+ }
17
+
18
+ // Sample input: the label of the locked rail row the dialog opened over.
19
+ function title(label) {
20
+ return Format.fill(WORDS.title, label || "")
21
+ }
22
+
23
+ // Sample input: "Unlocked /dev/sda1 as /dev/dm-0.", the line udisksctl unlock prints.
24
+ function parseUnlocked(output) {
25
+ var m = String(output || "").match(/as\s+(\/dev\/\S+)/)
26
+ return m ? m[1].replace(/[.,;:\s]+$/, "") : ""
27
+ }
28
+
29
+ // Sample input: "Backup", the locked rail row's own label.
30
+ function unlockingNote(label) {
31
+ return Format.fill(WORDS.unlocking, label || "")
32
+ }
33
+
34
+ // Sample input: "Backup", the drive the passphrase did not open.
35
+ function wrongNote(label) {
36
+ return Format.fill(WORDS.wrong, label || "")
37
+ }
38
+
39
+ // Sample input: "Backup", the drive just unlocked and mounted.
40
+ function unlockedNote(label) {
41
+ return Format.fill(WORDS.unlocked, label || "")
42
+ }
43
+
44
+ // Sample input: "Backup", the drive unmounted but still unlocked.
45
+ function lockNote(label) {
46
+ return Format.fill(WORDS.lockFailed, label || "")
47
+ }
48
+
49
+ // Sample: "Mounted /dev/dm-0 at /run/media/gm/My Backup." ends with a period.
50
+ function parseMounted(output) {
51
+ var m = String(output || "").match(/\bat\s+(\/.*?)\.?$/m)
52
+ return m ? m[1] : ""
53
+ }
54
+
55
+ // Sample input: "Backup", the drive unlocked but never mounted.
56
+ function mountNote(label) {
57
+ return Format.fill(WORDS.mountFailed, label || "")
58
+ }
59
+
60
+ // Sample input: "Backup", the drive whose unlock failed for a reason other than the passphrase.
61
+ function unlockFailedNote(label) {
62
+ return Format.fill(WORDS.unlockFailed, label || "")
63
+ }
64
+
65
+ // Sample input: "Error unlocking /dev/sdb1: GDBus.Error:org.freedesktop.UDisks2.Error.Failed: x", answered with the error name.
66
+ function parseDbusError(output) {
67
+ var m = String(output || "").match(/GDBus\.Error:([A-Za-z0-9._-]+)/)
68
+ return m ? m[1] : ""
69
+ }
70
+
71
+ // Sample input: "/dev/sdb1"; udisksctl opens --key-file as a path, so "-" names a file and stdin is /dev/stdin.
72
+ function unlockArgv(device) {
73
+ return ["udisksctl", "unlock", "--block-device", String(device || ""), "--key-file", "/dev/stdin"]
74
+ }
75
+
76
+ // Sample input: "Error unlocking /dev/sda1: GDBus.Error:org.freedesktop.UDisks2.Error.Failed: Incorrect passphrase." reads as a wrong passphrase; only the error name decides, so every Failed does, and any other name (NotAuthorized among them) reads as could not be unlocked.
77
+ function refusalNote(stderr, label) {
78
+ return parseDbusError(stderr) === "org.freedesktop.UDisks2.Error.Failed" ? wrongNote(label) : unlockFailedNote(label)
79
+ }
80
+
81
+ // Sample input: the rail's device rows and "/dev/loop0"; the locked row for that device, or null before the rail lists it.
82
+ function lockedRow(entries, device) {
83
+ var rows = entries || []
84
+ for (var i = 0; i < rows.length; i++) {
85
+ if (rows[i] && rows[i].locked === true && String(rows[i].device || "") === String(device || ""))
86
+ return rows[i]
87
+ }
88
+ return null
89
+ }
90
+
91
+ // Sample input: [], one locked fallback row and "/dev/loop0"; the locked row wherever the list lives, rail first.
92
+ function namingRow(primary, fallback, device) {
93
+ return lockedRow(primary, device) || lockedRow(fallback, device)
94
+ }
95
+
96
+ // Sample input: "crypto_LUKS" with "2", the fstype and FSVER lsblk reports for a LUKS2 container.
97
+ function cryptoName(fstype, fsver) {
98
+ if (String(fstype || "").toLowerCase() === "crypto_luks") {
99
+ if (String(fsver || "") === "2")
100
+ return "LUKS2"
101
+ if (String(fsver || "") === "1")
102
+ return "LUKS1"
103
+ return "LUKS"
104
+ }
105
+ var name = String(fstype || "").replace(/^crypto_/i, "").toUpperCase()
106
+ return name.length > 0 ? name : "LUKS"
107
+ }
108
+
109
+ // Sample input: "Backup", "500.0 GB", "LUKS2", the name row under the title, one template per shape.
110
+ function subtitle(label, sizeText, crypto) {
111
+ var name = String(label || "")
112
+ var size = String(sizeText || "")
113
+ var kind = String(crypto || "")
114
+ if (size.length > 0 && kind.length > 0)
115
+ return "%1 · %2 · %3".arg(name).arg(size).arg(kind)
116
+ if (size.length > 0)
117
+ return "%1 · %2".arg(name).arg(size)
118
+ if (kind.length > 0)
119
+ return "%1 · %2".arg(name).arg(kind)
120
+ return name
121
+ }
122
+
123
+ // Sample input: the lsblk body and "/dev/mapper/luks-vault", answered with its container "/dev/sdb1", or "" when gone.
124
+ function backingFor(body, cryptDevice) {
125
+ var tree
126
+ try {
127
+ tree = JSON.parse(String(body || ""))
128
+ } catch (e) {
129
+ return ""
130
+ }
131
+ var want = String(cryptDevice || "")
132
+ var nodes = (tree && tree.blockdevices) || []
133
+ for (var i = 0; i < nodes.length; i++) {
134
+ var found = backingIn(nodes[i], want)
135
+ if (found.length > 0)
136
+ return found
137
+ }
138
+ return ""
139
+ }
140
+
141
+ // A crypt leaf's parent is the container udisksctl lock takes, whatever depth it sits at; no other type has one.
142
+ function backingIn(node, want) {
143
+ var kids = node.children || []
144
+ for (var i = 0; i < kids.length; i++) {
145
+ if (String(kids[i].type || "") === "crypt" && Devices.devicePath(kids[i]) === want)
146
+ return Devices.devicePath(node)
147
+ var deeper = backingIn(kids[i], want)
148
+ if (deeper.length > 0)
149
+ return deeper
150
+ }
151
+ return ""
152
+ }