scandoc-ai-components 0.1.17 → 0.1.18
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.
- package/dist/index.js +176 -36
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11170,6 +11170,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
11170
11170
|
|
|
11171
11171
|
const DOCUMENT_DETECTOR = new _ai_detect_document__WEBPACK_IMPORTED_MODULE_0__["default"]();
|
|
11172
11172
|
class ExtractorVideo {
|
|
11173
|
+
static DEBUG = true;
|
|
11173
11174
|
static FREQUENCY_MS = 10;
|
|
11174
11175
|
static VALIDATION_BATCH_SIZE = 1;
|
|
11175
11176
|
static VALIDATION_IMG_WIDTH = 384;
|
|
@@ -11197,8 +11198,48 @@ class ExtractorVideo {
|
|
|
11197
11198
|
this.waitingForSecondSide = false;
|
|
11198
11199
|
this.hasShownTurnMessage = false;
|
|
11199
11200
|
this.turnMessageTimer = null;
|
|
11201
|
+
this.debugLog = [];
|
|
11200
11202
|
this.onExtractedResults = onExtractedResults;
|
|
11201
11203
|
}
|
|
11204
|
+
logDebug(event, data = {}) {
|
|
11205
|
+
if (!ExtractorVideo.DEBUG) return;
|
|
11206
|
+
const entry = {
|
|
11207
|
+
ts: new Date().toISOString(),
|
|
11208
|
+
event,
|
|
11209
|
+
data
|
|
11210
|
+
};
|
|
11211
|
+
this.debugLog.push(entry);
|
|
11212
|
+
try {
|
|
11213
|
+
console.log("[ScanDocAI]", event, data);
|
|
11214
|
+
} catch (_) {}
|
|
11215
|
+
}
|
|
11216
|
+
getDebugDump() {
|
|
11217
|
+
return {
|
|
11218
|
+
userAgent: navigator.userAgent,
|
|
11219
|
+
secureContext: window.isSecureContext,
|
|
11220
|
+
location: window.location.href,
|
|
11221
|
+
videoPresent: !!this.video,
|
|
11222
|
+
videoReadyState: this.video?.readyState,
|
|
11223
|
+
videoNetworkState: this.video?.networkState,
|
|
11224
|
+
videoPaused: this.video?.paused,
|
|
11225
|
+
videoMuted: this.video?.muted,
|
|
11226
|
+
videoAutoplay: this.video?.autoplay,
|
|
11227
|
+
videoPlaysInline: this.video?.playsInline,
|
|
11228
|
+
videoDimensions: {
|
|
11229
|
+
videoWidth: this.video?.videoWidth || 0,
|
|
11230
|
+
videoHeight: this.video?.videoHeight || 0,
|
|
11231
|
+
clientWidth: this.video?.clientWidth || 0,
|
|
11232
|
+
clientHeight: this.video?.clientHeight || 0
|
|
11233
|
+
},
|
|
11234
|
+
streamTracks: this.video?.srcObject ? this.video.srcObject.getTracks().map(t => ({
|
|
11235
|
+
kind: t.kind,
|
|
11236
|
+
label: t.label,
|
|
11237
|
+
readyState: t.readyState,
|
|
11238
|
+
enabled: t.enabled
|
|
11239
|
+
})) : [],
|
|
11240
|
+
log: this.debugLog
|
|
11241
|
+
};
|
|
11242
|
+
}
|
|
11202
11243
|
reset() {
|
|
11203
11244
|
this.stopVideo();
|
|
11204
11245
|
this.candidateImages = [];
|
|
@@ -11215,12 +11256,16 @@ class ExtractorVideo {
|
|
|
11215
11256
|
this.hasShownTurnMessage = false;
|
|
11216
11257
|
clearTimeout(this.turnMessageTimer);
|
|
11217
11258
|
this.turnMessageTimer = null;
|
|
11259
|
+
this.debugLog = [];
|
|
11218
11260
|
}
|
|
11219
11261
|
async analyzeVideoStream() {
|
|
11220
11262
|
if (!this.isRunning) return;
|
|
11221
11263
|
const now = Date.now();
|
|
11222
11264
|
const cfgValues = (0,_config__WEBPACK_IMPORTED_MODULE_1__.getScanDocAIConfigValues)();
|
|
11223
11265
|
if (this.scanStartTime && now - this.scanStartTime > cfgValues.MAX_SCAN_DURATION_MS) {
|
|
11266
|
+
this.logDebug("scan_timeout", {
|
|
11267
|
+
elapsedMs: now - this.scanStartTime
|
|
11268
|
+
});
|
|
11224
11269
|
this.stopVideo();
|
|
11225
11270
|
this.onExtractedResults({
|
|
11226
11271
|
success: false,
|
|
@@ -11231,7 +11276,16 @@ class ExtractorVideo {
|
|
|
11231
11276
|
}
|
|
11232
11277
|
const canvas = document.createElement("canvas");
|
|
11233
11278
|
const video = document.getElementById("ScanDocAIVideoElement");
|
|
11234
|
-
if (video
|
|
11279
|
+
if (!video) {
|
|
11280
|
+
this.logDebug("analyze_no_video_element");
|
|
11281
|
+
setTimeout(() => this.analyzeVideoStream(), ExtractorVideo.FREQUENCY_MS);
|
|
11282
|
+
return;
|
|
11283
|
+
}
|
|
11284
|
+
if (video.videoWidth < video.videoHeight) {
|
|
11285
|
+
this.logDebug("portrait_video_detected", {
|
|
11286
|
+
videoWidth: video.videoWidth,
|
|
11287
|
+
videoHeight: video.videoHeight
|
|
11288
|
+
});
|
|
11235
11289
|
this.showMessage("Please rotate your device to landscape mode.");
|
|
11236
11290
|
this.candidateImages = [];
|
|
11237
11291
|
setTimeout(() => this.analyzeVideoStream(), ExtractorVideo.FREQUENCY_MS);
|
|
@@ -11250,6 +11304,9 @@ class ExtractorVideo {
|
|
|
11250
11304
|
const [isValidationOk, response] = await (0,_requests_validation__WEBPACK_IMPORTED_MODULE_3__["default"])(images.map(e => e.validationImg), this.pastBlurValues, {});
|
|
11251
11305
|
if (!isValidationOk) {
|
|
11252
11306
|
const msg = Array.isArray(response) ? response.join(", ") : String(response || "");
|
|
11307
|
+
this.logDebug("validation_failed", {
|
|
11308
|
+
response: msg
|
|
11309
|
+
});
|
|
11253
11310
|
if (msg.toLowerCase().includes("token expired/invalid")) {
|
|
11254
11311
|
this.stopVideo();
|
|
11255
11312
|
this.showMessage("Token expired/invalid. Please provide a new token.", true);
|
|
@@ -11264,6 +11321,7 @@ class ExtractorVideo {
|
|
|
11264
11321
|
return;
|
|
11265
11322
|
}
|
|
11266
11323
|
if (response?.InfoCode === "1006" && response?.TransactionID) {
|
|
11324
|
+
this.logDebug("unsupported_document", response);
|
|
11267
11325
|
const frontImage = this.candidateImages[this.candidateImages.length - 1].fullImg;
|
|
11268
11326
|
await (0,_requests_error_logging__WEBPACK_IMPORTED_MODULE_4__["default"])(frontImage, "", response.TransactionID, response.OS, response.Device, response.Browser);
|
|
11269
11327
|
this.showMessage("Document not supported.", true);
|
|
@@ -11345,6 +11403,10 @@ class ExtractorVideo {
|
|
|
11345
11403
|
return;
|
|
11346
11404
|
}
|
|
11347
11405
|
this.candidateImages = [];
|
|
11406
|
+
}).catch(err => {
|
|
11407
|
+
this.logDebug("document_detector_error", {
|
|
11408
|
+
message: err?.message || String(err)
|
|
11409
|
+
});
|
|
11348
11410
|
}).finally(() => {
|
|
11349
11411
|
setTimeout(() => this.analyzeVideoStream(), ExtractorVideo.FREQUENCY_MS);
|
|
11350
11412
|
});
|
|
@@ -11452,21 +11514,15 @@ class ExtractorVideo {
|
|
|
11452
11514
|
};
|
|
11453
11515
|
}
|
|
11454
11516
|
}
|
|
11455
|
-
if (supported.width) {
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
|
|
11459
|
-
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
}
|
|
11465
|
-
if (supported.aspectRatio) {
|
|
11466
|
-
video.aspectRatio = {
|
|
11467
|
-
ideal: width / height
|
|
11468
|
-
};
|
|
11469
|
-
}
|
|
11517
|
+
if (supported.width) video.width = {
|
|
11518
|
+
ideal: width
|
|
11519
|
+
};
|
|
11520
|
+
if (supported.height) video.height = {
|
|
11521
|
+
ideal: height
|
|
11522
|
+
};
|
|
11523
|
+
if (supported.aspectRatio) video.aspectRatio = {
|
|
11524
|
+
ideal: width / height
|
|
11525
|
+
};
|
|
11470
11526
|
return {
|
|
11471
11527
|
video,
|
|
11472
11528
|
audio: false
|
|
@@ -11485,12 +11541,14 @@ class ExtractorVideo {
|
|
|
11485
11541
|
async tryEnableDocumentFocus(stream) {
|
|
11486
11542
|
const track = stream?.getVideoTracks?.()[0];
|
|
11487
11543
|
if (!track) {
|
|
11544
|
+
this.logDebug("focus_no_track");
|
|
11488
11545
|
return {
|
|
11489
11546
|
ok: false,
|
|
11490
11547
|
reason: "No video track found"
|
|
11491
11548
|
};
|
|
11492
11549
|
}
|
|
11493
11550
|
if (!track.getCapabilities || !track.applyConstraints) {
|
|
11551
|
+
this.logDebug("focus_api_unavailable");
|
|
11494
11552
|
return {
|
|
11495
11553
|
ok: false,
|
|
11496
11554
|
reason: "Focus APIs unavailable on this browser/device",
|
|
@@ -11539,11 +11597,13 @@ class ExtractorVideo {
|
|
|
11539
11597
|
result.reason = "No supported focus controls were exposed";
|
|
11540
11598
|
}
|
|
11541
11599
|
result.settingsAfter = track.getSettings ? track.getSettings() : null;
|
|
11600
|
+
this.logDebug("focus_result", result);
|
|
11542
11601
|
return result;
|
|
11543
11602
|
} catch (err) {
|
|
11544
11603
|
result.ok = false;
|
|
11545
11604
|
result.error = err.message || String(err);
|
|
11546
11605
|
result.settingsAfter = track.getSettings ? track.getSettings() : null;
|
|
11606
|
+
this.logDebug("focus_error", result);
|
|
11547
11607
|
return result;
|
|
11548
11608
|
}
|
|
11549
11609
|
}
|
|
@@ -11553,12 +11613,23 @@ class ExtractorVideo {
|
|
|
11553
11613
|
width,
|
|
11554
11614
|
height
|
|
11555
11615
|
}) {
|
|
11556
|
-
|
|
11616
|
+
const constraints = this.buildVideoConstraints({
|
|
11557
11617
|
width,
|
|
11558
11618
|
height,
|
|
11559
11619
|
mode,
|
|
11560
11620
|
deviceId
|
|
11561
|
-
})
|
|
11621
|
+
});
|
|
11622
|
+
this.logDebug("getUserMedia_attempt", {
|
|
11623
|
+
constraints
|
|
11624
|
+
});
|
|
11625
|
+
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
11626
|
+
this.logDebug("getUserMedia_success", {
|
|
11627
|
+
deviceId,
|
|
11628
|
+
width,
|
|
11629
|
+
height,
|
|
11630
|
+
trackLabels: stream.getTracks().map(t => t.label)
|
|
11631
|
+
});
|
|
11632
|
+
return stream;
|
|
11562
11633
|
}
|
|
11563
11634
|
async testDeviceAtPreferredResolutions(device, mode) {
|
|
11564
11635
|
const attempts = [];
|
|
@@ -11595,6 +11666,13 @@ class ExtractorVideo {
|
|
|
11595
11666
|
aspectRatio,
|
|
11596
11667
|
label
|
|
11597
11668
|
});
|
|
11669
|
+
this.logDebug("device_test_success", {
|
|
11670
|
+
deviceLabel: device?.label,
|
|
11671
|
+
deviceId: device?.deviceId,
|
|
11672
|
+
requested: size,
|
|
11673
|
+
settings,
|
|
11674
|
+
label
|
|
11675
|
+
});
|
|
11598
11676
|
return {
|
|
11599
11677
|
result,
|
|
11600
11678
|
attempts
|
|
@@ -11605,6 +11683,13 @@ class ExtractorVideo {
|
|
|
11605
11683
|
requested: size,
|
|
11606
11684
|
error: err.message || String(err)
|
|
11607
11685
|
});
|
|
11686
|
+
this.logDebug("device_test_error", {
|
|
11687
|
+
deviceLabel: device?.label,
|
|
11688
|
+
deviceId: device?.deviceId,
|
|
11689
|
+
requested: size,
|
|
11690
|
+
error: err?.message || String(err),
|
|
11691
|
+
name: err?.name
|
|
11692
|
+
});
|
|
11608
11693
|
await this.stopMediaStream(stream);
|
|
11609
11694
|
}
|
|
11610
11695
|
}
|
|
@@ -11618,12 +11703,10 @@ class ExtractorVideo {
|
|
|
11618
11703
|
mode,
|
|
11619
11704
|
tested: []
|
|
11620
11705
|
};
|
|
11621
|
-
|
|
11622
|
-
// First try a warmup stream to unlock labels
|
|
11623
11706
|
let warmupStream = null;
|
|
11624
11707
|
let warmupResult = null;
|
|
11625
11708
|
try {
|
|
11626
|
-
const warmupSize = ExtractorVideo.VIDEO_CANDIDATE_SETTINGS[2];
|
|
11709
|
+
const warmupSize = ExtractorVideo.VIDEO_CANDIDATE_SETTINGS[2];
|
|
11627
11710
|
warmupStream = await this.openCandidateStream({
|
|
11628
11711
|
mode,
|
|
11629
11712
|
width: warmupSize.width,
|
|
@@ -11644,13 +11727,32 @@ class ExtractorVideo {
|
|
|
11644
11727
|
}),
|
|
11645
11728
|
requested: warmupSize
|
|
11646
11729
|
};
|
|
11647
|
-
|
|
11730
|
+
this.logDebug("warmup_success", {
|
|
11731
|
+
label,
|
|
11732
|
+
settings
|
|
11733
|
+
});
|
|
11734
|
+
} catch (err) {
|
|
11735
|
+
this.logDebug("warmup_error", {
|
|
11736
|
+
name: err?.name,
|
|
11737
|
+
message: err?.message || String(err)
|
|
11738
|
+
});
|
|
11648
11739
|
warmupStream = null;
|
|
11649
11740
|
}
|
|
11650
11741
|
let devices = [];
|
|
11651
11742
|
try {
|
|
11652
11743
|
devices = await navigator.mediaDevices.enumerateDevices();
|
|
11653
|
-
|
|
11744
|
+
this.logDebug("enumerate_devices", {
|
|
11745
|
+
devices: devices.map(d => ({
|
|
11746
|
+
kind: d.kind,
|
|
11747
|
+
label: d.label,
|
|
11748
|
+
deviceId: d.deviceId
|
|
11749
|
+
}))
|
|
11750
|
+
});
|
|
11751
|
+
} catch (err) {
|
|
11752
|
+
this.logDebug("enumerate_devices_error", {
|
|
11753
|
+
name: err?.name,
|
|
11754
|
+
message: err?.message || String(err)
|
|
11755
|
+
});
|
|
11654
11756
|
devices = [];
|
|
11655
11757
|
}
|
|
11656
11758
|
const videoInputs = devices.filter(d => d.kind === "videoinput");
|
|
@@ -11704,13 +11806,12 @@ class ExtractorVideo {
|
|
|
11704
11806
|
requested: chosen.requested,
|
|
11705
11807
|
source: "device-test"
|
|
11706
11808
|
};
|
|
11809
|
+
this.logDebug("camera_chosen", debug.chosen);
|
|
11707
11810
|
return {
|
|
11708
11811
|
chosen,
|
|
11709
11812
|
debug
|
|
11710
11813
|
};
|
|
11711
11814
|
}
|
|
11712
|
-
|
|
11713
|
-
// Final fallback: simple facingMode-based opens in descending priority
|
|
11714
11815
|
for (const size of ExtractorVideo.VIDEO_CANDIDATE_SETTINGS) {
|
|
11715
11816
|
try {
|
|
11716
11817
|
const stream = await this.openCandidateStream({
|
|
@@ -11746,16 +11847,24 @@ class ExtractorVideo {
|
|
|
11746
11847
|
requested: size,
|
|
11747
11848
|
source: "fallback-facingMode"
|
|
11748
11849
|
};
|
|
11850
|
+
this.logDebug("camera_chosen_fallback", debug.chosen);
|
|
11749
11851
|
return {
|
|
11750
11852
|
chosen,
|
|
11751
11853
|
debug
|
|
11752
11854
|
};
|
|
11753
|
-
} catch (
|
|
11855
|
+
} catch (err) {
|
|
11856
|
+
this.logDebug("fallback_open_error", {
|
|
11857
|
+
requested: size,
|
|
11858
|
+
name: err?.name,
|
|
11859
|
+
message: err?.message || String(err)
|
|
11860
|
+
});
|
|
11861
|
+
}
|
|
11754
11862
|
}
|
|
11755
11863
|
throw new Error("Could not start a suitable camera.");
|
|
11756
11864
|
}
|
|
11757
11865
|
async startVideo() {
|
|
11758
11866
|
try {
|
|
11867
|
+
this.logDebug("startVideo_begin");
|
|
11759
11868
|
const serviceConfig = (0,_config__WEBPACK_IMPORTED_MODULE_1__.getScanDocAIConfig)();
|
|
11760
11869
|
await serviceConfig.getAccessToken(false);
|
|
11761
11870
|
const videoElem = document.getElementById("ScanDocAIVideoElement");
|
|
@@ -11772,38 +11881,75 @@ class ExtractorVideo {
|
|
|
11772
11881
|
debug
|
|
11773
11882
|
} = await this.pickBestPhoneCamera(mode);
|
|
11774
11883
|
this.video.srcObject = chosen.stream;
|
|
11775
|
-
|
|
11776
|
-
|
|
11884
|
+
this.logDebug("srcObject_assigned", {
|
|
11885
|
+
label: chosen.label,
|
|
11886
|
+
settings: chosen.settings
|
|
11777
11887
|
});
|
|
11888
|
+
try {
|
|
11889
|
+
await this.video.play();
|
|
11890
|
+
this.logDebug("video_play_success", {
|
|
11891
|
+
readyState: this.video.readyState,
|
|
11892
|
+
videoWidth: this.video.videoWidth,
|
|
11893
|
+
videoHeight: this.video.videoHeight
|
|
11894
|
+
});
|
|
11895
|
+
} catch (e) {
|
|
11896
|
+
this.logDebug("video_play_error", {
|
|
11897
|
+
name: e?.name,
|
|
11898
|
+
message: e?.message || String(e)
|
|
11899
|
+
});
|
|
11900
|
+
throw e;
|
|
11901
|
+
}
|
|
11778
11902
|
this.focusDebug = await this.tryEnableDocumentFocus(chosen.stream);
|
|
11779
11903
|
this.cameraDebug = debug;
|
|
11780
11904
|
this.video.addEventListener("loadeddata", () => {
|
|
11905
|
+
this.logDebug("video_loadeddata", {
|
|
11906
|
+
videoWidth: this.video.videoWidth,
|
|
11907
|
+
videoHeight: this.video.videoHeight
|
|
11908
|
+
});
|
|
11781
11909
|
this.adjustOverlayPosition();
|
|
11782
11910
|
});
|
|
11911
|
+
this.video.addEventListener("error", () => {
|
|
11912
|
+
this.logDebug("video_element_error", {
|
|
11913
|
+
error: this.video?.error ? {
|
|
11914
|
+
code: this.video.error.code,
|
|
11915
|
+
message: this.video.error.message
|
|
11916
|
+
} : null
|
|
11917
|
+
});
|
|
11918
|
+
});
|
|
11783
11919
|
window.addEventListener("resize", () => this.adjustOverlayPosition());
|
|
11784
11920
|
setTimeout(() => this.adjustOverlayPosition(), 500);
|
|
11785
11921
|
this.scanStartTime = Date.now();
|
|
11786
11922
|
setTimeout(() => this.analyzeVideoStream(), ExtractorVideo.FREQUENCY_MS);
|
|
11787
11923
|
this.showMessage("Starting scanning");
|
|
11924
|
+
this.logDebug("startVideo_success", this.getDebugDump());
|
|
11788
11925
|
return true;
|
|
11789
11926
|
} catch (error) {
|
|
11790
11927
|
console.error("startVideo failed:", error);
|
|
11928
|
+
this.logDebug("startVideo_failed", {
|
|
11929
|
+
name: error?.name,
|
|
11930
|
+
message: error?.message || String(error),
|
|
11931
|
+
dump: this.getDebugDump()
|
|
11932
|
+
});
|
|
11791
11933
|
this.isRunning = false;
|
|
11792
11934
|
this.stopVideo();
|
|
11793
11935
|
this.onExtractedResults({
|
|
11794
11936
|
success: false,
|
|
11795
11937
|
code: error.status === 401 || error.status === 403 ? "004" : "005",
|
|
11796
|
-
info: error.status === 401 || error.status === 403 ? "Authentication failed: Invalid API key/token." : "Startup failed: " + (error.message || "Unknown error")
|
|
11938
|
+
info: error.status === 401 || error.status === 403 ? "Authentication failed: Invalid API key/token." : "Startup failed: " + (error.message || "Unknown error"),
|
|
11939
|
+
debug: ExtractorVideo.DEBUG ? this.getDebugDump() : undefined
|
|
11797
11940
|
});
|
|
11798
11941
|
return false;
|
|
11799
11942
|
}
|
|
11800
11943
|
}
|
|
11801
11944
|
stopVideo() {
|
|
11802
11945
|
this.isRunning = false;
|
|
11946
|
+
this.logDebug("stopVideo_called");
|
|
11803
11947
|
if (this.video) {
|
|
11804
11948
|
this.video.pause();
|
|
11805
11949
|
if (this.video.srcObject !== undefined && this.video.srcObject !== null) {
|
|
11806
|
-
|
|
11950
|
+
try {
|
|
11951
|
+
this.video.srcObject.getTracks().forEach(t => t.stop());
|
|
11952
|
+
} catch (_) {}
|
|
11807
11953
|
}
|
|
11808
11954
|
this.video.srcObject = null;
|
|
11809
11955
|
}
|
|
@@ -11924,13 +12070,11 @@ class ExtractorVideo {
|
|
|
11924
12070
|
margin-left: 20%;
|
|
11925
12071
|
margin-right: 20%;
|
|
11926
12072
|
}
|
|
11927
|
-
|
|
11928
12073
|
.desktopVideoHolder {
|
|
11929
12074
|
position: relative;
|
|
11930
12075
|
width: 100%;
|
|
11931
12076
|
overflow: hidden;
|
|
11932
12077
|
}
|
|
11933
|
-
|
|
11934
12078
|
.desktopVideo {
|
|
11935
12079
|
width: 100%;
|
|
11936
12080
|
height: auto;
|
|
@@ -11939,7 +12083,6 @@ class ExtractorVideo {
|
|
|
11939
12083
|
max-width: 100vw;
|
|
11940
12084
|
max-height: 100vh;
|
|
11941
12085
|
}
|
|
11942
|
-
|
|
11943
12086
|
.centerGuideDot {
|
|
11944
12087
|
position: absolute;
|
|
11945
12088
|
width: 16px;
|
|
@@ -11952,12 +12095,10 @@ class ExtractorVideo {
|
|
|
11952
12095
|
pointer-events: none;
|
|
11953
12096
|
display: none;
|
|
11954
12097
|
}
|
|
11955
|
-
|
|
11956
12098
|
@keyframes flicker {
|
|
11957
12099
|
0%, 100% { opacity: 1; }
|
|
11958
12100
|
50% { opacity: 0.3; }
|
|
11959
12101
|
}
|
|
11960
|
-
|
|
11961
12102
|
.backgroundOverlay {
|
|
11962
12103
|
position: absolute;
|
|
11963
12104
|
top: 0;
|
|
@@ -11968,7 +12109,6 @@ class ExtractorVideo {
|
|
|
11968
12109
|
z-index: 2;
|
|
11969
12110
|
pointer-events: none;
|
|
11970
12111
|
}
|
|
11971
|
-
|
|
11972
12112
|
.desktopFeedback {
|
|
11973
12113
|
position: relative;
|
|
11974
12114
|
display: flex;
|