@mudlet/mudlet-web 0.5.0 → 1.0.1

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 (301) hide show
  1. package/README.md +1 -1
  2. package/dist-lib/analytics.d.ts +27 -0
  3. package/dist-lib/assets/fonts/Vera.woff2 +0 -0
  4. package/dist-lib/assets/fonts/VeraBI.woff2 +0 -0
  5. package/dist-lib/assets/fonts/VeraBd.woff2 +0 -0
  6. package/dist-lib/assets/fonts/VeraIt.woff2 +0 -0
  7. package/dist-lib/assets/mapParser.worker-DrVZ3wg_.js +9 -0
  8. package/dist-lib/backupImport-wt8r7JXI.js +233 -0
  9. package/dist-lib/branding.d.ts +111 -13
  10. package/dist-lib/db/sqliteClient.d.ts +195 -7
  11. package/dist-lib/hooks/useAutoReconnect.d.ts +61 -0
  12. package/dist-lib/hooks/useDocumentFullscreen.d.ts +23 -0
  13. package/dist-lib/hooks/useKeyboardShortcuts.d.ts +37 -0
  14. package/dist-lib/hooks/useRecordLastPlayed.d.ts +10 -0
  15. package/dist-lib/import/applyMudletProfile.d.ts +35 -9
  16. package/dist-lib/import/backupImport.d.ts +118 -0
  17. package/dist-lib/import/collectProfileExport.d.ts +33 -2
  18. package/dist-lib/import/defaultPackages.d.ts +57 -14
  19. package/dist-lib/import/defaults/CF-loader/CF-loader.mpackage +0 -0
  20. package/dist-lib/import/defaults/MedBootstrap/MedBootstrap.mpackage +0 -0
  21. package/dist-lib/import/defaults/deleteOldProfiles/deleteOldProfiles.mpackage +0 -0
  22. package/dist-lib/import/defaults/echo/echo.mpackage +0 -0
  23. package/dist-lib/import/defaults/enable-accessibility/enable-accessibility.mpackage +0 -0
  24. package/dist-lib/import/defaults/generic_mapper/generic_mapper.mpackage +0 -0
  25. package/dist-lib/import/defaults/gui-drop/gui-drop.mpackage +0 -0
  26. package/dist-lib/import/defaults/icesus-loader/icesus-loader.mpackage +0 -0
  27. package/dist-lib/import/defaults/mg-loader/mg-loader.mpackage +0 -0
  28. package/dist-lib/import/defaults/mudlet-base-ui/mudlet-base-ui.mpackage +0 -0
  29. package/dist-lib/import/defaults/mudlet-mapper.xml +1215 -389
  30. package/dist-lib/import/mudletControlChars.d.ts +14 -0
  31. package/dist-lib/import/mudletHost.d.ts +73 -10
  32. package/dist-lib/import/mudletLink.d.ts +53 -2
  33. package/dist-lib/import/mudletProfileExport.d.ts +38 -5
  34. package/dist-lib/import/mudletProfileImport.d.ts +110 -12
  35. package/dist-lib/import/mudletVariables.d.ts +4 -3
  36. package/dist-lib/import/mudletWriteback.d.ts +15 -1
  37. package/dist-lib/import/mudletXmlImport.d.ts +46 -0
  38. package/dist-lib/import/packageFonts.d.ts +33 -0
  39. package/dist-lib/import/packageInstaller.d.ts +111 -7
  40. package/dist-lib/import/qtProfileData.d.ts +10 -0
  41. package/dist-lib/import/remotePackageInstall.d.ts +23 -7
  42. package/dist-lib/import/zipEntries.d.ts +45 -0
  43. package/dist-lib/index.d.ts +7 -3
  44. package/dist-lib/index.js +50508 -29836
  45. package/dist-lib/logging/SessionLogger.d.ts +75 -15
  46. package/dist-lib/map/MapSelectionOverlay.d.ts +2 -2
  47. package/dist-lib/map/MapStore.d.ts +387 -60
  48. package/dist-lib/map/MudletHighlightOverlay.d.ts +2 -2
  49. package/dist-lib/map/{MudixMapReader.d.ts → MudletMapReader.d.ts} +2 -2
  50. package/dist-lib/map/areaGraph.d.ts +120 -0
  51. package/dist-lib/map/environmentKit.d.ts +36 -0
  52. package/dist-lib/map/labelPixmap.d.ts +90 -0
  53. package/dist-lib/map/mapImageExport.d.ts +36 -2
  54. package/dist-lib/map/mapStyle.d.ts +11 -0
  55. package/dist-lib/map/mapVersion.d.ts +66 -0
  56. package/dist-lib/map/pathfinding.d.ts +2 -2
  57. package/dist-lib/mud/CharLoginController.d.ts +230 -0
  58. package/dist-lib/mud/ItemIdSequence.d.ts +1 -1
  59. package/dist-lib/mud/MudSession.d.ts +279 -22
  60. package/dist-lib/mud/PatternEngine.d.ts +153 -14
  61. package/dist-lib/mud/aliases/AliasEngine.d.ts +55 -9
  62. package/dist-lib/mud/autoLogin.d.ts +59 -0
  63. package/dist-lib/mud/commandSplit.d.ts +9 -0
  64. package/dist-lib/mud/connection/LineAssembler.d.ts +38 -11
  65. package/dist-lib/mud/connection/MudClient.d.ts +291 -53
  66. package/dist-lib/mud/connection/SubnegotiationRepair.d.ts +24 -0
  67. package/dist-lib/mud/connection/TelnetNegotiator.d.ts +208 -68
  68. package/dist-lib/mud/connection/telnetDebug.d.ts +8 -8
  69. package/dist-lib/mud/events.d.ts +102 -23
  70. package/dist-lib/mud/games/bundledGames.d.ts +12 -7
  71. package/dist-lib/mud/games/gameLinks.d.ts +40 -0
  72. package/dist-lib/mud/games/icons/3Kingdoms.png +0 -0
  73. package/dist-lib/mud/games/icons/3Scapes.png +0 -0
  74. package/dist-lib/mud/games/icons/achaea.png +0 -0
  75. package/dist-lib/mud/games/icons/aetolia.png +0 -0
  76. package/dist-lib/mud/games/icons/banner_astaria.png +0 -0
  77. package/dist-lib/mud/games/icons/banner_darkmists.png +0 -0
  78. package/dist-lib/mud/games/icons/banner_dreamland.png +0 -0
  79. package/dist-lib/mud/games/icons/banner_petria.jpg +0 -0
  80. package/dist-lib/mud/games/icons/banner_ropmud.png +0 -0
  81. package/dist-lib/mud/games/icons/blackmud.png +0 -0
  82. package/dist-lib/mud/games/icons/carrionfields.png +0 -0
  83. package/dist-lib/mud/games/icons/dragonfire_icon.png +0 -0
  84. package/dist-lib/mud/games/icons/fed2-logo.png +0 -0
  85. package/dist-lib/mud/games/icons/icesus_480x120.png +0 -0
  86. package/dist-lib/mud/games/icons/imperian.png +0 -0
  87. package/dist-lib/mud/games/icons/infinity_480x120.png +0 -0
  88. package/dist-lib/mud/games/icons/lusternia.png +0 -0
  89. package/dist-lib/mud/games/icons/morgengrauen_480x120.png +0 -0
  90. package/dist-lib/mud/games/icons/mudlet-tutorial.png +0 -0
  91. package/dist-lib/mud/games/icons/phoenixmud_480x120.png +0 -0
  92. package/dist-lib/mud/games/icons/starmourn.png +0 -0
  93. package/dist-lib/mud/games/icons/voidmud_icon.png +0 -0
  94. package/dist-lib/mud/games/icons/wotmudicon.png +0 -0
  95. package/dist-lib/mud/games/websiteLinks.d.ts +21 -0
  96. package/dist-lib/mud/keybindings/KeyEngine.d.ts +110 -4
  97. package/dist-lib/mud/keybindings/browserReservedKeys.d.ts +2 -2
  98. package/dist-lib/mud/keybindings/keyEventTarget.d.ts +61 -0
  99. package/dist-lib/mud/keybindings/qtKeys.d.ts +91 -12
  100. package/dist-lib/mud/protocol/atcp.d.ts +19 -0
  101. package/dist-lib/mud/protocol/byteString.d.ts +24 -0
  102. package/dist-lib/mud/protocol/charLoginFlow.d.ts +243 -16
  103. package/dist-lib/mud/protocol/charset.d.ts +111 -46
  104. package/dist-lib/mud/protocol/codePages.d.ts +10 -0
  105. package/dist-lib/mud/protocol/constants.d.ts +17 -10
  106. package/dist-lib/mud/protocol/echo.d.ts +23 -27
  107. package/dist-lib/mud/protocol/gmcp.d.ts +36 -6
  108. package/dist-lib/mud/protocol/index.d.ts +3 -2
  109. package/dist-lib/mud/protocol/luaLiteral.d.ts +12 -0
  110. package/dist-lib/mud/protocol/mccp.d.ts +83 -1
  111. package/dist-lib/mud/protocol/mnes.d.ts +41 -58
  112. package/dist-lib/mud/protocol/msdp.d.ts +11 -4
  113. package/dist-lib/mud/protocol/msp.d.ts +3 -2
  114. package/dist-lib/mud/protocol/mssp.d.ts +9 -4
  115. package/dist-lib/mud/protocol/multiByte.d.ts +51 -0
  116. package/dist-lib/mud/protocol/multiByteEncode.d.ts +42 -0
  117. package/dist-lib/mud/protocol/mxp.d.ts +193 -14
  118. package/dist-lib/mud/protocol/oauthClientFlow.d.ts +128 -0
  119. package/dist-lib/mud/protocol/qtCodePages.generated.d.ts +1 -0
  120. package/dist-lib/mud/protocol/tlsCodes.d.ts +40 -3
  121. package/dist-lib/mud/replay/ReplayPlayer.d.ts +16 -1
  122. package/dist-lib/mud/replay/replayFormat.d.ts +29 -2
  123. package/dist-lib/mud/text/Console.d.ts +255 -49
  124. package/dist-lib/mud/text/FormatState.d.ts +137 -14
  125. package/dist-lib/mud/text/ansiEscapes.d.ts +32 -16
  126. package/dist-lib/mud/text/colorParsers.d.ts +14 -2
  127. package/dist-lib/mud/text/colorSpaceId.d.ts +2 -0
  128. package/dist-lib/mud/text/colors.d.ts +17 -10
  129. package/dist-lib/mud/text/controlCharacterMode.d.ts +1 -1
  130. package/dist-lib/mud/text/hyperlinkVisibility.d.ts +1 -1
  131. package/dist-lib/mud/text/lineBreak.d.ts +5 -0
  132. package/dist-lib/mud/text/serverWrap.d.ts +2 -2
  133. package/dist-lib/mud/text/textAnalyzer.d.ts +79 -0
  134. package/dist-lib/mud/text/unicodeRuns.d.ts +11 -0
  135. package/dist-lib/mud/text/unicodeTables.generated.d.ts +3 -0
  136. package/dist-lib/mud/text/wcwidth.d.ts +27 -22
  137. package/dist-lib/mud/timers/TimerEngine.d.ts +163 -11
  138. package/dist-lib/mud/timers/workerClock.d.ts +67 -0
  139. package/dist-lib/mud/triggers/TriggerEngine.d.ts +449 -47
  140. package/dist-lib/mud/triggers/legacyColorPatterns.d.ts +58 -0
  141. package/dist-lib/mud/triggers/pcre/Pcre2.d.ts +83 -1
  142. package/dist-lib/oauth-callback.html +94 -0
  143. package/dist-lib/pcre2Wasm.d.ts +54 -0
  144. package/dist-lib/pcre2Wasm.js +241 -0
  145. package/dist-lib/scripting/EngineHost.d.ts +45 -21
  146. package/dist-lib/scripting/IScriptingRuntime.d.ts +103 -27
  147. package/dist-lib/scripting/MxpFrameManager.d.ts +10 -1
  148. package/dist-lib/scripting/ScriptingAPI.d.ts +1030 -213
  149. package/dist-lib/scripting/ScriptingEngine.d.ts +727 -106
  150. package/dist-lib/scripting/StopwatchManager.d.ts +97 -36
  151. package/dist-lib/scripting/http/HttpService.d.ts +9 -1
  152. package/dist-lib/scripting/http/userUrl.d.ts +41 -0
  153. package/dist-lib/scripting/lua/LuaRuntime.d.ts +352 -77
  154. package/dist-lib/scripting/lua/argContracts.d.ts +71 -0
  155. package/dist-lib/scripting/lua/bindings/automation.d.ts +1 -1
  156. package/dist-lib/scripting/lua/bindings/commands.d.ts +13 -0
  157. package/dist-lib/scripting/lua/bindings/context.d.ts +20 -2
  158. package/dist-lib/scripting/lua/bindings/diagnostics.d.ts +1 -1
  159. package/dist-lib/scripting/lua/bindings/map.d.ts +1 -1
  160. package/dist-lib/scripting/lua/bindings/media.d.ts +2 -2
  161. package/dist-lib/scripting/lua/bindings/output.d.ts +1 -1
  162. package/dist-lib/scripting/lua/bindings/session.d.ts +2 -2
  163. package/dist-lib/scripting/lua/bindings/textEdit.d.ts +1 -1
  164. package/dist-lib/scripting/lua/bindings/userWindows.d.ts +1 -1
  165. package/dist-lib/scripting/lua/byteArmor.d.ts +36 -0
  166. package/dist-lib/scripting/lua/imageSize.d.ts +7 -0
  167. package/dist-lib/scripting/lua/rex.d.ts +4 -2
  168. package/dist-lib/scripting/lua/sqlRowEncoder.d.ts +6 -1
  169. package/dist-lib/scripting/lua/utf8CaseMap.d.ts +1 -0
  170. package/dist-lib/scripting/lua/utf8Patterns.d.ts +21 -1
  171. package/dist-lib/scripting/lua/wellFormedStrings.d.ts +40 -0
  172. package/dist-lib/scripting/lua/yajl.d.ts +43 -5
  173. package/dist-lib/scripting/profilesPresence.d.ts +20 -2
  174. package/dist-lib/scripting/vfs/ProfileVFS.d.ts +164 -10
  175. package/dist-lib/scripting/vfs/fsErrors.d.ts +28 -0
  176. package/dist-lib/scripting/vfs/idbCommit.d.ts +20 -0
  177. package/dist-lib/storage/appStore.d.ts +24 -9
  178. package/dist-lib/storage/hooks.d.ts +5 -1
  179. package/dist-lib/storage/index.d.ts +2 -2
  180. package/dist-lib/storage/mapStorage.d.ts +2 -0
  181. package/dist-lib/storage/persistentStorage.d.ts +3 -1
  182. package/dist-lib/storage/profileStorage.d.ts +15 -0
  183. package/dist-lib/storage/profileVfsData.d.ts +3 -3
  184. package/dist-lib/storage/schema.d.ts +512 -40
  185. package/dist-lib/storage/storageMigration.d.ts +82 -0
  186. package/dist-lib/storage-g5V1b-c1.js +2039 -0
  187. package/dist-lib/styles.css +1 -1
  188. package/dist-lib/ui/AboutModal.d.ts +1 -1
  189. package/dist-lib/ui/BrandLoginFields.d.ts +1 -1
  190. package/dist-lib/ui/BrowserSignInModal.d.ts +23 -0
  191. package/dist-lib/ui/CmdLineMenuRegistry.d.ts +14 -5
  192. package/dist-lib/ui/CommandBar.d.ts +8 -8
  193. package/dist-lib/ui/ConnectionFormModal.d.ts +20 -1
  194. package/dist-lib/ui/ConnectionScreen.d.ts +9 -1
  195. package/dist-lib/ui/GameLinkPrompt.d.ts +28 -0
  196. package/dist-lib/ui/HelpModal.d.ts +5 -1
  197. package/dist-lib/ui/MapSymbolUsageModal.d.ts +32 -0
  198. package/dist-lib/ui/MouseEventRegistry.d.ts +31 -4
  199. package/dist-lib/ui/NotepadModal.d.ts +22 -0
  200. package/dist-lib/ui/ResizableModal.d.ts +16 -1
  201. package/dist-lib/ui/SettingsModal.d.ts +10 -1
  202. package/dist-lib/ui/TlsAlertBanner.d.ts +3 -1
  203. package/dist-lib/ui/Toolbar.d.ts +22 -1
  204. package/dist-lib/ui/VaultManageButton.d.ts +10 -5
  205. package/dist-lib/ui/VaultModal.d.ts +3 -0
  206. package/dist-lib/ui/buttons/ButtonsBar.d.ts +3 -1
  207. package/dist-lib/ui/buttons/inactiveButtons.d.ts +25 -0
  208. package/dist-lib/ui/cmdline/CommandLineManager.d.ts +19 -0
  209. package/dist-lib/ui/cmdline/plainText.d.ts +16 -0
  210. package/dist-lib/ui/cmdline/subCommandLine.d.ts +78 -0
  211. package/dist-lib/ui/cmdline/useCmdLineSelection.d.ts +26 -0
  212. package/dist-lib/ui/cmdline/useSubCommandLineKeys.d.ts +33 -0
  213. package/dist-lib/ui/codemirror/lineParagraphMarks.d.ts +19 -0
  214. package/dist-lib/ui/codemirror/luaHover.d.ts +7 -0
  215. package/dist-lib/ui/codemirror/options.d.ts +33 -0
  216. package/dist-lib/ui/codemirror/theme.d.ts +29 -5
  217. package/dist-lib/ui/commands/addonCommands.d.ts +134 -0
  218. package/dist-lib/ui/commands/appShortcuts.d.ts +86 -0
  219. package/dist-lib/ui/commands/hostCommands.d.ts +88 -0
  220. package/dist-lib/ui/commands/keyMatch.d.ts +20 -0
  221. package/dist-lib/ui/commands/keySequence.d.ts +57 -0
  222. package/dist-lib/ui/components/ContextMenu.d.ts +21 -1
  223. package/dist-lib/ui/components/FontPicker.d.ts +5 -1
  224. package/dist-lib/ui/components/useModalFocus.d.ts +13 -1
  225. package/dist-lib/ui/helpTopics.d.ts +15 -0
  226. package/dist-lib/ui/labels/LabelManager.d.ts +172 -9
  227. package/dist-lib/ui/labels/LabelOverlay.d.ts +19 -0
  228. package/dist-lib/ui/labels/backgroundImageSize.d.ts +19 -0
  229. package/dist-lib/ui/labels/labelModel.d.ts +64 -0
  230. package/dist-lib/ui/labels/qColor.d.ts +13 -0
  231. package/dist-lib/ui/labels/qtCss.d.ts +12 -4
  232. package/dist-lib/ui/landmarks.d.ts +9 -0
  233. package/dist-lib/ui/launcher/ActionMenu.d.ts +19 -0
  234. package/dist-lib/ui/launcher/GameDetails.d.ts +21 -0
  235. package/dist-lib/ui/launcher/GameSection.d.ts +18 -0
  236. package/dist-lib/ui/launcher/LauncherSearch.d.ts +23 -0
  237. package/dist-lib/ui/launcher/ProfileArt.d.ts +20 -0
  238. package/dist-lib/ui/launcher/ProfileSection.d.ts +43 -0
  239. package/dist-lib/ui/launcher/launcherModel.d.ts +72 -0
  240. package/dist-lib/ui/layout/overlayLayerOrder.d.ts +2 -2
  241. package/dist-lib/ui/menu/MenuBar.d.ts +31 -0
  242. package/dist-lib/ui/menu/SplitButton.d.ts +39 -0
  243. package/dist-lib/ui/menu/anchoredPopup.d.ts +74 -0
  244. package/dist-lib/ui/menu/appMenus.d.ts +65 -0
  245. package/dist-lib/ui/menu/menuModel.d.ts +88 -0
  246. package/dist-lib/ui/menu/toolbarModel.d.ts +56 -0
  247. package/dist-lib/ui/notepad.d.ts +76 -0
  248. package/dist-lib/ui/openSignInPage.d.ts +14 -0
  249. package/dist-lib/ui/output/OutputContextMenu.d.ts +14 -1
  250. package/dist-lib/ui/output/OutputRenderer.d.ts +5 -0
  251. package/dist-lib/ui/output/OutputSearchBar.d.ts +5 -1
  252. package/dist-lib/ui/output/StickyOutputPanel.d.ts +17 -3
  253. package/dist-lib/ui/output/TextAnalyzerModal.d.ts +25 -0
  254. package/dist-lib/ui/output/caretMode.d.ts +3 -2
  255. package/dist-lib/ui/output/clearSplit.d.ts +11 -0
  256. package/dist-lib/ui/output/outputCopy.d.ts +41 -2
  257. package/dist-lib/ui/output/outputRows.d.ts +43 -0
  258. package/dist-lib/ui/output/selectionGesture.d.ts +35 -0
  259. package/dist-lib/ui/output/wordSelection.d.ts +33 -0
  260. package/dist-lib/ui/search/matcher.d.ts +14 -4
  261. package/dist-lib/ui/settings/SettingsShell.d.ts +91 -0
  262. package/dist-lib/ui/settings/ShortcutEditor.d.ts +13 -0
  263. package/dist-lib/ui/sound/SoundManager.d.ts +210 -44
  264. package/dist-lib/ui/sound/closedCaption.d.ts +4 -1
  265. package/dist-lib/ui/sound/mediaDirection.d.ts +35 -0
  266. package/dist-lib/ui/tabCompletion.d.ts +53 -0
  267. package/dist-lib/ui/textedit/TextEditManager.d.ts +11 -2
  268. package/dist-lib/ui/useOpenProfiles.d.ts +1 -1
  269. package/dist-lib/ui/video/VideoManager.d.ts +7 -0
  270. package/dist-lib/ui/windows/WindowManager.d.ts +452 -37
  271. package/dist-lib/ui/windows/panels/ScriptEditorPanel.d.ts +14 -0
  272. package/dist-lib/ui/windows/panels/ScriptSearch.d.ts +6 -1
  273. package/dist-lib/ui/windows/panels/TextPanel.d.ts +4 -1
  274. package/dist-lib/ui/windows/panels/VariablesView.d.ts +37 -7
  275. package/dist-lib/ui/windows/panels/WindowCmdLine.d.ts +4 -2
  276. package/dist-lib/ui/windows/panels/aliasLoop.d.ts +24 -0
  277. package/dist-lib/ui/windows/panels/editorClipboard.d.ts +45 -0
  278. package/dist-lib/ui/windows/panels/editorUndo.d.ts +79 -0
  279. package/dist-lib/ui/windows/panels/mapAreaChange.d.ts +10 -0
  280. package/dist-lib/utils/appShellCache.d.ts +25 -0
  281. package/dist-lib/utils/fontFamilyName.d.ts +13 -0
  282. package/dist-lib/utils/fontLoader.d.ts +31 -0
  283. package/dist-lib/utils/formatBytes.d.ts +4 -0
  284. package/dist-lib/utils/mustBeOneOf.d.ts +9 -0
  285. package/dist-lib/utils/profileLock.d.ts +1 -1
  286. package/dist-lib/utils/systemTheme.d.ts +24 -0
  287. package/dist-lib/utils/timeZone.d.ts +10 -0
  288. package/dist-lib/vault/CredentialVault.d.ts +51 -5
  289. package/dist-lib/vault/deviceUnlock.d.ts +47 -0
  290. package/dist-lib/vault/vaultAccess.d.ts +24 -2
  291. package/dist-lib/vault/vaultHelpTopic.d.ts +9 -0
  292. package/dist-lib/vault/vaultRecord.d.ts +33 -1
  293. package/dist-lib/vfs-sw.js +220 -11
  294. package/dist-lib/vite.d.ts +1 -1
  295. package/dist-lib/vite.js +66 -43
  296. package/package.json +23 -15
  297. package/dist-lib/assets/mapParser.worker-t-3rd1zR.js +0 -9
  298. package/dist-lib/mud/connection/PingTracker.d.ts +0 -41
  299. package/dist-lib/ui/BundledGameGrid.d.ts +0 -21
  300. package/dist-lib/ui/ConnectionGrid.d.ts +0 -21
  301. package/dist-lib/ui/bufferWords.d.ts +0 -38
