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,478 @@
1
+ .pragma library
2
+ .import "Input.js" as Input
3
+ .import "Format.js" as Format
4
+
5
+ // The status bar's two search lines, each filled by Format.fill.
6
+ var WORDS = {
7
+ // flea-qml: find reports matches only, so there is no scanned count to show.
8
+ searching: "%1 found · Searching",
9
+ landed: "%1 found in %2 s"
10
+ }
11
+
12
+ // Enter starts the subtree search; editing the real input alone does not run find.
13
+ var OFF = ""
14
+ var TYPING = "typing"
15
+ var RESULTS = "results"
16
+
17
+ // f opens the session with no rows touched; from Recent it leaves first, so the scope and rows are the real folder.
18
+ // flea-qml: `contents` (Ctrl+G) opens it as a content search; f and a tag place open a name search.
19
+ function start(root, contents) {
20
+ // A virtual collection has no single recursive filesystem scope. Never search
21
+ // the unrelated directory that was visible before opening Trash.
22
+ if (root.recentMode === "trash") {
23
+ root.message("Open a Trash folder to Find inside it; / filters this collection", false)
24
+ return
25
+ }
26
+ if (root.searchMode === RESULTS) {
27
+ root.searchMode = TYPING
28
+ return
29
+ }
30
+ if ((root.searchMode || "").length > 0) {
31
+ return
32
+ }
33
+ // The cursor's file rides pendingSelect until Esc; mid-session landings skip it while the query stands.
34
+ var under = root.rowFor(root.cursorIndex)
35
+ root.pendingSelect = under && under.n ? root.join(root.path, under.n) : ""
36
+ var fromRecent = root.recentMode.length > 0
37
+ if (fromRecent) {
38
+ // The history rows keep their own base until the folder's rows, asked below, replace them.
39
+ root.searchBase = root.path
40
+ if (root.recentFrom.length > 0) {
41
+ root.path = root.recentFrom
42
+ }
43
+ root.recentMode = ""
44
+ root.recentFrom = ""
45
+ root.recentPaths = []
46
+ root.restoreRecentSort()
47
+ }
48
+ root.searchFrom = root.path
49
+ root.searchContents = contents === true
50
+ root.searchMode = TYPING
51
+ openScope(root)
52
+ // Recent's rows name paths under "/", so the folder's own rows are asked for now and Esc re-lists it.
53
+ if (fromRecent) {
54
+ sendQuery(root)
55
+ }
56
+ }
57
+
58
+ // The backend session for the pane's scope, with the drawn state of a fresh walk; f and a tag place both open through here.
59
+ function openScope(root) {
60
+ // Gens keep rising across sessions, so a closed session's late line never matches; the first answer parks on row 0.
61
+ root.searchOpenedGen = root.searchGen
62
+ if (root.swap) { root.swap.landedGen = 0; root.swap.answeredQuery = "" }
63
+ root.searchQuery = ""
64
+ root.searchSent = ""
65
+ // flea-qml: nothing runs until Enter, so a fresh strip is not searching yet.
66
+ root.searchRunning = false
67
+ root.searchCancelled = false
68
+ root.searchScanned = 0
69
+ root.backend.searchOpen(scopeRoot(root.path, root.home || "", root.searchStep), root.path, root.showHidden)
70
+ }
71
+
72
+ // flea-qml: Find's scopes, which Tab turns through in this order wherever the pane is: the folder
73
+ // itself, home, and the root of the folder's own filesystem.
74
+ var HERE = 0, HOME = 1, ROOT = 2
75
+ var SCOPE_COUNT = 3
76
+ var SCOPE_MARK = [".", "~", "/"]
77
+
78
+ // The root a path stands on, read off the path's own start, so every system answers alike:
79
+ // "/" for /home/a, "C:\" for C:\Users\a, and "\\server\share\" for a path under that share.
80
+ function rootOf(path) {
81
+ var m = /^(\\\\[^\\/]+[\\/][^\\/]+[\\/]?|[A-Za-z]:[\\/]?|[\\/])/.exec(String(path))
82
+ return m ? m[0] : "/"
83
+ }
84
+
85
+ function scopeRoot(path, home, step) {
86
+ if (step === HOME && home) return home
87
+ if (step === ROOT) return rootOf(path)
88
+ return path
89
+ }
90
+
91
+ // Keystrokes send rising gens with old rows held and the cursor standing for the landing to keep.
92
+ // flea-qml: only Enter (and Tab over a query already run) sends one; searchSent is what it sent.
93
+ function sendQuery(root) {
94
+ root.searchSent = root.searchQuery
95
+ // flea-qml: the find runs from here until its terminal line lands.
96
+ root.searchRunning = root.searchQuery.length > 0
97
+ root.searchCancelled = false
98
+ root.searchGen += 1
99
+ root.searchKeyAt = Date.now()
100
+ root.searchFirstRowsAt = 0
101
+ root.searchSettledAt = 0
102
+ root.backend.searchQuery(root.searchQuery, root.searchGen, root.windowSize, root.sizeWish, root.searchContents === true)
103
+ }
104
+
105
+ // flea-qml: Ctrl+G. Outside Find it opens a content search; inside, it turns the search between
106
+ // names and contents. Either way nothing runs until Enter: from the results it goes back to the
107
+ // query line, as f does, so the next Enter runs the query in the new mode.
108
+ function contents(root) {
109
+ if ((root.searchMode || "").length === 0) {
110
+ start(root, true)
111
+ return
112
+ }
113
+ if (root.searchLeaving === true) return
114
+ root.searchContents = root.searchContents !== true
115
+ if (root.searchMode === RESULTS) root.searchMode = TYPING
116
+ }
117
+
118
+ // flea-qml: typing only edits the query line; Enter runs the find.
119
+ function extend(root, character) {
120
+ root.searchQuery += character
121
+ }
122
+
123
+ // Backspace to empty sends "" and the folder rows come back, with the strip still open.
124
+ function shrink(root) {
125
+ if (root.searchQuery.length === 0) {
126
+ return
127
+ }
128
+ root.searchQuery = root.searchQuery.substring(0, root.searchQuery.length - 1)
129
+ }
130
+
131
+ // flea-qml: Enter runs the find every time, changed query or not, so the results are fresh; a press
132
+ // within ENTER_DEBOUNCE_MS of the last run is the same press repeated and runs nothing more.
133
+ var ENTER_DEBOUNCE_MS = 500
134
+ function commit(root) {
135
+ if ((root.searchQuery || "").length === 0) {
136
+ abort(root)
137
+ return
138
+ }
139
+ var now = Date.now()
140
+ if (now - (root.searchEnterAt || 0) >= ENTER_DEBOUNCE_MS) {
141
+ root.searchEnterAt = now
142
+ sendQuery(root)
143
+ }
144
+ root.searchMode = RESULTS
145
+ }
146
+
147
+ // A leaving session takes no query from outside, so a caller that clears its own state first asks here.
148
+ function takesQuery(root) {
149
+ return root.searchLeaving !== true
150
+ }
151
+
152
+ // A query set from outside the strip lands as results over the Home scope, from a fresh session, a standing one or a cancelled one; a leaving session takes none.
153
+ // Sample input: (pane, "tag:Red") with the pane browsing, in Recent, or typing or showing results at either scope.
154
+ function openQuery(root, query) {
155
+ if (!takesQuery(root)) {
156
+ return
157
+ }
158
+ if ((root.searchMode || "").length === 0) {
159
+ root.searchStep = HOME
160
+ start(root)
161
+ } else if (root.searchCancelled === true) {
162
+ // A cancelled walk answers nothing more, so the place opens a fresh Home session with the drawn state of a new walk.
163
+ root.searchStep = HOME
164
+ openScope(root)
165
+ } else if (root.searchStep !== HOME) {
166
+ // flea-qml: the place's query runs over home, whichever scope Tab had turned to.
167
+ root.searchStep = HOME
168
+ openScope(root)
169
+ }
170
+ root.searchQuery = query
171
+ sendQuery(root)
172
+ commit(root)
173
+ }
174
+
175
+ // Tab flips the scope, opens the new scope at once and re-sends the standing query.
176
+ function rescope(root) {
177
+ root.searchStep = nextStep(root.searchStep, root.home || "")
178
+ var scope = scopeRoot(root.path, root.home || "", root.searchStep)
179
+ root.backend.searchOpen(scope, root.path, root.showHidden)
180
+ // flea-qml: a query already run reruns in the new scope; an unrun one waits for Enter.
181
+ if ((root.searchSent || "").length > 0 && (root.searchQuery || "").length > 0) {
182
+ sendQuery(root)
183
+ }
184
+ }
185
+
186
+ // flea-qml: the command the empty query line stands for, after the scope it runs in.
187
+ // The space after -iname is the one a shell command line holds before its argument.
188
+ function placeholder(path, home, step, contents) {
189
+ // A content search names the text it looks for; the scope is the "in" after the field.
190
+ if (contents === true) return "grep -ri "
191
+ return "find " + SCOPE_MARK[step === HOME && !home ? HERE : step] + " -iname "
192
+ }
193
+
194
+ // flea-qml: where Tab moves the scope next, the same everywhere; home is skipped when none is known.
195
+ function tabHint(path, home, step) {
196
+ return "tab: " + SCOPE_MARK[nextStep(step, home)]
197
+ }
198
+
199
+ function nextStep(step, home) {
200
+ var next = (step + 1) % SCOPE_COUNT
201
+ return next === HOME && !home ? (next + 1) % SCOPE_COUNT : next
202
+ }
203
+
204
+ // flea-qml: the manager's hidden setting changed under a standing Find: the scope reopens with it,
205
+ // and a query already run runs again, walking hidden folders now or pruning them.
206
+ function rehide(root) {
207
+ root.backend.searchOpen(scopeRoot(root.path, root.home || "", root.searchStep), root.path, root.showHidden)
208
+ if ((root.searchSent || "").length > 0 && (root.searchQuery || "").length > 0)
209
+ sendQuery(root)
210
+ }
211
+
212
+ // flea-qml: ✕ stops a running find and leaves at once, the two Escapes in one press.
213
+ function dismiss(root) {
214
+ if (root.searchRunning && root.backend) root.backend.searchCancel()
215
+ root.searchRunning = false
216
+ abort(root)
217
+ }
218
+
219
+ // The first Esc while the walk runs stops it and keeps the results on screen.
220
+ function cancel(root) {
221
+ if (root.backend) {
222
+ root.backend.searchCancel()
223
+ }
224
+ }
225
+
226
+ // Esc leaves at once when empty or landed, or re-lists the folder it came from otherwise.
227
+ function abort(root) {
228
+ // A second Esc lands nowhere: the first already closed the backend and owes the landing.
229
+ if (root.searchLeaving === true) {
230
+ return
231
+ }
232
+ // flea-qml: Esc has two meanings, decided only by whether a find runs: running, it stops the
233
+ // find and keeps what it found; not running, it closes Find. The query line plays no part.
234
+ if (root.searchRunning) {
235
+ cancel(root)
236
+ return
237
+ }
238
+ var back = (root.searchFrom || "").length > 0 ? root.searchFrom : root.path
239
+ if (!owesRelist(root)) {
240
+ closeSession(root)
241
+ root.pendingSelect = ""
242
+ return
243
+ }
244
+ // The backend closes at the request; the drawn state waits for the folder to land.
245
+ leaveWalk(root)
246
+ root.openWithoutHistory(back, { holdWalk: true, relist: true, keptQuery: root.filterQuery })
247
+ }
248
+
249
+ // Any gen this session sent may have drawn rows the folder does not own, so leaving it re-lists the folder.
250
+ function owesRelist(root) {
251
+ return (root.searchMode || "").length > 0 && root.searchGen > (root.searchOpenedGen || 0)
252
+ }
253
+
254
+ // A live re-answer keeps the cursor's file when the new window still names it, else row 0.
255
+ function keptIndex(name, items, start) {
256
+ if (name === null || name === undefined) {
257
+ return start
258
+ }
259
+ for (var i = 0; i < items.length; i++) {
260
+ if (items[i].n === name) {
261
+ return start + i
262
+ }
263
+ }
264
+ return start
265
+ }
266
+
267
+ // A navigation drops the session without re-listing, so the next listing lands on clean state.
268
+ function leaveWalk(root) {
269
+ if ((root.searchMode || "").length === 0) {
270
+ return false
271
+ }
272
+ // One close per exit: tabs close the walk before the navigation closes it again.
273
+ if (root.searchLeaving === true) {
274
+ return true
275
+ }
276
+ // Results on screen keep their strip until the next listing lands; the backend closes now.
277
+ if (live(root)) {
278
+ if (root.backend) {
279
+ root.backend.searchClose()
280
+ }
281
+ root.searchLeaving = true
282
+ return true
283
+ }
284
+ return closeSession(root)
285
+ }
286
+
287
+ // Closing the session is one searchclose; a list closes it too, so a doubled close is silence.
288
+ function closeSession(root) {
289
+ if ((root.searchMode || "").length === 0) {
290
+ return false
291
+ }
292
+ if (root.backend) {
293
+ root.backend.searchClose()
294
+ }
295
+ root.searchMode = OFF
296
+ root.searchQuery = ""
297
+ root.searchRunning = false
298
+ root.searchCancelled = false
299
+ root.searchScanned = 0
300
+ root.searchFrom = ""
301
+ root.searchBase = ""
302
+ root.listingState = listingState(root, root.total)
303
+ root.stateMessage = ""
304
+ return true
305
+ }
306
+
307
+ // A terminal line answers only the newest gen this session sent; older gens drop with anything gen-less.
308
+ function accepts(root, gen) {
309
+ return (root.searchMode || "").length > 0 && gen === root.searchGen && gen > (root.searchOpenedGen || 0)
310
+ }
311
+
312
+ // An exit landing clears the drawn search state in the same turn its rows do; the backend already closed.
313
+ function closeLeaving(root) {
314
+ root.searchLeaving = false
315
+ root.searchMode = OFF
316
+ root.searchQuery = ""
317
+ root.searchRunning = false
318
+ root.searchCancelled = false
319
+ root.searchScanned = 0
320
+ root.searchFrom = ""
321
+ root.searchBase = ""
322
+ }
323
+
324
+ // The answered counts land; the first window rides its own rows line, so nothing is asked for.
325
+ function searched(root, total, scanned, ms, cancelled, gen, walking) {
326
+ // Answers for a session closed at its exit's request never land.
327
+ if (root.searchLeaving === true) {
328
+ return
329
+ }
330
+ if (!accepts(root, gen)) {
331
+ return
332
+ }
333
+ root.searchRunning = walking === true
334
+ root.searchCancelled = cancelled
335
+ if (walking !== true) {
336
+ root.searchSettledAt = Date.now()
337
+ }
338
+ root.total = total
339
+ root.searchScanned = scanned
340
+ root.searchMs = ms
341
+ root.listingState = listingState(root, total)
342
+ root.listArea.restartSettle()
343
+ }
344
+
345
+ // Query-line keys: enter keeps, escape leaves, tab rescopes, printables extend; cursor motions run through Focus.
346
+ function typeKey(event, root) {
347
+ // Keys struck while the exit is out wait for the folder, the way any held listing holds them.
348
+ if (root.searchLeaving === true) {
349
+ return true
350
+ }
351
+ // Ctrl+V and Shift+Insert extend the query by the clipboard's first line, one generation (issue 287).
352
+ if (Input.isPasteKey(event))
353
+ return Input.pasteInto(root, function (text) { extend(root, text) })
354
+ if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
355
+ commit(root)
356
+ return true
357
+ }
358
+ if (event.key === Qt.Key_Escape) {
359
+ abort(root)
360
+ return true
361
+ }
362
+ if (event.key === Qt.Key_Backspace) {
363
+ shrink(root)
364
+ return true
365
+ }
366
+ // Issue 30's control: tab flips the scope between the whole home directory and the one the pane
367
+ // is standing in. It is the only writer, and nothing resets it, so the flip holds for the window;
368
+ // ui/SearchStrip.qml draws "in <scope>" under the caret, so every search says which one it took.
369
+ if (event.key === Qt.Key_G && (event.modifiers & Qt.ControlModifier) && !(event.modifiers & (Qt.AltModifier | Qt.MetaModifier))) {
370
+ contents(root)
371
+ return true
372
+ }
373
+ if (event.key === Qt.Key_Tab || event.key === Qt.Key_Backtab) {
374
+ rescope(root)
375
+ return true
376
+ }
377
+ if (Input.isPrintable(event.text)) {
378
+ extend(root, event.text)
379
+ return true
380
+ }
381
+ return true
382
+ }
383
+
384
+ // o on a result opens the directory that holds it and puts the cursor on the row, the design's reveal.
385
+ function reveal(root) {
386
+ var row = root.rowFor(root.cursorIndex)
387
+ if (!row) {
388
+ return
389
+ }
390
+ var full = root.join(baseOf(root), row.n)
391
+ var cut = full.lastIndexOf("/")
392
+ if (cut <= 0) {
393
+ return
394
+ }
395
+ root.recentMode = ""
396
+ root.recentFrom = ""
397
+ root.recentPaths = []
398
+ // Through the pane: importing RecentMode.js here would close a Nav import cycle.
399
+ root.restoreRecentSort()
400
+ root.pendingSelect = full
401
+ root.open(full.substring(0, cut))
402
+ }
403
+
404
+ // Read-only stopwatch for the newest gen; per-keystroke latency is measured off it.
405
+ function stamps(root) {
406
+ return { gen: root.searchGen, keyAt: root.searchKeyAt || 0,
407
+ firstRowsAt: root.searchFirstRowsAt || 0, settledAt: root.searchSettledAt || 0 }
408
+ }
409
+
410
+ // Rows on screen belong to a standing query: results in, folder out, whatever mode holds them.
411
+ function live(root) {
412
+ return (root.searchMode || "").length > 0 && (root.searchQuery || "").length > 0
413
+ }
414
+
415
+ // What activating a row means right now. On a search result it takes
416
+ // you to the file instead of opening it; the canvas keeps enter on open and o on reveal, so it is
417
+ // only the pointer that asks this. ui/js/Tap.js is the one caller.
418
+ // flea-qml: a tap on a result only selects it, so the pointer browses results the way the arrows
419
+ // do and the search stays; two taps open, as anywhere else, and o or the menu reveals.
420
+ function activateAction(root) {
421
+ return "open"
422
+ }
423
+
424
+ // A walk with no matches yet is still working, so the list area keeps the crawl rather than
425
+ // flashing the empty state at every directory that happens to hold nothing.
426
+ function listingState(root, total) {
427
+ if (total > 0) {
428
+ return "ready"
429
+ }
430
+ return root.searchRunning ? "loading" : "empty"
431
+ }
432
+
433
+ // Strip note as whole templates: the count with its crawl while the walk runs, alone landed.
434
+ var NOTE = { walking: "%1 found · still scanning", landed: "%1 found" }
435
+ function note(total, running, empty) {
436
+ if (empty === true) {
437
+ return ""
438
+ }
439
+ if (running) {
440
+ return NOTE.walking.replace("%1", Format.count(total))
441
+ }
442
+ return NOTE.landed.replace("%1", Format.count(total))
443
+ }
444
+
445
+ // Empty-state caption for the query the shown answer is for; the function replacer keeps "$&" and "$$" in it literal.
446
+ function nothingMatches(answered) {
447
+ if (answered.length === 0) {
448
+ return ""
449
+ }
450
+ return "Nothing matches %1".replace("%1", function () { return answered })
451
+ }
452
+
453
+ // Strip right edge as whole templates: walking esc stops the walk, any other esc leaves.
454
+ var WAY = { walking: "esc cancels, then returns", done: "esc returns" }
455
+ function wayOut(running, empty) {
456
+ if (running && empty !== true) {
457
+ return WAY.walking
458
+ }
459
+ return WAY.done
460
+ }
461
+
462
+ // Row facilities join a row against the listing's base, the scope or the folder, never pane.path mid-session.
463
+ function baseOf(root) {
464
+ return (root.searchBase || "").length > 0 ? root.searchBase : root.path
465
+ }
466
+
467
+ // The rule itself lives in Format.tilde, because the window chrome draws a path through the same one.
468
+ function scope(path, home) {
469
+ return Format.tilde(path, home)
470
+ }
471
+
472
+ // The status bar's own left half while a search is up, the two lines the canvas draws.
473
+ function statusLine(running, total, scanned, ms) {
474
+ if (running) {
475
+ return Format.fill(WORDS.searching, Format.count(total), Format.count(scanned))
476
+ }
477
+ return Format.fill(WORDS.landed, Format.count(total), (ms / 1000).toFixed(1))
478
+ }
@@ -0,0 +1,97 @@
1
+ .pragma library
2
+
3
+ // A selection is a set of row indices over the current listing; a new list clears it, because an index
4
+ // into a directory that has changed means nothing. Task 8 declined ScriptModel plus ItemSelectionModel
5
+ // on measured memory (see AGENTS.md "The list model"), so this is a hand-rolled index set instead.
6
+ function create() {
7
+ var rows = {}
8
+ var n = 0
9
+ // True while the set is one row a plain tap or a landing anchor made, which a plain move carries along.
10
+ var lone = false
11
+ // True only for the row a navigation landed on, which Escape climbs past instead of unwinding.
12
+ var landed = false
13
+ // Shift adds to the gesture's starting marks; other mutators end it, and a cursor differing from shiftLast starts a new block.
14
+ var shiftBase = null
15
+ var shiftLast = -1
16
+ var shiftSeq = 0
17
+
18
+ function endShift() { shiftBase = null }
19
+
20
+ function has(i) {
21
+ return rows[i] === true
22
+ }
23
+
24
+ function add(i) {
25
+ if (!has(i)) { rows[i] = true; n += 1 }
26
+ }
27
+
28
+ function remove(i) {
29
+ if (has(i)) { delete rows[i]; n -= 1 }
30
+ }
31
+
32
+ function dropLone() {
33
+ lone = false
34
+ landed = false
35
+ }
36
+ // v on its lone row keeps it and drops lone, so the next v toggles it off.
37
+ function promote(i) { if (lone && n === 1 && has(i)) { dropLone(); return true } return false }
38
+
39
+ return {
40
+ has: has,
41
+ promote: promote,
42
+ count: function () { return n },
43
+ // A lone row follows a plain move; any deliberate mark drops that promise at once.
44
+ follows: function () { return lone && n === 1 },
45
+ // Only a navigation landing keeps the climb-through promise; a click's own only() drops it.
46
+ isLanded: function () { return landed === true && lone && n === 1 },
47
+ toggle: function (i) { dropLone(); endShift(); has(i) ? remove(i) : add(i) },
48
+ only: function (i, keep) {
49
+ rows = {}
50
+ n = 0
51
+ add(i)
52
+ lone = true
53
+ landed = keep === true
54
+ endShift()
55
+ },
56
+ extendTo: function (i, anchor) {
57
+ dropLone()
58
+ endShift()
59
+ var lo = Math.min(i, anchor)
60
+ var hi = Math.max(i, anchor)
61
+ rows = {}
62
+ n = 0
63
+ for (var r = lo; r <= hi; r++)
64
+ add(r)
65
+ },
66
+ all: function (total) {
67
+ dropLone()
68
+ endShift()
69
+ rows = {}
70
+ n = 0
71
+ for (var r = 0; r < total; r++)
72
+ add(r)
73
+ },
74
+ clear: function () { rows = {}; n = 0; dropLone(); endShift() },
75
+ // The gesture's own trio, the only calls that leave the base standing. The base is a snapshot
76
+ // taken once at gesture start, never per key, so the gesture's range may shrink without dropping it.
77
+ shiftBegin: function (base, last, seq) { shiftBase = base.slice(); shiftLast = last; shiftSeq = seq || 0 },
78
+ shiftMoved: function (last, seq) { shiftLast = last; shiftSeq = seq || 0 },
79
+ shiftState: function () { return shiftBase === null ? null : { base: shiftBase, last: shiftLast, seq: shiftSeq } },
80
+ shiftApply: function (range) {
81
+ dropLone()
82
+ rows = {}
83
+ n = 0
84
+ for (var i = 0; i < shiftBase.length; i++)
85
+ add(shiftBase[i])
86
+ for (var j = 0; j < range.length; j++)
87
+ add(range[j])
88
+ },
89
+ indices: function () {
90
+ var out = []
91
+ for (var k in rows)
92
+ out.push(Number(k))
93
+ out.sort(function (a, b) { return a - b })
94
+ return out
95
+ }
96
+ }
97
+ }