unified-video-framework 1.4.195 → 1.4.197
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.
|
@@ -238,6 +238,10 @@ export class WebPlayer extends BasePlayer {
|
|
|
238
238
|
this.video.playsInline = this.config.playsInline ?? true;
|
|
239
239
|
this.video.preload = this.config.preload ?? 'metadata';
|
|
240
240
|
|
|
241
|
+
// Enable AirPlay for iOS devices
|
|
242
|
+
(this.video as any).webkitAllowsAirPlay = true;
|
|
243
|
+
this.video.setAttribute('x-webkit-airplay', 'allow');
|
|
244
|
+
|
|
241
245
|
if (this.config.crossOrigin) {
|
|
242
246
|
this.video.crossOrigin = this.config.crossOrigin;
|
|
243
247
|
}
|
|
@@ -938,6 +942,8 @@ export class WebPlayer extends BasePlayer {
|
|
|
938
942
|
try {
|
|
939
943
|
await this.play();
|
|
940
944
|
this.debugLog('✅ Muted autoplay successful');
|
|
945
|
+
// Show YouTube-style unmute button instead of blocking overlay
|
|
946
|
+
this.showUnmuteButton();
|
|
941
947
|
return true;
|
|
942
948
|
} catch (error) {
|
|
943
949
|
this.debugLog('❌ Muted autoplay failed');
|
|
@@ -1133,6 +1139,129 @@ export class WebPlayer extends BasePlayer {
|
|
|
1133
1139
|
}
|
|
1134
1140
|
}
|
|
1135
1141
|
|
|
1142
|
+
/**
|
|
1143
|
+
* Show YouTube-style unmute button when video autoplays muted
|
|
1144
|
+
*/
|
|
1145
|
+
private showUnmuteButton(): void {
|
|
1146
|
+
// Remove existing unmute button
|
|
1147
|
+
this.hideUnmuteButton();
|
|
1148
|
+
|
|
1149
|
+
this.debugLog('🔇 Showing unmute button - video autoplaying muted');
|
|
1150
|
+
|
|
1151
|
+
const unmuteBtn = document.createElement('button');
|
|
1152
|
+
unmuteBtn.id = 'uvf-unmute-btn';
|
|
1153
|
+
unmuteBtn.className = 'uvf-unmute-btn';
|
|
1154
|
+
unmuteBtn.setAttribute('aria-label', 'Tap to unmute');
|
|
1155
|
+
unmuteBtn.innerHTML = `
|
|
1156
|
+
<svg viewBox="0 0 24 24" class="uvf-unmute-icon">
|
|
1157
|
+
<path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/>
|
|
1158
|
+
</svg>
|
|
1159
|
+
<span class="uvf-unmute-text">Tap to unmute</span>
|
|
1160
|
+
`;
|
|
1161
|
+
|
|
1162
|
+
// Click handler to unmute
|
|
1163
|
+
unmuteBtn.addEventListener('click', (e) => {
|
|
1164
|
+
e.stopPropagation();
|
|
1165
|
+
if (this.video) {
|
|
1166
|
+
this.video.muted = false;
|
|
1167
|
+
this.debugLog('🔊 Video unmuted by user');
|
|
1168
|
+
this.hideUnmuteButton();
|
|
1169
|
+
}
|
|
1170
|
+
});
|
|
1171
|
+
|
|
1172
|
+
// Add enhanced styles
|
|
1173
|
+
const style = document.createElement('style');
|
|
1174
|
+
style.textContent = `
|
|
1175
|
+
.uvf-unmute-btn {
|
|
1176
|
+
position: absolute !important;
|
|
1177
|
+
bottom: 80px !important;
|
|
1178
|
+
left: 20px !important;
|
|
1179
|
+
z-index: 1000 !important;
|
|
1180
|
+
display: flex !important;
|
|
1181
|
+
align-items: center !important;
|
|
1182
|
+
gap: 8px !important;
|
|
1183
|
+
padding: 12px 16px !important;
|
|
1184
|
+
background: rgba(0, 0, 0, 0.8) !important;
|
|
1185
|
+
border: none !important;
|
|
1186
|
+
border-radius: 4px !important;
|
|
1187
|
+
color: white !important;
|
|
1188
|
+
font-size: 14px !important;
|
|
1189
|
+
font-weight: 500 !important;
|
|
1190
|
+
cursor: pointer !important;
|
|
1191
|
+
transition: all 0.2s ease !important;
|
|
1192
|
+
backdrop-filter: blur(10px) !important;
|
|
1193
|
+
-webkit-backdrop-filter: blur(10px) !important;
|
|
1194
|
+
animation: uvf-unmute-pulse 2s ease-in-out infinite !important;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
.uvf-unmute-btn:hover {
|
|
1198
|
+
background: rgba(0, 0, 0, 0.9) !important;
|
|
1199
|
+
transform: scale(1.05) !important;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
.uvf-unmute-btn:active {
|
|
1203
|
+
transform: scale(0.95) !important;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
.uvf-unmute-icon {
|
|
1207
|
+
width: 20px !important;
|
|
1208
|
+
height: 20px !important;
|
|
1209
|
+
fill: white !important;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
.uvf-unmute-text {
|
|
1213
|
+
white-space: nowrap !important;
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
@keyframes uvf-unmute-pulse {
|
|
1217
|
+
0%, 100% {
|
|
1218
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;
|
|
1219
|
+
}
|
|
1220
|
+
50% {
|
|
1221
|
+
box-shadow: 0 2px 16px rgba(255, 255, 255, 0.2) !important;
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
/* Mobile responsive */
|
|
1226
|
+
@media (max-width: 767px) {
|
|
1227
|
+
.uvf-unmute-btn {
|
|
1228
|
+
bottom: 70px !important;
|
|
1229
|
+
left: 50% !important;
|
|
1230
|
+
transform: translateX(-50%) !important;
|
|
1231
|
+
padding: 10px 14px !important;
|
|
1232
|
+
font-size: 13px !important;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
.uvf-unmute-btn:hover {
|
|
1236
|
+
transform: translateX(-50%) scale(1.05) !important;
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
`;
|
|
1240
|
+
|
|
1241
|
+
// Add to page if not already added
|
|
1242
|
+
if (!document.getElementById('uvf-unmute-styles')) {
|
|
1243
|
+
style.id = 'uvf-unmute-styles';
|
|
1244
|
+
document.head.appendChild(style);
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// Add to player
|
|
1248
|
+
if (this.playerWrapper) {
|
|
1249
|
+
this.playerWrapper.appendChild(unmuteBtn);
|
|
1250
|
+
this.debugLog('✅ Unmute button added to player');
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
/**
|
|
1255
|
+
* Hide unmute button
|
|
1256
|
+
*/
|
|
1257
|
+
private hideUnmuteButton(): void {
|
|
1258
|
+
const unmuteBtn = document.getElementById('uvf-unmute-btn');
|
|
1259
|
+
if (unmuteBtn) {
|
|
1260
|
+
unmuteBtn.remove();
|
|
1261
|
+
this.debugLog('Unmute button removed');
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1136
1265
|
private updateTimeTooltip(e: MouseEvent): void {
|
|
1137
1266
|
const progressBar = document.getElementById('uvf-progress-bar');
|
|
1138
1267
|
const tooltip = document.getElementById('uvf-time-tooltip');
|
|
@@ -4112,18 +4241,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
4112
4241
|
height: 24px;
|
|
4113
4242
|
}
|
|
4114
4243
|
|
|
4115
|
-
.uvf-player-wrapper.uvf-fullscreen .uvf-top-btn {
|
|
4116
|
-
width: 40px;
|
|
4117
|
-
height: 40px;
|
|
4118
|
-
min-width: 40px;
|
|
4119
|
-
min-height: 40px;
|
|
4120
|
-
}
|
|
4121
|
-
|
|
4122
|
-
.uvf-player-wrapper.uvf-fullscreen .uvf-top-btn svg {
|
|
4123
|
-
width: 20px;
|
|
4124
|
-
height: 20px;
|
|
4125
|
-
}
|
|
4126
|
-
|
|
4127
4244
|
.uvf-player-wrapper.uvf-fullscreen .uvf-time-display {
|
|
4128
4245
|
font-size: 14px;
|
|
4129
4246
|
padding: 0 10px;
|
|
@@ -4223,12 +4340,29 @@ export class WebPlayer extends BasePlayer {
|
|
|
4223
4340
|
}
|
|
4224
4341
|
|
|
4225
4342
|
|
|
4226
|
-
/* Mobile portrait - hide skip buttons */
|
|
4343
|
+
/* Mobile portrait - hide skip buttons, ensure top bar visible */
|
|
4227
4344
|
@media screen and (max-width: 767px) and (orientation: portrait) {
|
|
4228
4345
|
#uvf-skip-back,
|
|
4229
4346
|
#uvf-skip-forward {
|
|
4230
4347
|
display: none !important;
|
|
4231
4348
|
}
|
|
4349
|
+
|
|
4350
|
+
/* Ensure top bar and controls are visible */
|
|
4351
|
+
.uvf-top-bar {
|
|
4352
|
+
display: flex !important;
|
|
4353
|
+
z-index: 10 !important;
|
|
4354
|
+
}
|
|
4355
|
+
|
|
4356
|
+
.uvf-top-controls {
|
|
4357
|
+
display: flex !important;
|
|
4358
|
+
}
|
|
4359
|
+
|
|
4360
|
+
/* Show top bar when controls are visible or on hover */
|
|
4361
|
+
.uvf-player-wrapper:hover .uvf-top-bar,
|
|
4362
|
+
.uvf-player-wrapper.controls-visible .uvf-top-bar {
|
|
4363
|
+
opacity: 1 !important;
|
|
4364
|
+
transform: translateY(0) !important;
|
|
4365
|
+
}
|
|
4232
4366
|
}
|
|
4233
4367
|
|
|
4234
4368
|
/* Mobile devices (landscape) - Optimized for fullscreen viewing with safe areas */
|
|
@@ -4326,18 +4460,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
4326
4460
|
gap: 6px !important;
|
|
4327
4461
|
}
|
|
4328
4462
|
|
|
4329
|
-
.uvf-top-btn {
|
|
4330
|
-
width: 40px;
|
|
4331
|
-
height: 40px;
|
|
4332
|
-
min-width: 40px;
|
|
4333
|
-
min-height: 40px;
|
|
4334
|
-
}
|
|
4335
|
-
|
|
4336
|
-
.uvf-top-btn svg {
|
|
4337
|
-
width: 18px;
|
|
4338
|
-
height: 18px;
|
|
4339
|
-
}
|
|
4340
|
-
|
|
4341
4463
|
/* Title bar within top bar - landscape */
|
|
4342
4464
|
.uvf-top-bar .uvf-title-bar {
|
|
4343
4465
|
padding: 0;
|
|
@@ -4423,19 +4545,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
4423
4545
|
height: 23px;
|
|
4424
4546
|
}
|
|
4425
4547
|
|
|
4426
|
-
/* Tablet top controls */
|
|
4427
|
-
.uvf-top-btn {
|
|
4428
|
-
width: 42px;
|
|
4429
|
-
height: 42px;
|
|
4430
|
-
min-width: 42px;
|
|
4431
|
-
min-height: 42px;
|
|
4432
|
-
}
|
|
4433
|
-
|
|
4434
|
-
.uvf-top-btn svg {
|
|
4435
|
-
width: 19px;
|
|
4436
|
-
height: 19px;
|
|
4437
|
-
}
|
|
4438
|
-
|
|
4439
4548
|
/* Top bar for tablet */
|
|
4440
4549
|
.uvf-top-bar {
|
|
4441
4550
|
padding: 16px;
|
|
@@ -4574,23 +4683,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
4574
4683
|
height: 24px;
|
|
4575
4684
|
}
|
|
4576
4685
|
|
|
4577
|
-
/* Enhanced top controls */
|
|
4578
|
-
.uvf-top-btn {
|
|
4579
|
-
width: 40px;
|
|
4580
|
-
height: 40px;
|
|
4581
|
-
transition: all 0.2s cubic-bezier(0.4, 0.0, 0.2, 1);
|
|
4582
|
-
}
|
|
4583
|
-
|
|
4584
|
-
.uvf-top-btn:hover {
|
|
4585
|
-
transform: scale(1.1);
|
|
4586
|
-
background: var(--uvf-overlay-medium);
|
|
4587
|
-
}
|
|
4588
|
-
|
|
4589
|
-
.uvf-top-btn svg {
|
|
4590
|
-
width: 20px;
|
|
4591
|
-
height: 20px;
|
|
4592
|
-
}
|
|
4593
|
-
|
|
4594
4686
|
/* Top bar for desktop 1024px+ */
|
|
4595
4687
|
.uvf-top-bar {
|
|
4596
4688
|
padding: 20px;
|
|
@@ -4710,16 +4802,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
4710
4802
|
height: 28px;
|
|
4711
4803
|
}
|
|
4712
4804
|
|
|
4713
|
-
.uvf-top-btn {
|
|
4714
|
-
width: 44px;
|
|
4715
|
-
height: 44px;
|
|
4716
|
-
}
|
|
4717
|
-
|
|
4718
|
-
.uvf-top-btn svg {
|
|
4719
|
-
width: 22px;
|
|
4720
|
-
height: 22px;
|
|
4721
|
-
}
|
|
4722
|
-
|
|
4723
4805
|
.uvf-center-play-btn {
|
|
4724
4806
|
width: clamp(64px, 10vw, 76px);
|
|
4725
4807
|
height: clamp(64px, 10vw, 76px);
|
|
@@ -4760,8 +4842,7 @@ export class WebPlayer extends BasePlayer {
|
|
|
4760
4842
|
/* High-DPI display optimizations */
|
|
4761
4843
|
@media screen and (-webkit-min-device-pixel-ratio: 2),
|
|
4762
4844
|
screen and (min-resolution: 192dpi) {
|
|
4763
|
-
.uvf-control-btn
|
|
4764
|
-
.uvf-top-btn {
|
|
4845
|
+
.uvf-control-btn {
|
|
4765
4846
|
image-rendering: -webkit-optimize-contrast;
|
|
4766
4847
|
image-rendering: crisp-edges;
|
|
4767
4848
|
}
|
|
@@ -4778,7 +4859,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
4778
4859
|
/* Reduced motion accessibility */
|
|
4779
4860
|
@media (prefers-reduced-motion: reduce) {
|
|
4780
4861
|
.uvf-control-btn,
|
|
4781
|
-
.uvf-top-btn,
|
|
4782
4862
|
.uvf-center-play-btn,
|
|
4783
4863
|
.uvf-progress-handle,
|
|
4784
4864
|
.uvf-volume-slider,
|
|
@@ -4787,7 +4867,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
4787
4867
|
}
|
|
4788
4868
|
|
|
4789
4869
|
.uvf-control-btn:hover,
|
|
4790
|
-
.uvf-top-btn:hover,
|
|
4791
4870
|
.uvf-center-play-btn:hover {
|
|
4792
4871
|
transform: none !important;
|
|
4793
4872
|
}
|
|
@@ -4813,11 +4892,6 @@ export class WebPlayer extends BasePlayer {
|
|
|
4813
4892
|
border-radius: 50%
|
|
4814
4893
|
}
|
|
4815
4894
|
|
|
4816
|
-
.uvf-top-btn {
|
|
4817
|
-
min-width: 44px;
|
|
4818
|
-
min-height: 44px;
|
|
4819
|
-
}
|
|
4820
|
-
|
|
4821
4895
|
.uvf-progress-bar {
|
|
4822
4896
|
height: 3px;
|
|
4823
4897
|
}
|
|
@@ -4836,22 +4910,21 @@ export class WebPlayer extends BasePlayer {
|
|
|
4836
4910
|
background: var(--uvf-overlay-medium);
|
|
4837
4911
|
transform: scale(0.95);
|
|
4838
4912
|
}
|
|
4839
|
-
|
|
4840
|
-
.uvf-top-btn:active {
|
|
4841
|
-
background: var(--uvf-overlay-medium);
|
|
4842
|
-
transform: scale(0.95);
|
|
4843
|
-
}
|
|
4844
4913
|
}
|
|
4845
4914
|
|
|
4846
4915
|
/* Keyboard navigation and accessibility */
|
|
4847
4916
|
.uvf-control-btn:focus-visible,
|
|
4848
|
-
.uvf-top-btn:focus-visible,
|
|
4849
4917
|
.uvf-center-play-btn:focus-visible {
|
|
4850
4918
|
outline: 2px solid var(--uvf-primary-color, #007bff);
|
|
4851
4919
|
outline-offset: 2px;
|
|
4852
4920
|
background: var(--uvf-overlay-medium);
|
|
4853
4921
|
}
|
|
4854
4922
|
|
|
4923
|
+
.uvf-top-btn:focus-visible {
|
|
4924
|
+
outline: 2px solid var(--uvf-primary-color, #007bff);
|
|
4925
|
+
outline-offset: 2px;
|
|
4926
|
+
}
|
|
4927
|
+
|
|
4855
4928
|
.uvf-progress-bar-wrapper:focus-visible {
|
|
4856
4929
|
outline: 2px solid var(--uvf-primary-color, #007bff);
|
|
4857
4930
|
outline-offset: 2px;
|
|
@@ -4883,7 +4956,10 @@ export class WebPlayer extends BasePlayer {
|
|
|
4883
4956
|
|
|
4884
4957
|
/* High contrast mode support */
|
|
4885
4958
|
@media (prefers-contrast: high) {
|
|
4886
|
-
.uvf-control-btn
|
|
4959
|
+
.uvf-control-btn {
|
|
4960
|
+
border: 1px solid;
|
|
4961
|
+
}
|
|
4962
|
+
|
|
4887
4963
|
.uvf-top-btn {
|
|
4888
4964
|
border: 1px solid;
|
|
4889
4965
|
}
|
|
@@ -5670,6 +5746,8 @@ export class WebPlayer extends BasePlayer {
|
|
|
5670
5746
|
} else {
|
|
5671
5747
|
volumeIcon.style.display = 'block';
|
|
5672
5748
|
muteIcon.style.display = 'none';
|
|
5749
|
+
// Hide unmute button when video is unmuted
|
|
5750
|
+
this.hideUnmuteButton();
|
|
5673
5751
|
}
|
|
5674
5752
|
}
|
|
5675
5753
|
});
|
|
@@ -5846,6 +5924,17 @@ export class WebPlayer extends BasePlayer {
|
|
|
5846
5924
|
const stopCastBtn = document.getElementById('uvf-stop-cast-btn');
|
|
5847
5925
|
const shareBtn = document.getElementById('uvf-share-btn');
|
|
5848
5926
|
|
|
5927
|
+
// Update cast button icon and functionality for iOS (AirPlay)
|
|
5928
|
+
if (this.isIOSDevice() && castBtn) {
|
|
5929
|
+
castBtn.innerHTML = `
|
|
5930
|
+
<svg viewBox="0 0 24 24">
|
|
5931
|
+
<path d="M1 18h6v-2H1v2zm0-4h12v-2H1v2zm16.5 4.5c-1.25 0-2.45-.5-3.35-1.41L12 18.5l2.09 2.09c1.8 1.8 4.72 1.8 6.52 0 1.8-1.8 1.8-4.72 0-6.52L12 5.5 3.39 14.11c-1.8 1.8-1.8 4.72 0 6.52.9.9 2.1 1.41 3.35 1.41l6.76-6.76M12 7.91l6.89 6.89c.78.78.78 2.05 0 2.83-.78.78-2.05.78-2.83 0L12 13.57 7.94 17.63c-.78.78-2.05.78-2.83 0-.78-.78-.78-2.05 0-2.83L12 7.91z"/>
|
|
5932
|
+
</svg>
|
|
5933
|
+
`;
|
|
5934
|
+
castBtn.setAttribute('title', 'AirPlay');
|
|
5935
|
+
castBtn.setAttribute('aria-label', 'AirPlay');
|
|
5936
|
+
}
|
|
5937
|
+
|
|
5849
5938
|
castBtn?.addEventListener('click', () => this.onCastButtonClick());
|
|
5850
5939
|
stopCastBtn?.addEventListener('click', () => this.stopCasting());
|
|
5851
5940
|
shareBtn?.addEventListener('click', () => this.shareVideo());
|
|
@@ -8189,6 +8278,13 @@ export class WebPlayer extends BasePlayer {
|
|
|
8189
8278
|
}
|
|
8190
8279
|
|
|
8191
8280
|
private onCastButtonClick(): void {
|
|
8281
|
+
// On iOS, use AirPlay instead of Google Cast
|
|
8282
|
+
if (this.isIOSDevice()) {
|
|
8283
|
+
this.showAirPlayPicker();
|
|
8284
|
+
return;
|
|
8285
|
+
}
|
|
8286
|
+
|
|
8287
|
+
// Google Cast for non-iOS devices
|
|
8192
8288
|
try {
|
|
8193
8289
|
const castNs = (window as any).cast;
|
|
8194
8290
|
if (this.isCasting && castNs && castNs.framework) {
|
|
@@ -8200,6 +8296,31 @@ export class WebPlayer extends BasePlayer {
|
|
|
8200
8296
|
// Not casting yet
|
|
8201
8297
|
this.initCast();
|
|
8202
8298
|
}
|
|
8299
|
+
|
|
8300
|
+
/**
|
|
8301
|
+
* Show AirPlay picker for iOS devices
|
|
8302
|
+
*/
|
|
8303
|
+
private showAirPlayPicker(): void {
|
|
8304
|
+
if (!this.video) {
|
|
8305
|
+
this.showNotification('Video not ready');
|
|
8306
|
+
return;
|
|
8307
|
+
}
|
|
8308
|
+
|
|
8309
|
+
// Check if AirPlay is supported
|
|
8310
|
+
const videoElement = this.video as any;
|
|
8311
|
+
if (typeof videoElement.webkitShowPlaybackTargetPicker === 'function') {
|
|
8312
|
+
try {
|
|
8313
|
+
videoElement.webkitShowPlaybackTargetPicker();
|
|
8314
|
+
this.debugLog('AirPlay picker shown');
|
|
8315
|
+
} catch (error) {
|
|
8316
|
+
this.debugWarn('Failed to show AirPlay picker:', (error as Error).message);
|
|
8317
|
+
this.showNotification('AirPlay not available');
|
|
8318
|
+
}
|
|
8319
|
+
} else {
|
|
8320
|
+
this.debugWarn('AirPlay not supported on this device');
|
|
8321
|
+
this.showNotification('AirPlay not supported');
|
|
8322
|
+
}
|
|
8323
|
+
}
|
|
8203
8324
|
|
|
8204
8325
|
private stopCasting(): void {
|
|
8205
8326
|
try {
|