@@ -15,21 +15,37 @@ export interface PlaySoundOptions {
15
15
  fadeout?: number;
16
16
  /** Start offset within the buffer, in milliseconds. */
17
17
  start?: number;
18
+ /** Position in the track, in milliseconds, at which playback ends (Mudlet's
19
+ * `finish`). Absent → the end of the file. Each pass of a loop ends there. */
20
+ finish?: number;
18
21
  /** Loop count. 1 = play once (default). -1 = infinite. N>1 = N total plays. */
19
22
  loops?: number;
20
23
  /** Dedupe key — calling again with same key replaces the previous one. */
21
24
  key?: string;
22
25
  /** Group tag — stopMusic({tag=...}) and stopSounds() filter on this. */
23
26
  tag?: string;
27
+ /** 1..100 — Mudlet's media priority (sounds only). A sound with a priority
28
+ * is refused while one of equal or higher priority is playing, and stops
29
+ * the lower-priority ones when it does play (TMedia::
30
+ * doesMediaHavePriorityToPlay). Absent → no priority, never refused. */
31
+ priority?: number;
24
32
  /** Which mute gate governs this playback. Default 'api'. */
25
33
  origin?: MediaOrigin;
26
34
  /** Optional closed-caption text (Mudlet's media `caption`). Shown verbatim
27
35
  * when closed captions are on; absent → a caption is synthesized from the
28
36
  * kind + filename. */
29
37
  caption?: string;
38
+ /** Sounds only: -100 (left) to 100 (right), already held to that range —
39
+ * Client.Media 2's `pan`. Wins over a direction. */
40
+ pan?: number;
41
+ /** Sounds only: where the sound comes from, as canonicalMediaDirection
42
+ * spells it — panned by the way the listener faces. */
43
+ direction?: string;
30
44
  }
