aurasu 0.1.7 → 0.1.8

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.
Binary file
Binary file
Binary file
Binary file
@@ -150,6 +150,36 @@
150
150
  "sha256": "7f0f8344db9fda1d6b3d0c6a45e36ae51d5198b7613deee326a85e67cd2f413b",
151
151
  "size": 2142
152
152
  },
153
+ {
154
+ "path": "assets/splash/aurajs-gg-wordmark.webp",
155
+ "sha256": "80a4ebd7d23f624aa1ead31c4702b3c21ce8c99075e80e4f3a371870585c73af",
156
+ "size": 21970
157
+ },
158
+ {
159
+ "path": "assets/splash/bg.webp",
160
+ "sha256": "3a8892862610ce453314dae576f6707470a7761eb2be5987b55501d9ccd41f54",
161
+ "size": 46216
162
+ },
163
+ {
164
+ "path": "assets/splash/boot-loop.wav",
165
+ "sha256": "569b8c457d478b003011d62f165ffd73ad11a598d28337b2c98ee8bb4357c0f7",
166
+ "size": 70604
167
+ },
168
+ {
169
+ "path": "assets/splash/boot-sting.wav",
170
+ "sha256": "386abbb357537ec0a284c9ff64de26821782de10002b2b5c9675b26bb755c44d",
171
+ "size": 48554
172
+ },
173
+ {
174
+ "path": "assets/splash/logo-mascot-sheet.webp",
175
+ "sha256": "aaa75bea690285b2c6df08182c248cdae6ca374057978cdba25d57d8fb70c225",
176
+ "size": 22036
177
+ },
178
+ {
179
+ "path": "assets/splash/logoholo.webp",
180
+ "sha256": "65bec52e3ecb6417aa74832a3153c837b9aaee6b3dd5d7e8536235b7d11442cd",
181
+ "size": 12782
182
+ },
153
183
  {
154
184
  "path": "assets/ui-back.wav",
155
185
  "sha256": "a4e071c73866aa94a7e34a636c18aff4a9c83a4bd3d5333f63f07704e982b793",
@@ -177,8 +207,8 @@
177
207
  },
178
208
  {
179
209
  "path": "bin/play.js",
180
- "sha256": "9b444ba23f1ea908c16a2266b223f987386966a0248bad0e56f4d2d1beafee46",
181
- "size": 40778
210
+ "sha256": "c29cc4a29d0470e46ce5555cbc4001f96d7458ab7a5975ad55b3248fb5859520",
211
+ "size": 42416
182
212
  },
183
213
  {
184
214
  "path": "config/gameplay/game.config.js",
@@ -192,7 +222,7 @@
192
222
  },
193
223
  {
194
224
  "path": "package.json",
195
- "sha256": "d211b5fd827554a8baa78e1ca4ec03a9e343e4747e5772d0f329b18db0cd94bc",
225
+ "sha256": "4c081cac3332359fef0c3c4e224ccf1d3f48441c38e70dd54394225110dca757",
196
226
  "size": 568
197
227
  },
198
228
  {
@@ -212,8 +242,8 @@
212
242
  },
213
243
  {
214
244
  "path": "src/main.js",
215
- "sha256": "441adcb9f5cd61413b82146b7c9b9b44782f7543a273cb8f6b66b5151a1ff8b7",
216
- "size": 365
245
+ "sha256": "0b2f36b0a56d38529289077b7a43795edc4c064d9747c47f3c200426bbfb67d9",
246
+ "size": 577
217
247
  },
218
248
  {
219
249
  "path": "src/runtime/app-state.js",
@@ -255,6 +285,11 @@
255
285
  "sha256": "56321b896b4368973feb6f5581a9e27d2553b1be91d66206e88cf9ffb25723f8",
256
286
  "size": 6384
257
287
  },
288
+ {
289
+ "path": "src/runtime/splash.js",
290
+ "sha256": "00cd80250f0abffd14b27241d65dc0b3402c3814a5bb4395d0cd538b20ae59fc",
291
+ "size": 9799
292
+ },
258
293
  {
259
294
  "path": "src/runtime/ui-settings.js",
260
295
  "sha256": "c09e6ae51fa3dc507da5c8b1975598629081bad0af98faa32471ca5fb1b32c6e",
@@ -272,14 +307,14 @@
272
307
  }
