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,396 @@
1
+ import QtQuick
2
+ import qs.Commons
3
+ import "." as Flea
4
+ import "js/Format.js" as Format
5
+ import "js/PropertyFacts.js" as PropertyFacts
6
+ import "js/Tags.js" as Tags
7
+
8
+ // Menu-only actions share the existing card, field and button language.
9
+ FocusScope {
10
+ id: root
11
+ anchors.fill: parent
12
+ visible: opened || opacity > 0
13
+ // Closed means no input, even while the fade-out is still drawn.
14
+ enabled: opened
15
+ opacity: 0
16
+ Flea.Reveal { target: root; shown: root.opened; lift: card }
17
+ property bool opened: false
18
+ property string action: ""
19
+ property int requestId: 0
20
+ property string folder: ""
21
+ property var facts: ({})
22
+ // A folder's walk as the card knows it, null for anything else; the Size and Contains lines read it as it moves.
23
+ property var walk: null
24
+ // A file's codec, bit rate or photo facts as the facts reply sent them, empty until it lands; the pairs between Size and Modified read it.
25
+ property var extra: ({})
26
+ property string errorText: ""
27
+ property bool busy: false
28
+ property bool committing: false
29
+ property bool checkPending: false
30
+ property Item focusHolder: null
31
+ readonly property bool inputAction: action === "newFile" || action === "moveTo" || action === "copyTo"
32
+ readonly property bool deletionActive: action === "deletePermanently" && committing
33
+ readonly property bool canSubmit: !busy && inputAction && field.text.length > 0
34
+ // The lines that change in place while the folder counts; the model names them and is not rebuilt as the count moves.
35
+ readonly property var liveLines: facts.ok ? ({size: PropertyFacts.size(facts.bytes, walk), contains: PropertyFacts.contains(walk)}) : ({})
36
+ // Raw.html and Properties040: a photo's Camera, Lens, Exposure and Taken, the ones its EXIF names, sit before Modified.
37
+ readonly property var extraPairs: PropertyFacts.extraPairs(Object.assign({ok: root.facts.ok}, root.extra), root.facts.photo)
38
+ readonly property string title: ({moveTo: "Move to", copyTo: "Copy to", properties: "Properties", newFile: "New file", deletePermanently: "Delete permanently"})[action] || ""
39
+ // The card and its scrim step aside for the confirmation, and stay aside while it fades out with a closing dialog.
40
+ readonly property bool cardShown: !confirmation.opened && (root.opened || !confirmation.visible)
41
+ // Cleanup a closing reply defers until the fade ended, so the card holds still while it fades out.
42
+ property var settle: null
43
+ readonly property var cardItem: card
44
+ readonly property var confirmationItem: confirmation
45
+ readonly property var closeItem: closeButton
46
+ readonly property var submitItem: submitButton
47
+ readonly property var fieldItem: field
48
+ signal requested(var message)
49
+ signal approved(var message)
50
+ signal created(string path)
51
+ signal deleted(var message)
52
+ signal closed()
53
+
54
+ function open(operation, identity, parentPath, holder) {
55
+ action = operation
56
+ requestId = identity
57
+ folder = parentPath
58
+ focusHolder = holder
59
+ walk = null
60
+ extra = ({})
61
+ facts = ({})
62
+ errorText = ""
63
+ checkPending = false
64
+ confirmation.close()
65
+ settle = null
66
+ field.text = operation === "newFile" ? "New File" : parentPath
67
+ busy = operation === "properties" || operation === "deletePermanently"
68
+ committing = false
69
+ opened = true
70
+ body.contentY = 0
71
+ if (inputAction) { field.forceActiveFocus(); field.selectAll() }
72
+ else closeButton.forceActiveFocus()
73
+ if (busy) requested({c: "menuaction", op: operation === "deletePermanently" ? "prepareDelete" : "properties", id: requestId})
74
+ }
75
+ // Two dialogs share the one request id, so this one answers only for the ops it asked for:
76
+ // routing an Open with reply in here closed a Properties card that had just opened over it.
77
+ readonly property var ownedOps: ["properties", "prepareDelete", "refreshDelete", "checkDelete",
78
+ "delete", "validate", "newFile", "contents", "facts", ""]
79
+ function receive(message) {
80
+ if ((!opened && !deletionActive) || message.id !== requestId || message.op === "close") return
81
+ if (root.ownedOps.indexOf(message.op === undefined ? "" : message.op) < 0) return
82
+ if (deletionActive && message.op !== "delete") return
83
+ // A late count after the card left Properties changes nothing; a refused one ends as the floor already counted.
84
+ if (message.op === "contents") { if (walk) walk = PropertyFacts.next(walk, message); return }
85
+ // A refused or late facts reply adds no pair; the card already says everything else.
86
+ if (message.op === "facts") { if (message.ok) extra = message; return }
87
+ // A reply that ends the card keeps its busy look until the fade ended.
88
+ var ends = message.ok && !message.stale && (message.op === undefined || message.op === "" || message.op === "validate" || message.op === "newFile")
89
+ if (!ends) { busy = false; committing = false }
90
+ if (!message.ok) {
91
+ confirmation.close()
92
+ opened = true
93
+ closeButton.forceActiveFocus()
94
+ errorText = message.error || "That action could not be completed."
95
+ return
96
+ }
97
+ if (message.stale || message.op === "checkDelete" && !message.valid) { refreshDeletion(); return }
98
+ if (message.op === "prepareDelete" || message.op === "refreshDelete") {
99
+ facts = message
100
+ if (checkPending) { checkPending = false; refreshDeletion() }
101
+ else confirmation.open(message)
102
+ return
103
+ }
104
+ if (message.op === "checkDelete") {
105
+ if (checkPending) { checkPending = false; refreshDeletion() }
106
+ return
107
+ }
108
+ if (message.op === "delete") { deleted(Object.assign({count: facts.count}, message)); finish(); return }
109
+ if (message.op === "properties") {
110
+ walk = message.directory ? PropertyFacts.begin(message) : null
111
+ facts = message
112
+ if (walk) requested({c: "menuaction", op: "contents", id: requestId})
113
+ else if (message.kind === "File") requested({c: "menuaction", op: "facts", id: requestId})
114
+ return
115
+ }
116
+ if (message.op === "validate") { approved(message); closeSettled(); return }
117
+ if (message.op === "newFile") created(message.path)
118
+ closeSettled()
119
+ }
120
+ // The close of a finished reply: the busy look it left is cleared once the card is gone.
121
+ function closeSettled() {
122
+ settle = function () { busy = false; committing = false }
123
+ finish()
124
+ settleNow()
125
+ }
126
+ function settleNow() {
127
+ if (opacity !== 0 || settle === null) return
128
+ var run = settle
129
+ settle = null
130
+ run()
131
+ }
132
+ onOpacityChanged: root.settleNow()
133
+ function close() {
134
+ if (!opened || busy && committing && action === "newFile") return
135
+ finish()
136
+ }
137
+ function finish() {
138
+ requested({c: "menuaction", op: "close", id: requestId})
139
+ confirmation.close()
140
+ opened = false
141
+ closed()
142
+ if (focusHolder) focusHolder.forceActiveFocus()
143
+ }
144
+ function refreshDeletion() {
145
+ confirmation.close()
146
+ opened = true
147
+ busy = true
148
+ errorText = ""
149
+ closeButton.forceActiveFocus()
150
+ requested({c: "menuaction", op: "refreshDelete", id: requestId})
151
+ }
152
+ function checkDeletion() {
153
+ if (!opened || action !== "deletePermanently" || errorText) return
154
+ if (busy) { checkPending = true; return }
155
+ busy = true
156
+ requested({c: "menuaction", op: "checkDelete", id: requestId, token: facts.token})
157
+ }
158
+ function sourceChanged() {
159
+ if (!opened || action !== "deletePermanently" || errorText) return
160
+ confirmation.close()
161
+ if (busy) checkPending = true
162
+ else refreshDeletion()
163
+ }
164
+ function submit() {
165
+ if (!canSubmit) return
166
+ if (action !== "newFile" && field.text.charAt(0) !== "/") {
167
+ errorText = "Enter a full folder path, starting with /."
168
+ return
169
+ }
170
+ if (action === "newFile" && (field.text === "." || field.text === ".." || field.text.indexOf("/") >= 0)) {
171
+ errorText = "Enter a name without a /."
172
+ return
173
+ }
174
+ if (action === "newFile") body.forceActiveFocus()
175
+ else closeButton.forceActiveFocus()
176
+ busy = true
177
+ committing = true
178
+ errorText = ""
179
+ if (action === "newFile") requested({c: "newfile", op: "newFile", id: requestId, path: folder, name: field.text})
180
+ else requested({c: "menuaction", op: "validate", id: requestId, action: action, dest: field.text})
181
+ }
182
+ // Each focusable child routes Tab here before Qt can move focus outside the card.
183
+ function stepFocus(back) {
184
+ var items = [field, closeButton, submitButton].filter(function(item) {
185
+ return item.visible && item.enabled && item.activeFocusOnTab
186
+ })
187
+ if (!items.length) return
188
+ var current = -1
189
+ for (var i = 0; i < items.length; i++) if (items[i].activeFocus) current = i
190
+ var next = current < 0 ? (back ? items.length - 1 : 0)
191
+ : (current + (back ? -1 : 1) + items.length) % items.length
192
+ items[next].forceActiveFocus()
193
+ }
194
+ Keys.onTabPressed: function(event) { root.stepFocus((event.modifiers & Qt.ShiftModifier) !== 0); event.accepted = true }
195
+ Keys.onBacktabPressed: function(event) { root.stepFocus(true); event.accepted = true }
196
+ Keys.onEscapePressed: function(event) { root.close(); event.accepted = true }
197
+ Keys.onPressed: function(event) { event.accepted = true }
198
+ Rectangle {
199
+ anchors.fill: parent
200
+ visible: root.cardShown
201
+ color: Theme.color.background
202
+ opacity: 0.5
203
+ MouseArea {
204
+ anchors.fill: parent
205
+ hoverEnabled: true
206
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
207
+ onClicked: root.close()
208
+ onWheel: function(wheel) { wheel.accepted = true }
209
+ }
210
+ }
211
+ Rectangle {
212
+ id: card
213
+ visible: root.cardShown
214
+ x: Theme.cardOrigin(root.width, width)
215
+ y: Theme.cardOrigin(root.height, height)
216
+ width: Theme.cardSpan(Theme.space(420) * Theme.dialogWidthRatio, root.width - 2 * Theme.spacing.gap)
217
+ height: Theme.cardSpan(body.wanted + 2 * Theme.spacing.rowPaddingX, root.height - 2 * Theme.spacing.gap)
218
+ color: Theme.color.surface
219
+ border.color: Theme.color.mutedFrame
220
+ border.width: Theme.spacing.hairline
221
+ radius: Style.cornerRadius
222
+ MouseArea {
223
+ anchors.fill: parent
224
+ hoverEnabled: true
225
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
226
+ onWheel: function(wheel) { wheel.accepted = true }
227
+ }
228
+ Flea.CardFrame {
229
+ id: body
230
+ bleed: Theme.focusClearance
231
+ anchors.fill: parent
232
+ anchors.margins: Theme.spacing.rowPaddingX - Theme.focusClearance
233
+ title: Column {
234
+ width: parent.width
235
+ spacing: Theme.spacing.gap
236
+ Flea.DialogTitle {
237
+ width: parent.width
238
+ text: root.title
239
+ }
240
+ Rectangle { width: parent.width; height: Theme.spacing.hairline; color: Theme.color.mutedFrame; opacity: 0.4 }
241
+ }
242
+ buttons: Row {
243
+ anchors.right: parent.right
244
+ spacing: Theme.spacing.gap
245
+ Flea.DialogButton {
246
+ id: closeButton
247
+ label: root.action === "properties" ? "Close" : "Cancel"
248
+ available: !(root.busy && root.committing && root.action === "newFile")
249
+ tabHandle: true
250
+ tabStop: true
251
+ onTabbed: function(from, back) { root.stepFocus(back) }
252
+ onActivated: root.close()
253
+ }
254
+ Flea.DialogButton {
255
+ id: submitButton
256
+ visible: root.action !== "properties" && root.action !== "deletePermanently"
257
+ label: root.action === "newFile" ? "Create" : root.action === "moveTo" ? "Move" : "Copy"
258
+ primary: true
259
+ available: root.canSubmit
260
+ tabHandle: true
261
+ tabStop: true
262
+ onTabbed: function(from, back) { root.stepFocus(back) }
263
+ onActivated: root.submit()
264
+ }
265
+ }
266
+ Column {
267
+ width: parent.width
268
+ spacing: Theme.spacing.gap
269
+ Text {
270
+ width: parent.width
271
+ visible: root.inputAction
272
+ text: root.action === "newFile" ? "Name" : "Destination folder"
273
+ textFormat: Text.PlainText
274
+ color: Theme.color.foreground
275
+ font { family: Theme.font.family; pixelSize: Theme.font.body }
276
+ }
277
+ Rectangle {
278
+ visible: root.inputAction
279
+ width: parent.width
280
+ height: Theme.rowHeight - Theme.spacing.rowPaddingY
281
+ color: Theme.color.background
282
+ border.color: field.activeFocus ? Theme.color.accent : Theme.color.mutedFrame
283
+ border.width: Theme.spacing.hairline
284
+ TextInput {
285
+ id: field
286
+ anchors.left: parent.left
287
+ anchors.right: parent.right
288
+ anchors.verticalCenter: parent.verticalCenter
289
+ anchors.leftMargin: Theme.spacing.gap
290
+ anchors.rightMargin: Theme.spacing.gap
291
+ color: Theme.color.foreground
292
+ selectionColor: Theme.color.accent
293
+ selectedTextColor: Theme.color.background
294
+ font { family: Theme.font.family; pixelSize: Theme.font.body }
295
+ activeFocusOnTab: root.inputAction
296
+ enabled: !root.busy
297
+ clip: true
298
+ selectByMouse: true
299
+ Accessible.name: root.action === "newFile" ? "Filename" : "Destination folder"
300
+ Keys.onTabPressed: function(event) { root.stepFocus((event.modifiers & Qt.ShiftModifier) !== 0) }
301
+ Keys.onBacktabPressed: root.stepFocus(true)
302
+ Keys.onReturnPressed: root.submit()
303
+ Keys.onEnterPressed: root.submit()
304
+ }
305
+ }
306
+ Repeater {
307
+ model: root.action === "properties" && root.facts.ok ? [
308
+ ["Path", root.facts.path],
309
+ ["Type", root.facts.kind],
310
+ ["Size", "", "size"],
311
+ ...(root.facts.directory ? [["Contains", "", "contains"]] : []),
312
+ ...(root.extraPairs || []),
313
+ // A foreign word stays untouched and shows here, so a tag another app set is visible.
314
+ ...((root.facts.tags || []).length > 0 ? [["Tags", (root.facts.tags || []).join(", ")]] : []),
315
+ ["Modified", Format.date(root.facts.modified)],
316
+ ["Permissions", root.facts.mode],
317
+ ["Owner", (root.facts.owner || "Unknown") + " (uid " + root.facts.uid + ")"],
318
+ ["Group", "gid " + root.facts.gid],
319
+ ...(root.facts.symlink ? [["Link target", root.facts.target]] : [])
320
+ ] : []
321
+ Column {
322
+ id: pair
323
+ required property var modelData
324
+ // The Tags value is drawn as swatch and name per tag, so its plain string stays only as the model's text.
325
+ readonly property bool tagged: modelData[0] === "Tags"
326
+ width: body.holderWidth
327
+ Text { width: parent.width; text: parent.modelData[0]; textFormat: Text.PlainText; color: Theme.color.muted; font { family: Theme.font.family; pixelSize: Theme.font.caption } }
328
+ Text {
329
+ readonly property var line: parent.modelData.length > 2 ? root.liveLines[parent.modelData[2]] : null
330
+ visible: !pair.tagged
331
+ width: parent.width
332
+ text: line ? PropertyFacts.styled(line, Theme.color.muted) : parent.modelData[1]
333
+ textFormat: line ? Text.StyledText : Text.PlainText
334
+ wrapMode: Text.WrapAnywhere
335
+ color: Theme.color.foreground
336
+ font { family: Theme.font.family; pixelSize: Theme.font.body }
337
+ }
338
+ Flow {
339
+ visible: pair.tagged
340
+ width: parent.width
341
+ spacing: Theme.spacing.tagPairGap
342
+ Repeater {
343
+ model: pair.tagged ? root.facts.tags : []
344
+ Row {
345
+ id: tagItem
346
+ required property string modelData
347
+ spacing: Theme.spacing.tagNameGap
348
+ // A name Flea does not know is plain text with no swatch; a digit fallback keeps the 14 px square its digit needs.
349
+ Flea.TagSwatch {
350
+ size: Theme.tag.fallback ? Tags.SWATCH_SIZE : Tags.PAIR_SWATCH_SIZE
351
+ visible: Tags.NAMES.indexOf(tagItem.modelData) >= 0
352
+ anchors.verticalCenter: parent.verticalCenter
353
+ swatch: tagItem.modelData
354
+ fallback: Theme.tag.fallback
355
+ digit: Tags.keyFor(tagItem.modelData)
356
+ tagColors: Theme.tag.menuColors
357
+ }
358
+ Text {
359
+ anchors.verticalCenter: parent.verticalCenter
360
+ text: tagItem.modelData
361
+ textFormat: Text.PlainText
362
+ color: Theme.color.foreground
363
+ font { family: Theme.font.family; pixelSize: Theme.font.body }
364
+ }
365
+ }
366
+ }
367
+ }
368
+ }
369
+ }
370
+ Text {
371
+ width: parent.width
372
+ visible: text.length > 0
373
+ text: root.errorText || (root.busy ? "Working…" : "")
374
+ textFormat: Text.PlainText
375
+ wrapMode: Text.Wrap
376
+ color: root.errorText ? Theme.color.errorOnSurface : Theme.color.muted
377
+ font { family: Theme.font.family; pixelSize: Theme.font.caption }
378
+ }
379
+ }
380
+ }
381
+ }
382
+ // Match Trash's identity-check cadence only while the destructive strip is visible.
383
+ Timer { interval: 2500; repeat: true; running: confirmation.opened && !root.busy; onTriggered: root.checkDeletion() }
384
+ Flea.TrashConfirm {
385
+ id: confirmation
386
+ scopeName: "items"
387
+ onCancelled: root.close()
388
+ onConfirmed: function(token) {
389
+ root.busy = true
390
+ root.committing = true
391
+ root.opened = false
392
+ if (root.focusHolder) root.focusHolder.forceActiveFocus()
393
+ root.requested({c: "menuaction", op: "delete", id: root.requestId, token: token})
394
+ }
395
+ }
396
+ }
@@ -0,0 +1,24 @@
1
+ import QtQuick
2
+
3
+ // One edge of a menu that scrolls, fading the surface out where more rows wait: the Menus board's "Edges fade to say so".
4
+ Rectangle {
5
+ // The card's own padding between its border and its rows, which the fade crosses before it reaches a cut row.
6
+ property real inset: 0
7
+ // How far the fade reaches past that padding into the row the edge cuts.
8
+ property real reach: Theme.spacing.gap
9
+ // The frame Rectangle's border width: the fade lies inside it, so the hairline frame stays whole, corners included.
10
+ readonly property real frameBorder: parent.border.width
11
+ anchors.left: parent.left
12
+ anchors.right: parent.right
13
+ anchors.leftMargin: frameBorder
14
+ anchors.rightMargin: frameBorder
15
+ anchors.topMargin: frameBorder
16
+ anchors.bottomMargin: frameBorder
17
+ // Measured from the inner edge, so it still ends where the card's padding plus reach ends.
18
+ height: inset + reach - frameBorder
19
+ radius: Math.max(0, parent.radius - frameBorder)
20
+ gradient: Gradient {
21
+ GradientStop { position: 0; color: Theme.color.surface }
22
+ GradientStop { position: 1; color: Qt.rgba(Theme.color.surface.r, Theme.color.surface.g, Theme.color.surface.b, 0) }
23
+ }
24
+ }
@@ -0,0 +1,227 @@
1
+ import QtQuick
2
+ import "." as Flea
3
+ import "js/Menu.js" as Menu
4
+ import "js/MenuContext.js" as MenuContext
5
+
6
+ // Menu state and receivers stay live; the visual warms after the first frame and listing idle.
7
+ Item {
8
+ id: root
9
+ required property var pane
10
+ anchors.fill: parent
11
+ visible: false
12
+ readonly property var item: visual.item
13
+ readonly property int status: visual.status
14
+ property bool syncing: false
15
+ property bool firstFrame: false
16
+ readonly property bool ready: root.item !== null && visual.status === Loader.Ready
17
+ readonly property bool settled: root.pane.listingState !== "loading" && !root.pane.listInFlight
18
+ readonly property real inputAt: root.pane.inputAt
19
+ onInputAtChanged: if (warm.running) warm.restart()
20
+
21
+ signal chosen(string action)
22
+ signal refused(string reason)
23
+ signal snapshotRequested()
24
+ signal railChosen(string action, string key)
25
+ signal lockedChosen(string action, string path)
26
+
27
+ property Item focusOwner: null
28
+ property bool showHidden: false
29
+ property bool providersRefreshing: false
30
+ property var taildropPeers: []
31
+ property bool rowIsFile: false
32
+ property bool taildropInstalled: false
33
+ property string taildropReason: ""
34
+ property string taildropCode: ""
35
+ property var archiveFormats: []
36
+ property bool canConvert: false
37
+ property bool canExtract: false
38
+ property string archiveName: ""
39
+ property int rowMode: 0
40
+ property int selectionCount: 0
41
+ property bool cursorIsTarget: false
42
+ property var openWithApps: []
43
+ property bool openWithLoaded: false
44
+ property var identitySource: null
45
+ property bool clipboardAvailable: false
46
+ property bool clipboardWatchFailed: false
47
+ property bool rowIsArchive: false
48
+ property bool rowIsImage: false
49
+ property string rowName: ""
50
+ property string flashZipMember: ""
51
+ property bool rowIsSymlink: false
52
+ property bool rowHasShebang: false
53
+ property var selectionModes: []
54
+ property var compareKinds: []
55
+ property bool dropboxInstalled: false
56
+ property var localSend: ({ installed: false, peers: [], checking: false })
57
+ property string dropboxPath: ""
58
+ property string dropboxReason: ""
59
+ property string dropboxCode: ""
60
+ property bool rowInDropbox: false
61
+ property bool canTrash: true
62
+ property bool dirWritable: true
63
+ property bool canLink: true
64
+ property var tagSubmenu: null
65
+ property string storageClass: ""
66
+ property bool hasFolderSort: false
67
+ property string tileTarget: ""
68
+ property int tileMode: 0
69
+ property rect workArea: Qt.rect(0, 0, root.width, root.height)
70
+ property bool opened: false
71
+ property bool preparing: false
72
+ property bool hasRow: true
73
+ property bool forHeader: false
74
+ property string openedIdentity: ""
75
+ property string lockedPath: ""
76
+ property int lockedMode: 0
77
+ property var railEntries: []
78
+ property string railKey: ""
79
+ property Item focusHolder: null
80
+ property int cursor: 0
81
+ property int openSubmenuRow: -1
82
+ property int submenuCursor: 0
83
+ property string loneFlyoutAction: ""
84
+ property var lastProviderAnswer: null
85
+
86
+ readonly property bool forRail: root.railEntries.length > 0
87
+ readonly property bool forLocked: root.lockedPath.length > 0
88
+ readonly property bool submenuOpen: root.openSubmenuRow >= 0 || root.loneFlyoutAction.length > 0
89
+ readonly property var entries: root.item ? root.item.entries : []
90
+ readonly property var submenuEntries: root.item ? root.item.submenuEntries : []
91
+ readonly property var frameItem: root.item ? root.item.frameItem : null
92
+ readonly property var submenuFrameItem: root.item ? root.item.submenuFrameItem : null
93
+ readonly property bool keyboardFocused: root.item ? root.item.keyboardFocused : false
94
+ readonly property var inputNames: [
95
+ "focusOwner", "showHidden", "providersRefreshing", "taildropPeers",
96
+ "rowIsFile", "taildropInstalled", "taildropReason", "taildropCode",
97
+ "archiveFormats", "canConvert", "canExtract", "archiveName",
98
+ "rowMode", "selectionCount", "cursorIsTarget", "openWithApps",
99
+ "openWithLoaded", "identitySource", "clipboardAvailable", "clipboardWatchFailed",
100
+ "rowIsArchive", "rowIsImage", "rowName", "flashZipMember",
101
+ "rowIsSymlink", "rowHasShebang", "selectionModes", "compareKinds", "dropboxInstalled",
102
+ "localSend", "dropboxPath", "dropboxReason", "dropboxCode",
103
+ "rowInDropbox", "canTrash", "dirWritable", "canLink",
104
+ "tagSubmenu", "storageClass", "hasFolderSort", "tileTarget",
105
+ "tileMode", "workArea"
106
+ ]
107
+ readonly property var stateNames: [
108
+ "opened", "preparing", "hasRow", "forHeader",
109
+ "openedIdentity", "lockedPath", "lockedMode", "railEntries",
110
+ "railKey", "focusHolder", "cursor", "openSubmenuRow",
111
+ "submenuCursor", "loneFlyoutAction", "lastProviderAnswer"
112
+ ]
113
+
114
+ function liveInput(name) { return Qt.binding(function () { return root[name] }) }
115
+ function copyState(name, from, to) {
116
+ if (root.syncing || !root.item) return
117
+ root.syncing = true
118
+ try { to[name] = from[name] } finally { root.syncing = false }
119
+ }
120
+ function watchState(name) {
121
+ root[name + "Changed"].connect(function () { root.copyState(name, root, root.item) })
122
+ root.item[name + "Changed"].connect(function () { root.copyState(name, root.item, root) })
123
+ }
124
+ function configure() {
125
+ if (String(visual.source).length > 0) return
126
+ var values = { parent: root.liveInput("parent") }
127
+ for (var i = 0; i < root.inputNames.length; i++) values[root.inputNames[i]] = root.liveInput(root.inputNames[i])
128
+ visual.setSource("ContextMenu.qml", values)
129
+ }
130
+ function loaded() {
131
+ for (var s = 0; s < root.stateNames.length; s++) root.item[root.stateNames[s]] = root[root.stateNames[s]]
132
+ for (var n = 0; n < root.stateNames.length; n++) root.watchState(root.stateNames[n])
133
+ root.item.chosen.connect(root.chosen)
134
+ root.item.refused.connect(root.refused)
135
+ root.item.snapshotRequested.connect(root.snapshotRequested)
136
+ root.item.railChosen.connect(root.railChosen)
137
+ root.item.lockedChosen.connect(root.lockedChosen)
138
+ }
139
+ function prewarm() {
140
+ if (visual.active) return
141
+ root.configure()
142
+ visual.active = true
143
+ }
144
+ function ensure() {
145
+ if (root.item) return root.item
146
+ warm.stop()
147
+ // Cancelling first preserves inputs from birth when Qt restarts unfinished compilation.
148
+ visual.active = false
149
+ visual.source = ""
150
+ visual.asynchronous = false
151
+ root.configure()
152
+ visual.active = true
153
+ if (!root.item) throw new Error("ContextMenu.qml did not load: Loader status " + visual.status)
154
+ return root.item
155
+ }
156
+
157
+ Loader {
158
+ id: visual
159
+ active: false
160
+ asynchronous: true
161
+ onLoaded: root.loaded()
162
+ onStatusChanged: if (status === Loader.Error) throw new Error("ContextMenu.qml did not load: Loader status " + status)
163
+ }
164
+
165
+ // Match Quick Look's one-second idle hold, after both the first swap and listing readiness.
166
+ Timer {
167
+ id: warm
168
+ interval: 1000
169
+ running: root.firstFrame && root.settled && !visual.active
170
+ onTriggered: root.prewarm()
171
+ }
172
+ Connections {
173
+ target: root.firstFrame ? null : root.Window.window
174
+ function onFrameSwapped() { root.firstFrame = true }
175
+ }
176
+
177
+ function selectionIdentity() { return root.identitySource ? root.identitySource.menuSelectionIdentity() : "" }
178
+ function listingContext(flyoutAction, includeHidden) {
179
+ if (root.item) return root.item.listingContext(flyoutAction, includeHidden)
180
+ return MenuContext.listingContext(root, flyoutAction, includeHidden, {
181
+ scripts: Flea.Scripts.entries, hiddenActions: ViewState.menuHidden,
182
+ langMarks: ViewState.langMarks,
183
+ thumbPreview: ViewState.preview, updateVersion: UpdateCheck.menuVersion
184
+ })
185
+ }
186
+ function buildEntries(flyoutAction, includeHidden) {
187
+ if (root.item) return root.item.buildEntries(flyoutAction, includeHidden)
188
+ if (root.forRail) return root.railEntries
189
+ if (root.forHeader) return Menu.headerEntries(ViewState.hiddenCols, root.showHidden)
190
+ return Menu.listingEntries(root.listingContext(flyoutAction, includeHidden))
191
+ }
192
+ function validateChoice(action, subId, includeHidden) {
193
+ if (root.item) return root.item.validateChoice(action, subId, includeHidden)
194
+ return MenuContext.validateChoice(root, action, subId, includeHidden)
195
+ }
196
+ function refuseLone(kind) {
197
+ root.close()
198
+ root.refused(kind === "moved" ? "Selected items changed; reopen the menu."
199
+ : "That action is no longer available; reopen the menu.")
200
+ }
201
+ function providersSettled() {
202
+ if (root.item) root.item.providersSettled()
203
+ else root.lastProviderAnswer = MenuContext.settle(MenuContext.live(root))
204
+ }
205
+ function refreshProviderRows() { if (root.item) root.item.refreshProviderRows() }
206
+ function close() {
207
+ if (root.item) root.item.close()
208
+ else root.opened = false
209
+ }
210
+ function clearRail() {
211
+ if (root.item) root.item.clearRail()
212
+ else { root.railEntries = []; root.railKey = ""; root.lockedPath = ""; root.lockedMode = 0 }
213
+ }
214
+ function openAt(point) { root.ensure().openAt(point) }
215
+ function openBackground(point) { root.ensure().openBackground(point) }
216
+ function openLocked(path, mode, point) { root.ensure().openLocked(path, mode, point) }
217
+ function openForHeader(point) { root.ensure().openForHeader(point) }
218
+ function openForRail(key, rows, point) { if (rows && rows.length) root.ensure().openForRail(key, rows, point) }
219
+ function openSubmenu(index) { if (root.item) root.item.openSubmenu(index) }
220
+ function openSubmenuFor(action) { return root.ensure().openSubmenuFor(action) }
221
+ function choose(action) { if (root.item) root.item.choose(action) }
222
+ function chooseSub(id) { if (root.item) root.item.chooseSub(id) }
223
+ function setEntries(rows, flyoutRow) { root.ensure().setEntries(rows, flyoutRow) }
224
+ function itemFor(index) { return root.item ? root.item.itemFor(index) : null }
225
+ function submenuItemFor(index) { return root.item ? root.item.submenuItemFor(index) : null }
226
+ function submenuGlyphs() { return root.item ? root.item.submenuGlyphs() : "" }
227
+ }