31
45
  export interface PlayMusicOptions extends PlaySoundOptions {
32
- /** If true and a music track with the same name+key is already playing, do nothing. */
46
+ /** If true and a music track with the same name (and key, when one is
47
+ * given) is already playing, do nothing. Mudlet's default is true; the
48
+ * callers supply it, so absent here means false. */
33
49
  continue?: boolean;
34
50
  }
35
51
  export interface StopMusicOptions {
@@ -38,11 +54,62 @@ export interface StopMusicOptions {
38
54
  tag?: string;
39
55
  /** Fade-out duration in milliseconds. Overrides the source's own fadeout. */
40
56
  fadeout?: number;
57
+ /** Mudlet's `fadeaway`: fade out before stopping — over `fadeout`, else
58
+ * the source's own fadeout, else {@link DEFAULT_FADEAWAY_MS} — and keep
59
+ * the media listed as playing until the fade is over. */
60
+ fadeaway?: boolean;
41
61
  }
62
+ /**
63
+ * Which playing media a stop, pause or query applies to. Every field that is
64
+ * set must match. `name` matches the name a source was played under, the path
65
+ * it resolved to, or either's trailing filename; `priority` is a ceiling — a
66
+ * query passes over a source whose own priority is above it, and a stop or
67
+ * pause also spares one whose priority equals it (only lower priorities are
68
+ * stopped, as on desktop). A source without a priority counts as 0; `origin`
69
+ * narrows to script- or server-started media.
70
+ */
71
+ export interface MediaFilter {
72
+ name?: string;
73
+ key?: string;
74
+ tag?: string;
75
+ priority?: number;
76
+ origin?: MediaOrigin;
77
+ }
78
+ export interface StopSoundsOptions extends MediaFilter {
79
+ /** Fade-out duration in milliseconds. Overrides the source's own fadeout. */
80
+ fadeout?: number;
81
+ /** See {@link StopMusicOptions.fadeaway}. */
82
+ fadeaway?: boolean;
83
+ }
84
+ /** How long a `fadeaway` stop fades for when neither the stop nor the media
85
+ * names a fadeout — desktop's TMedia default. */
86
+ export declare const DEFAULT_FADEAWAY_MS = 5000;
87
+ /**
88
+ * Turns a media name into the path that is actually played. The engine wires
89
+ * one that finds the file in the profile VFS (so the media events carry its
90
+ * full path, as desktop's do) and expands a `*`/`?` wildcard to one matching
91
+ * file. Null means there is no such file: the request is refused there and
92
+ * then, and never listed as playing. Without a resolver, the name is played as
93
+ * given.
94
+ */
95
+ export type MediaPathResolver = (name: string) => string | null;
42
96
  export declare class SoundManager {
43
97
  private nextId;
44
98
  private active;
45
99
  private loader;
100
+ private resolver;
101
+ /**
102
+ * Bumped by every {@link stopAll}. `play()` has to await a fetch + decode
103
+ * before it can build a source, and a profile close (or resetProfile)
104
+ * landing inside that window would otherwise start the sound *after*
105
+ * teardown stopped everything — the manager has nothing to stop yet, so the
106
+ * track begins playing over a closed profile with no way left to reach it.
107
+ * A play captures the epoch before awaiting and abandons itself if it moved.
108
+ */
109
+ private epoch;
110
+ /** Set by {@link destroy}. Unlike an epoch bump this is permanent: the
111
+ * session is gone, so no in-flight or later play may start. */
112
+ private destroyed;
46
113
  /** 0..1, applied as an extra multiplier on every source's gain. */
47
114
  private masterVolume;
48
115
  /**
@@ -54,6 +121,11 @@ export declare class SoundManager {
54
121
  * tearing them down.
55
122
  */
56
123
  private muted;
124
+ /** The way the listener faces (TMedia::mListenerFacing), and the one a
125
+ * script last chose, which a game's Client.Media.Listener does not
126
+ * overwrite (mScriptListenerFacing). */
127
+ private listenerFacing;
128
+ private scriptListenerFacing;
57
129
  /**
58
130
  * Raised when a tracked source starts playing. ScriptingEngine wires this
59
131
  * to Mudlet's `sysMediaStarted(file, path, mediaType, key, tag)` — the same
@@ -61,9 +133,11 @@ export declare class SoundManager {
61
133
  *
62
134
  * Fired after `source.start()` has actually been accepted, so a decode
63
135
  * failure or a rejected start never announces a playback that isn't
64
- * happening. Mudlet withholds it for preload-volume loads; mudix has no
65
- * preload volume (`preload()` only warms the decode cache and never builds
66
- * a source), so there is nothing to withhold it for.
136
+ * happening. A paused source raises it again when it resumes, as a player
137
+ * re-entering PlayingState does. Mudlet withholds it for preload-volume
138
+ * loads; Mudlet Web has no preload volume (`preload()` only warms the
139
+ * decode cache and never builds a source), so there is nothing to withhold
140
+ * it for.
67
141
  */
68
142
  onMediaStarted?: (file: string, path: string, mediaType: MediaKind, key: string, tag: string) => void;
69
143
  /**
@@ -73,6 +147,9 @@ export declare class SoundManager {
73
147
  * each source's onended before stopping, so engine teardown never fires it.
74
148
  */
75
149
  onMediaFinished?: (file: string, path: string, mediaType: MediaKind, key: string, tag: string) => void;
150
+ /** Raised when pauseSounds / pauseMusic hold a playing source — Mudlet's
151
+ * `sysMediaPaused`, with the same five arguments. */
152
+ onMediaPaused?: (file: string, path: string, mediaType: MediaKind, key: string, tag: string) => void;
76
153
  /**
77
154
  * Raised when a tracked source starts ('plays') or ends ('stops'), so the
78
155
  * engine can print a closed caption (Mudlet's enableClosedCaption). Fires
@@ -81,6 +158,7 @@ export declare class SoundManager {
81
158
  */
82
159
  onMediaCaption?: (info: MediaCaptionInfo) => void;
83
160
  setLoader(fn: LoaderFn | null): void;
161
+ setPathResolver(fn: MediaPathResolver | null): void;
84
162
  setMasterVolume(value: number): void;
85
163
  /**
86
164
  * Mudlet `muteMediaAPI` / `muteMediaGame`. Sets the persistent mute gate for
@@ -97,44 +175,70 @@ export declare class SoundManager {
97
175
  private effectiveGain;
98
176
  playSound(opts: PlaySoundOptions): Promise<number>;
99
177
  playMusic(opts: PlayMusicOptions): Promise<number>;
100
- stopSounds(): void;
101
- /**
102
- * Mudlet `pauseSounds([channel])`. Web Audio source nodes can be
103
- * scheduled to start but not paused once playing — they're transient by
104
- * design, with no equivalent of QMediaPlayer::pause(). We approximate
105
- * Mudlet's contract by stopping the matching sources outright (so the
106
- * mute happens immediately) and let the player retrigger them with
107
- * `playSoundFile` to resume. The optional `channel` filters by the
108
- * source's `tag` (matches Mudlet's "channel" semantics: a Tag string
109
- * passed to playSoundFile). Music sources are untouched — they have a
110
- * separate `stopMusic` codepath.
111
- */
112
- pauseSounds(channel?: string): void;
113
- /**
114
- * Mudlet `pauseMusic([settings])`. Web Audio source nodes can't truly
115
- * pause once started (same constraint as {@link pauseSounds}), so this is
116
- * an immediate fade-out + stop of the matching music sources — re-trigger
117
- * `playMusicFile` to "resume". The optional `channel`/tag filters which
118
- * music tracks are affected; sound effects are untouched.
119
- */
120
- pauseMusic(channel?: string): void;
121
- stopMusic(opts?: StopMusicOptions): void;
122
- /**
123
- * Mudlet getPlayingSounds / getPlayingMusic. Returns the currently-playing
124
- * sources of the requested `kind` (default 'sound' — music is reported
125
- * separately by getPlayingMusic) optionally filtered by name/key/tag.
126
- * Volume is reported on Mudlet's 0..100 scale.
127
- */
128
- getPlaying(filter?: {
178
+ /**
179
+ * Mudlet `updateSounds` / Client.Media.Update — TMedia::updateMedia. Moves
180
+ * the script- (or game-) started media `filter` names to a new volume
181
+ * (1..100), pan or direction, gliding over `glideMs`. Sounds only, unless
182
+ * `filter.kinds` says otherwise: a Client.Media.Update without a type
183
+ * reaches music too. A key or tag must be the source's own; a name matches
184
+ * as a stop's does. Loading and paused sources move too. Pan and direction
185
+ * place sounds only, and a new direction takes over from a pan given
186
+ * earlier, or it would never be heard. Returns how many moved.
187
+ */
188
+ updateSounds(filter: {
129
189
  name?: string;
130
190
  key?: string;
131
191
  tag?: string;
132
- }, kind?: 'sound' | 'music'): Array<{
133
- name: string;
134
- key?: string;
135
- tag?: string;
136
- volume: number;
137
- }>;
192
+ origin: MediaOrigin;
193
+ kinds?: readonly ('sound' | 'music')[];
194
+ }, change: {
195
+ volume?: number;
196
+ pan?: number;
197
+ direction?: string;
198
+ glideMs?: number;
199
+ }): number;
200
+ /**
201
+ * Turn the listener to `facing` (canonical; a compass word or degrees) —
202
+ * TMedia::setListenerFacing. Refused (false) for up, down and the words
203
+ * relative to the player. Every placed sound without a pan of its own
204
+ * turns with it.
205
+ */
206
+ setListenerFacing(facing: string, setBy: 'script' | 'game'): boolean;
207
+ /** The way the listener faces now (TMedia::listenerFacing). */
208
+ getListenerFacing(): string;
209
+ /** Face the way a script last chose, or north — TMedia::resetListenerFacing,
210
+ * for a new connection. */
211
+ resetListenerFacing(): void;
212
+ private applyPan;
213
+ /** Mudlet `stopSounds([filter])` — stop the sounds matching `filter`
214
+ * (every sound when it is empty). Only priorities below the filter's are
215
+ * stopped. */
216
+ stopSounds(opts?: StopSoundsOptions): void;
217
+ /**
218
+ * Mudlet `pauseSounds([filter])`. A Web Audio source node can't be paused,
219
+ * so a paused source drops its node and remembers its position; playing
220
+ * the same name and key again ({@link play}) resumes it from there on a new
221
+ * node. A string filters by tag, Mudlet's "channel". Music is untouched —
222
+ * {@link pauseMusic} covers it.
223
+ */
224
+ pauseSounds(channel?: string | MediaFilter): void;
225
+ /** Mudlet `pauseMusic([filter])` — {@link pauseSounds} for music. */
226
+ pauseMusic(channel?: string | MediaFilter): void;
227
+ stopMusic(opts?: StopMusicOptions & {
228
+ origin?: MediaOrigin;
229
+ }): void;
230
+ /**
231
+ * Mudlet getPlayingSounds / getPlayingMusic. Returns the sources of the
232
+ * requested `kind` (default 'sound' — music is reported separately by
233
+ * getPlayingMusic) that are playing — from the moment they are asked to
234
+ * play until they end, a fade-out included — optionally filtered. Mudlet
235
+ * lists only the media its Lua API started, so the Lua bindings pass
236
+ * `origin: 'api'`. Volume is reported on Mudlet's 0..100 scale.
237
+ */
238
+ getPlaying(filter?: MediaFilter, kind?: 'sound' | 'music'): MediaListing[];
239
+ /** Mudlet getPausedSounds / getPausedMusic — {@link getPlaying} for the
240
+ * sources pauseSounds / pauseMusic hold. */
241
+ getPaused(filter?: MediaFilter, kind?: 'sound' | 'music'): MediaListing[];
138
242
  /**
139
243
  * Mudlet loadSoundFile. Preloads (decodes + caches) a sound so the first
140
244
  * playSoundFile has no decode latency. Fire-and-forget: warms `decodeCache`
@@ -143,19 +247,81 @@ export declare class SoundManager {
143
247
  */
144
248
  preload(name: string): boolean;
145
249
  /**
146
- * Mudlet `purgeMediaCache()` — drop every decoded-audio buffer so the next
147
- * play of any file re-fetches and re-decodes it. Active playback is
148
- * untouched (the cache only fronts the decode step). Always returns true.
250
+ * Mudlet `purgeMediaCache()` — stop every sound and music track, each
251
+ * raising its sysMediaFinished as TMedia::stopAllMediaPlayers does, and
252
+ * drop every decoded-audio buffer so the next play re-fetches and
253
+ * re-decodes. Deleting the cached files themselves is the caller's part.
254
+ * Always returns true.
149
255
  */
150
256
  purgeCache(): boolean;
151
- /** Stop everything this manager owns. Call on engine teardown. */
257
+ /** Stop everything this manager owns — including plays still awaiting a
258
+ * decode, which abandon themselves rather than starting afterwards. Call
259
+ * on engine teardown. */
152
260
  stopAll(): void;
153
261
  destroy(): void;
262
+ private resolve;
263
+ private list;
154
264
  private play;
265
+ /**
266
+ * Start a pass of `a` at `offsetSec` on a fresh node (a node can be started
267
+ * once). Web Audio's loop flag only repeats forever, so it serves -1 alone,
268
+ * looping between start and finish when a finish is set; a finite count
269
+ * plays each pass on its own node, and each pass is reported with its own
270
+ * sysMediaStarted / sysMediaFinished, as Mudlet's playlist does. A finish
271
+ * ends each finite pass there.
272
+ */
273
+ private startPass;
274
+ private onPassEnded;
275
+ /**
276
+ * Take `a` off the books and report its end. A stop reports it inside the
277
+ * call, as desktop's does, but prints the closing caption a turn later:
278
+ * TMedia releases a stopped player one event-loop turn late, and that turn
279
+ * is what prints it.
280
+ */
281
+ private end;
282
+ /**
283
+ * Mudlet's media events are (file, path, mediaType, key, tag): the played
284
+ * file's name, then its full path. An absent key or tag is an empty
285
+ * QString there, so it must be '' here and not undefined — a nil would
286
+ * shift every argument after it in Lua.
287
+ */
288
+ private eventArgs;
289
+ private announceStart;
290
+ private announceFinish;
291
+ private pauseKind;
292
+ /** Where in the track `a`'s current pass has got to, in seconds. */
293
+ private position;
294
+ /** Resume the paused source a play request names — see {@link resume}. */
295
+ private resumeMatching;
296
+ /**
297
+ * Resume a paused source of `kind` that the request matches, the way
298
+ * desktop's isMediaMatch() picks one: each of name, key and tag that the
299
+ * request gives must match, and it must give at least one. This is how a
300
+ * server resumes over GMCP with a key or tag alone. Returns the source's
301
+ * id, or undefined when nothing paused matches.
302
+ */
303
+ resume(kind: 'sound' | 'music', req: {
304
+ name?: string;
305
+ key?: string;
306
+ tag?: string;
307
+ origin?: MediaOrigin;
308
+ }): number | undefined;
155
309
  private fadeAndStop;
156
- private isMusicPlaying;
310
+ /** The music track a `continue` request would carry on with: the same
311
+ * name, and the same key when the request gives one. */
312
+ private playingMusic;
157
313
  private stopMusicMatching;
158
314
  private updateMediaSessionState;
159
315
  private firstActiveMusicName;
160
316
  }
317
+ /** One entry of {@link SoundManager.getPlaying} / {@link SoundManager.getPaused}. */
318
+ export interface MediaListing {
319
+ name: string;
320
+ key?: string;
321
+ tag?: string;
322
+ volume: number;
323
+ priority?: number;
324
+ pan?: number;
325
+ direction?: string;
326
+ }
161
327
  export {};
@@ -13,7 +13,7 @@
13
13
  * through the media player and so are never captioned. */
14
14
  export type MediaKind = 'sound' | 'music' | 'video';
15
15
  /** The player-lifecycle verb shown in the caption. Mudlet also has pauses/fades,
16
- * but mudix's Web Audio model collapses those into a stop, so we expose the two
16
+ * but Mudlet Web's Web Audio model collapses those into a stop, so we expose the two
17
17
  * transitions that map cleanly. */
18
18
  export type CaptionAction = 'plays' | 'stops';
19
19
  export interface MediaCaptionInfo {
@@ -24,6 +24,9 @@ export interface MediaCaptionInfo {
24
24
  key?: string;
25
25
  /** Explicit caption from the media packet / Lua `caption` arg, if any. */
26
26
  caption?: string;
27
+ /** Sounds only: where it comes from (canonical), shown after the caption
28
+ * so where a sound comes from never depends on hearing it. */
29
+ direction?: string;
27
30
  action: CaptionAction;
28
31
  }
29
32
  /**
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Where a sound comes from, and which way the player faces — the placement half
3
+ * of Mudlet's Client.Media 2 (TMedia::canonicalMediaDirection,
4
+ * mediaDirectionBearing and stereoPan).
5
+ *
6
+ * A direction is kept as desktop keeps it: a compass word ("north",
7
+ * "northeast", ...), one of the words relative to the player ("ahead",
8
+ * "behind", "left", "right"), "up" / "down", or whole degrees as a string
9
+ * ("0" to "359", 0 being north and 90 east).
10
+ */
11
+ /** The pan range, TMediaData::MediaPanLeft / MediaPanRight. */
12
+ export declare const MEDIA_PAN_LEFT = -100;
13
+ export declare const MEDIA_PAN_RIGHT = 100;
14
+ /** A direction spelled as TMedia keeps it, or '' when it names none. A number
15
+ * (or a string reading as one) is whole degrees, wrapped onto 0..359. */
16
+ export declare function canonicalMediaDirection(direction: string | number): string;
17
+ /** The bearing of a canonical direction in degrees, and whether it is relative
18
+ * to the way the player faces; null for up, down and anything unknown. */
19
+ export declare function mediaDirectionBearing(direction: string): {
20
+ bearing: number;
21
+ relative: boolean;
22
+ } | null;
23
+ /** Whether `facing` is a way a player can turn to: a compass word or degrees,
24
+ * not up, down or a word relative to the player. */
25
+ export declare function isListenerFacing(facing: string): boolean;
26
+ /**
27
+ * The stereo pan (-100..100) a sound is heard at — TMedia::stereoPan. A pan of
28
+ * its own wins; otherwise its direction is turned by the way the player faces,
29
+ * clockwise of which is to the right. Ahead and behind both centre, as stereo
30
+ * cannot tell front from back. Undefined when the sound is not placed at all.
31
+ */
32
+ export declare function stereoPan(pan: number | undefined, direction: string | undefined, facing: string): number | undefined;
33
+ /** A direction as a caption shows it, after the caption text:
34
+ * TMedia::mediaDirectionCaption. */
35
+ export declare function mediaDirectionCaption(direction: string): string;
@@ -0,0 +1,53 @@
1
+ /** How much of the main console TCommandLine::handleTabCompletion reads. */
2
+ export declare const TAB_COMPLETION_LINES = 500;
3
+ /**
4
+ * The candidate words, in the order desktop builds them: the buffer lines
5
+ * joined with spaces and split at word boundaries, then the suggestions, with
6
+ * anything on the blacklist (compared case-insensitively) taken out. Only the
7
+ * word runs of the buffer are kept — the runs between them start with a
8
+ * non-word character, so no completion pattern could match one anyway.
9
+ */
10
+ export declare function tabCompletionPool(lines: readonly string[], suggestions?: Iterable<string>, blacklist?: Iterable<string>): string[];
11
+ export interface TabCompletionMatches {
12
+ /** The text kept in front of the proposal (`mTabCompletionTyped.left(typePosition)`). */
13
+ userWords: string;
14
+ /** Candidates in Tab order, newest first; never empty. */
15
+ matches: string[];
16
+ }
17
+ /**
18
+ * What a Tab on `typed` can complete to, or null when desktop would do nothing:
19
+ * nothing typed, a trailing space, or no candidate.
20
+ *
21
+ * The word completed is the run of word characters at the very end; a
22
+ * candidate has to start with it (ignoring case) and carry at least one more
23
+ * word character straight after (`^<word>\w+`), so `zq` never offers
24
+ * `zq-thing` and `zqo` never offers `zqo'brien`. Repeats collapse only when
25
+ * spelled exactly alike — `zqcase` and `ZQCASE` are two candidates — and each
26
+ * candidate takes the place of its LAST occurrence, so the most recently seen
27
+ * comes first. When the text ends in some other character there is no word,
28
+ * desktop's `left(-1)` keeps the whole text, and any word at all is appended.
29
+ */
30
+ export declare function tabCompletionMatches(typed: string, pool: readonly string[]): TabCompletionMatches | null;
31
+ /**
32
+ * One command line's Tab state — desktop's mTabCompletionTyped /
33
+ * mTabCompletionCount / mTabCompletionOld. The first Tab remembers what was
34
+ * typed; later presses complete that same text again, stepping forward (Tab)
35
+ * or back (Shift+Tab) through the candidates and stopping at either end rather
36
+ * than wrapping. Typing anything in between starts over from the new text.
37
+ */
38
+ export declare class TabCompletionCycle {
39
+ private typed;
40
+ private count;
41
+ private lastWritten;
42
+ /** Forget the cycle: Escape, Space, Enter, or an edit. */
43
+ reset(): void;
44
+ /**
45
+ * A Tab (`dir` 1) or Shift+Tab (-1) on a line holding `current`. Returns the
46
+ * new line text and the proposal, or null when there is nothing to complete
47
+ * (the line is then left as it is).
48
+ */
49
+ step(current: string, dir: 1 | -1, pool: () => readonly string[]): {
50
+ text: string;
51
+ proposal: string;
52
+ } | null;
53
+ }
@@ -22,13 +22,21 @@ export interface TextEditState {
22
22
  tabMovesFocus: boolean;
23
23
  visible: boolean;
24
24
  }
25
+ /**
26
+ * The text a QPlainTextEdit gives back for `text` set into it. setPlainText
27
+ * splits blocks at CR, CRLF and LF alike, and toPlainText joins them — and any
28
+ * Unicode line or paragraph separator — with LF, turns a no-break space into a
29
+ * plain one, and leaves off a leading byte order mark.
30
+ */
31
+ export declare function toPlainText(text: string): string;
25
32
  export declare class TextEditManager {
26
33
  private edits;
27
34
  has(name: string): boolean;
28
35
  /** Read-only handle on a text edit's stored state, for the geometry and
29
36
  * visibility getters (getWindowGeometry, windowVisible). */
30
37
  get(name: string): Readonly<TextEditState> | undefined;
31
- /** Create (or replace) a text edit. Returns true (Mudlet always succeeds). */
38
+ /** Create a text edit. False when one of that name already exists — it is
39
+ * left as it was, as TMainConsole::createTextBox leaves it. */
32
40
  create(name: string, opts: {
33
41
  parent: string;
34
42
  x: number;
@@ -37,7 +45,8 @@ export declare class TextEditManager {
37
45
  height: number;
38
46
  }): boolean;
39
47
  destroy(name: string): boolean;
40
- /** Returns the editor's text, or null when no editor of that name exists. */
48
+ /** Returns the editor's text as QPlainTextEdit::toPlainText() hands it
49
+ * back, or null when no editor of that name exists. */
41
50
  getText(name: string): string | null;
42
51
  setText(name: string, text: string): boolean;
43
52
  clear(name: string): boolean;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Connection ids currently open in *another* browser tab.
3
3
  *
4
- * Every open profile holds an exclusive Web Lock named `mudix:profile:<id>`
4
+ * Every open profile holds an exclusive Web Lock named `mudlet:profile:<id>`
5
5
  * (see profileLock.ts), and `navigator.locks.query()` lists held locks across
6
6
  * all same-origin tabs — so the held profile locks are exactly the open set.
7
7
  * The connection screen renders with no profile active, so this tab holds no
@@ -33,6 +33,13 @@ export declare class VideoManager {
33
33
  * still reports what the script asked for.
34
34
  */
35
35
  private muted;
36
+ /** Bumped by every {@link stopAll}. `play()` awaits a fetch before it can
37
+ * build the element, and a profile close inside that window would mount a
38
+ * video after teardown already cleared them — the sound-side twin is
39
+ * `SoundManager`'s epoch. */
40
+ private epoch;
41
+ /** Set by {@link destroy} — permanent, unlike an epoch bump. */
42
+ private destroyed;
36
43
  /** Fires once the element has actually begun playing — mirrors Mudlet's
37
44
  * sysMediaStarted. Deliberately after `el.play()` resolves rather than
38
45
  * beside the caption below it: autoplay policy can reject the play, and an