273
308
  ],
274
309
  "package": {
275
- "aurajsVersion": "0.1.1",
310
+ "aurajsVersion": "0.1.3",
276
311
  "bin": {
277
312
  "aurasu": "bin/play.js"
278
313
  },
279
314
  "description": "A hit-circle rhythm game built with AuraJS.",
280
315
  "name": "aurasu",
281
316
  "type": "module",
282
- "version": "0.1.7"
317
+ "version": "0.1.8"
283
318
  },
284
319
  "publishedMetadata": {
285
320
  "authored": {
@@ -1 +1 @@
1
- O5bkJ0iWLdUelqYfyb8NY2J6Jug9Gl4w1LYuEJlnKiNLcQ6si5Gi8Q4tYvO9QesttU7qw8Boa+HYFCp6zWZDAg==
1
+ dVntP3f6ovlY/3IR88FwdOm1RuqOGaSJlY4d4r0gcWHGG5C2uyapbrNxm2ufha+zqpUXCCma3tTrnEl0Y7oQBg==
package/bin/play.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { spawn } from 'node:child_process';
3
+ import { spawn, spawnSync } from 'node:child_process';
4
4
  import { cpSync, createWriteStream, existsSync, mkdirSync, readFileSync } from 'node:fs';
5
5
  import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
6
6
  import { fileURLToPath, pathToFileURL } from 'node:url';
@@ -58,6 +58,39 @@ const ALL_COMMANDS = ['dev', 'join', 'play', 'fork', 'publish', 'session', 'stat
58
58
  const ROOM_CODE_PATTERN = /^[A-Z0-9]{4,8}$/;
59
59
  const FORK_EXCLUDED_TOP_LEVEL = new Set(['.aura', '.git', '.logs', 'build', 'dist', 'node_modules']);
60
60
 
61
+ function resolveAuraMaxxBinary() {
62
+ return process.platform === 'win32' ? 'auramaxx.cmd' : 'auramaxx';
63
+ }
64
+
65
+ function resolveNpmBinary() {
66
+ return process.platform === 'win32' ? 'npm.cmd' : 'npm';
67
+ }
68
+
69
+ function isAuraMaxxInstalled() {
70
+ const probe = spawnSync(resolveAuraMaxxBinary(), ['--version'], {
71
+ stdio: 'ignore',
72
+ env: process.env,
73
+ });
74
+ return !probe.error && probe.status === 0;
75
+ }
76
+
77
+ async function installAuraMaxxGlobally() {
78
+ return new Promise((resolveInstall) => {
79
+ const child = spawn(
80
+ resolveNpmBinary(),
81
+ ['install', '-g', 'auramaxx', '--foreground-scripts'],
82
+ {
83
+ cwd: process.cwd(),
84
+ stdio: 'inherit',
85
+ env: process.env,
86
+ },
87
+ );
88
+
89
+ child.on('error', () => resolveInstall(false));
90
+ child.on('close', (code) => resolveInstall((code ?? 1) === 0));
91
+ });
92
+ }
93
+
61
94
  function resolveLocalAuraCli(startRoot) {
62
95
  let current = resolve(startRoot);
63
96
  while (true) {
@@ -1063,6 +1096,38 @@ async function chooseDefaultCommand() {
1063
1096
  return choice;
1064
1097
  }
1065
1098
 
1099
+ async function maybeOfferAuraMaxxInstall() {
1100
+ if (isAuraMaxxInstalled()) {
1101
+ return;
1102
+ }
1103
+
1104
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
1105
+ return;
1106
+ }
1107
+
1108
+ printSection('AuraMaxx', 'AuraMaxx is not installed globally.');
1109
+ const choice = await promptSelect(
1110
+ ' Install AuraMaxx now?',
1111
+ [
1112
+ { value: 'yes', label: 'Yes, install AuraMaxx' },
1113
+ { value: 'no', label: 'No, continue playing' },
1114
+ ],
1115
+ 'yes',
1116
+ );
1117
+
1118
+ if (choice !== 'yes') {
1119
+ return;
1120
+ }
1121
+
1122
+ printSection('AuraMaxx', 'Installing global CLI...');
1123
+ const installed = await installAuraMaxxGlobally();
1124
+ if (installed) {
1125
+ printSection('AuraMaxx', 'Installed. Continuing play...');
1126
+ return;
1127
+ }
1128
+ printSection('AuraMaxx', 'Install failed. Continuing play...');
1129
+ }
1130
+
1066
1131
  async function main() {
1067
1132
  const parsed = parseArgs(process.argv.slice(2));
1068
1133
 
@@ -1092,6 +1157,7 @@ async function main() {
1092
1157
  if (command === 'play') {
1093
1158
  printBanner('PLAY');
1094
1159
  printSection(toDisplayTitle(packageName), 'Starting packaged local game session...');
1160
+ await maybeOfferAuraMaxxInstall();
1095
1161
  const externalAssets = await maybePrepareExternalAssets('play');
1096
1162
  const multiplayerEnv = await resolveLocalMultiplayerCommandEnv();
1097
1163
  await runCommand(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aurasu",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "A hit-circle rhythm game built with AuraJS.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,7 +21,7 @@
21
21
  "aura.package-integrity.sig"
22
22
  ],
23
23
  "dependencies": {
24
- "@auraindustry/aurajs": "0.1.1"
24
+ "@auraindustry/aurajs": "0.1.3"
25
25
  },
26
26
  "keywords": [
27
27
  "aurajs",
package/src/main.js CHANGED
@@ -1,16 +1,20 @@
1
1
  import { createApp } from './runtime/app.js';
2
+ import { initSplash, updateSplash, drawSplash, isSplashActive } from './runtime/splash.js';
2
3
 
3
4
  const app = createApp();
4
5
 
5
6
  aura.setup = function setup() {
7
+ initSplash();
6
8
  return app.setup();
7
9
  };
8
10
 
9
11
  aura.update = function update(dt) {
12
+ if (isSplashActive()) { updateSplash(dt); return; }
10
13
  app.update(dt);
11
14
  };
12
15
 
13
16
  aura.draw = function draw() {
17
+ if (isSplashActive()) { drawSplash(); return; }
14
18
  app.draw();
15
19
  };
16
20
 
@@ -0,0 +1,305 @@
1
+ // AuraJS Splash — unified retro paper-card boot screen.
2
+ // Auto-wired by createApp(). Shows once on launch, then hands off to the game.
3
+
4
+ const FADE_IN = 0.7;
5
+ const HOLD = 1.8;
6
+ const FADE_OUT = 0.7;
7
+ const TOTAL = FADE_IN + HOLD + FADE_OUT;
8
+
9
+ const PAPER = [0.89, 0.89, 0.89];
10
+ const PAPER_SHADOW = [0.80, 0.80, 0.80];
11
+ const PAPER_EDGE = [0.41, 0.41, 0.41];
12
+ const INK = [0.1, 0.1, 0.1];
13
+ const INK_MUTED = [0.42, 0.42, 0.42];
14
+ const MASCOT_FRAME_W = 64;
15
+ const MASCOT_FRAME_H = 84;
16
+ const MASCOT_SEQUENCE = Object.freeze([0, 1, 2, 1]);
17
+ const SPLASH_STING_PATH = 'splash/boot-sting.wav';
18
+ const SPLASH_LOOP_PATH = 'splash/boot-loop.wav';
19
+ const SPLASH_BUS = 'splash';
20
+ const QUIET_BUSES = Object.freeze(['default', 'music', 'sfx']);
21
+
22
+ let state = null;
23
+
24
+ function has(obj, method) {
25
+ return Boolean(obj) && typeof obj[method] === 'function';
26
+ }
27
+
28
+ function color(rgb, alpha = 1) {
29
+ return aura.rgba(rgb[0], rgb[1], rgb[2], alpha);
30
+ }
31
+
32
+ function drawShadowText(text, x, y, options = {}) {
33
+ const {
34
+ shadowOffset = 2,
35
+ shadowColor = color(INK_MUTED, 0.3),
36
+ ...rest
37
+ } = options;
38
+ aura.draw2d.text(text, x + shadowOffset, y + shadowOffset, {
39
+ ...rest,
40
+ color: shadowColor,
41
+ });
42
+ aura.draw2d.text(text, x, y, rest);
43
+ }
44
+
45
+ export function initSplash() {
46
+ state = {
47
+ t: 0,
48
+ logo: null,
49
+ mascot: null,
50
+ wordmark: null,
51
+ font: null,
52
+ stingHandle: null,
53
+ loopHandle: null,
54
+ busVolumes: null,
55
+ pausedHandles: [],
56
+ };
57
+ try { if (has(aura.assets, 'load')) state.logo = aura.assets.load('splash/logoholo.webp'); } catch (_) {}
58
+ try { if (has(aura.assets, 'load')) state.mascot = aura.assets.load('splash/logo-mascot-sheet.webp'); } catch (_) {}
59
+ try { if (has(aura.assets, 'load')) state.wordmark = aura.assets.load('splash/aurajs-gg-wordmark.webp'); } catch (_) {}
60
+ try {
61
+ if (has(aura.assets, 'loadBitmapFont')) {
62
+ const result = aura.assets.loadBitmapFont();
63
+ if (result && result.ok && result.font) state.font = result.font;
64
+ }
65
+ } catch (_) {}
66
+ captureBusVolumes();
67
+ applySplashBusIsolation();
68
+ try {
69
+ if (aura.audio && aura.audio.supported !== false && typeof aura.audio.play === 'function') {
70
+ state.loopHandle = aura.audio.play(SPLASH_LOOP_PATH, {
71
+ loop: true,
72
+ volume: 0.22,
73
+ bus: SPLASH_BUS,
74
+ });
75
+ state.stingHandle = aura.audio.play(SPLASH_STING_PATH, {
76
+ loop: false,
77
+ volume: 0.54,
78
+ bus: SPLASH_BUS,
79
+ });
80
+ }
81
+ } catch (_) {}
82
+ }
83
+
84
+ export function isSplashActive() {
85
+ return state !== null;
86
+ }
87
+
88
+ export function updateSplash(dt) {
89
+ if (!state) return;
90
+ syncPausedTracks();
91
+ try {
92
+ if (aura.audio && typeof aura.audio.update === 'function') {
93
+ aura.audio.update(Number(dt) > 0 ? Number(dt) : (1 / 60));
94
+ }
95
+ } catch (_) {}
96
+ state.t += dt;
97
+ if (state.t >= TOTAL) {
98
+ stopSplashAudio();
99
+ state = null;
100
+ }
101
+ }
102
+
103
+ export function drawSplash() {
104
+ if (!state) return;
105
+ const { width: w, height: h } = has(aura.window, 'getSize')
106
+ ? aura.window.getSize()
107
+ : { width: 640, height: 480 };
108
+ const t = state.t;
109
+ const cx = w / 2;
110
+ const cy = h / 2;
111
+
112
+ let a = 1;
113
+ if (t < FADE_IN) a = easeOut(t / FADE_IN);
114
+ else if (t > FADE_IN + HOLD) a = 1 - easeIn((t - FADE_IN - HOLD) / FADE_OUT);
115
+
116
+ aura.draw2d.clear(color(PAPER));
117
+
118
+ const panelW = Math.min(Math.floor(w * 0.48), 580);
119
+ const panelH = Math.min(Math.floor(h * 0.72), 620);
120
+ const panelX = Math.floor(cx - (panelW * 0.5));
121
+ const panelY = Math.floor(cy - (panelH * 0.5));
122
+
123
+ aura.draw2d.rectFill(panelX + 6, panelY + 6, panelW, panelH, color(INK, 0.08 * a));
124
+ aura.draw2d.rectFill(panelX, panelY, panelW, panelH, color(PAPER_EDGE, a));
125
+ aura.draw2d.rectFill(panelX + 6, panelY + 6, panelW - 12, panelH - 12, color(PAPER, a));
126
+ aura.draw2d.rectFill(panelX + 12, panelY + 12, panelW - 24, panelH - 24, color(PAPER, a * 0.96));
127
+
128
+ const floatY = Math.sin(t * 1.4 * Math.PI * 2) * 2;
129
+ const breathe = 0.985 + 0.015 * (0.5 + 0.5 * Math.sin(t * Math.PI * 2));
130
+ const mascotScale = Math.max(1, Math.min(Math.floor(Math.min(w, h) / 260), 2));
131
+ const mascotW = Math.floor(MASCOT_FRAME_W * mascotScale * breathe);
132
+ const mascotH = Math.floor(MASCOT_FRAME_H * mascotScale * breathe);
133
+ const mascotX = Math.floor(cx - (mascotW * 0.5));
134
+ const mascotY = Math.floor(panelY + panelH * 0.40 + floatY);
135
+ const mascotFrame = MASCOT_SEQUENCE[Math.floor(t * 7.5) % MASCOT_SEQUENCE.length] || 0;
136
+
137
+ aura.draw2d.rectFill(
138
+ mascotX + Math.floor(mascotW * 0.18),
139
+ mascotY + mascotH - 8,
140
+ Math.floor(mascotW * 0.64),
141
+ 6,
142
+ color(INK, a * 0.08),
143
+ );
144
+
145
+ if (state.mascot) {
146
+ aura.draw2d.sprite(state.mascot, mascotX, mascotY, {
147
+ width: mascotW,
148
+ height: mascotH,
149
+ frameX: mascotFrame * MASCOT_FRAME_W,
150
+ frameY: 0,
151
+ frameW: MASCOT_FRAME_W,
152
+ frameH: MASCOT_FRAME_H,
153
+ alpha: a,
154
+ });
155
+ } else if (state.logo) {
156
+ const sz = Math.min(Math.floor(panelW * 0.24), Math.floor(h * 0.14)) * breathe;
157
+ aura.draw2d.sprite(state.logo, Math.floor(cx - sz / 2), Math.floor(mascotY + 6), {
158
+ width: sz,
159
+ height: sz,
160
+ alpha: a,
161
+ });
162
+ }
163
+
164
+ const ta = clamp(a * easeOut(clamp((t - 0.2) / (FADE_IN * 0.6))));
165
+ const sa = clamp(a * easeOut(clamp((t - 0.4) / (FADE_IN * 0.6))));
166
+ const scale = Math.min(w, h) / 480;
167
+ const tsz = Math.max(24, Math.round(scale * 28));
168
+ const ssz = Math.max(11, Math.round(scale * 12));
169
+ const wordmarkW = Math.min(Math.floor(panelW * 0.52), 290);
170
+ const wordmarkH = Math.floor(wordmarkW * (768 / 1408));
171
+ const wordmarkX = Math.floor(cx - (wordmarkW * 0.5));
172
+ const wordmarkY = Math.floor(panelY + 36);
173
+ const sY = Math.floor(panelY + panelH - 108);
174
+ const fo = state.font ? { font: state.font } : {};
175
+
176
+ if (state.wordmark) {
177
+ aura.draw2d.sprite(state.wordmark, wordmarkX, wordmarkY, {
178
+ width: wordmarkW,
179
+ height: wordmarkH,
180
+ alpha: ta,
181
+ tint: color(INK, ta),
182
+ });
183
+ } else {
184
+ drawShadowText('AuraJS.gg', cx, wordmarkY + Math.floor(wordmarkH * 0.55), {
185
+ ...fo,
186
+ size: tsz,
187
+ color: color(INK, ta),
188
+ shadowColor: color(INK_MUTED, ta * 0.28),
189
+ align: 'center',
190
+ });
191
+ }
192
+
193
+ drawShadowText('Open-Source. MIT.', cx, sY, {
194
+ ...fo,
195
+ size: ssz,
196
+ color: color(INK_MUTED, sa),
197
+ shadowColor: color(PAPER_EDGE, sa * 0.18),
198
+ shadowOffset: 1,
199
+ align: 'center',
200
+ });
201
+ drawShadowText('Who needs publishers?', cx, sY + Math.max(16, Math.round(ssz * 1.45)), {
202
+ ...fo,
203
+ size: ssz,
204
+ color: color(INK_MUTED, sa),
205
+ shadowColor: color(PAPER_EDGE, sa * 0.18),
206
+ shadowOffset: 1,
207
+ align: 'center',
208
+ });
209
+
210
+ const rw = Math.min(panelW - 140, 240);
211
+ aura.draw2d.rectFill(Math.floor(cx - rw / 2), Math.floor(sY + Math.max(34, ssz * 3.2)), rw, 2, color(PAPER_EDGE, sa * 0.38));
212
+ }
213
+
214
+ function easeOut(t) {
215
+ const u = 1 - clamp(t);
216
+ return 1 - (u * u * u);
217
+ }
218
+
219
+ function easeIn(t) {
220
+ const c = clamp(t);
221
+ return c * c * c;
222
+ }
223
+
224
+ function clamp(v) {
225
+ return v < 0 ? 0 : v > 1 ? 1 : v;
226
+ }
227
+
228
+ function stopSplashAudio() {
229
+ if (!state || !aura.audio || typeof aura.audio.stop !== 'function') return;
230
+ try {
231
+ if (state.stingHandle != null) aura.audio.stop(state.stingHandle);
232
+ } catch (_) {}
233
+ try {
234
+ if (state.loopHandle != null) aura.audio.stop(state.loopHandle);
235
+ } catch (_) {}
236
+ restoreAudioState();
237
+ state.stingHandle = null;
238
+ state.loopHandle = null;
239
+ }
240
+
241
+ function captureBusVolumes() {
242
+ if (!state || !aura.audio || typeof aura.audio.getMixerState !== 'function') return;
243
+ try {
244
+ const mixer = aura.audio.getMixerState();
245
+ const buses = Array.isArray(mixer?.buses) ? mixer.buses : [];
246
+ state.busVolumes = buses.reduce((acc, entry) => {
247
+ const bus = String(entry?.bus || '').trim();
248
+ if (!bus) return acc;
249
+ acc[bus] = Number(entry?.volume);
250
+ return acc;
251
+ }, {});
252
+ } catch (_) {}
253
+ }
254
+
255
+ function applySplashBusIsolation() {
256
+ if (!state || !aura.audio || typeof aura.audio.setBusVolume !== 'function') return;
257
+ try { aura.audio.setBusVolume(SPLASH_BUS, 1); } catch (_) {}
258
+ for (const bus of QUIET_BUSES) {
259
+ try { aura.audio.setBusVolume(bus, 0); } catch (_) {}
260
+ }
261
+ }
262
+
263
+ function syncPausedTracks() {
264
+ if (!state || !aura.audio || typeof aura.audio.getMixerState !== 'function' || typeof aura.audio.pause !== 'function') return;
265
+ try {
266
+ const mixer = aura.audio.getMixerState();
267
+ const tracks = Array.isArray(mixer?.tracks) ? mixer.tracks : [];
268
+ const splashHandles = [state.stingHandle, state.loopHandle].filter((handle) => handle != null);
269
+ const pausedHandles = new Set(Array.isArray(state.pausedHandles) ? state.pausedHandles : []);
270
+ for (const track of tracks) {
271
+ const handle = Number(track?.handle);
272
+ if (!Number.isInteger(handle) || handle <= 0) continue;
273
+ if (splashHandles.includes(handle)) continue;
274
+ if (track?.paused === true || pausedHandles.has(handle)) continue;
275
+ try {
276
+ aura.audio.pause(handle);
277
+ pausedHandles.add(handle);
278
+ } catch (_) {}
279
+ }
280
+ state.pausedHandles = Array.from(pausedHandles);
281
+ } catch (_) {}
282
+ }
283
+
284
+ function restoreAudioState() {
285
+ if (!state || !aura.audio) return;
286
+ if (typeof aura.audio.setBusVolume === 'function') {
287
+ const snapshot = state.busVolumes && typeof state.busVolumes === 'object' ? state.busVolumes : null;
288
+ if (snapshot) {
289
+ for (const [bus, volume] of Object.entries(snapshot)) {
290
+ try { aura.audio.setBusVolume(bus, Number(volume)); } catch (_) {}
291
+ }
292
+ } else {
293
+ for (const bus of QUIET_BUSES) {
294
+ try { aura.audio.setBusVolume(bus, 1); } catch (_) {}
295
+ }
296
+ }
297
+ try { aura.audio.setBusVolume(SPLASH_BUS, 1); } catch (_) {}
298
+ }
299
+ if (typeof aura.audio.resume === 'function') {
300
+ for (const handle of Array.isArray(state.pausedHandles) ? state.pausedHandles : []) {
301
+ try { aura.audio.resume(handle); } catch (_) {}
302
+ }
303
+ }
304
+ state.pausedHandles = [];
305
+ }