Houjie
2025-04-11 1bf977929dd324f3ac64b70debd8a79443c54392
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
 * @fileoverview
 * File for camera selection UI.
 * 
 * @author mebjas <minhazav@gmail.com>
 * 
 * The word "QR Code" is registered trademark of DENSO WAVE INCORPORATED
 * http://www.denso-wave.com/qrcode/faqpatent-e.html
 */
 
import { CameraDevice } from "../../camera/core";
import {
    BaseUiElementFactory,
    PublicUiElementIdAndClasses
} from "./base";
import {
    Html5QrcodeScannerStrings
} from "../../strings";
 
/** Class for rendering and handling camera selection UI. */
export class CameraSelectionUi {
 
    private readonly selectElement: HTMLSelectElement;
    private readonly options: Array<HTMLOptionElement>;
    private readonly cameras: Array<CameraDevice>;
 
    private constructor(cameras: Array<CameraDevice>) {
        this.selectElement = BaseUiElementFactory
            .createElement<HTMLSelectElement>(
            "select",
            PublicUiElementIdAndClasses.CAMERA_SELECTION_SELECT_ID);
        this.cameras = cameras;
        this.options = [];        
    }
 
    /*eslint complexity: ["error", 10]*/
    private render(
        parentElement: HTMLElement) {
        const cameraSelectionContainer = document.createElement("span");
        cameraSelectionContainer.style.marginRight = "10px";
        const numCameras = this.cameras.length;
        if (numCameras === 0) {
            throw new Error("No cameras found");
        }
        if (numCameras === 1) {
            // If only one camera is found, don't show camera selection.
            cameraSelectionContainer.style.display = "none";
        } else {
            // Otherwise, show the number of cameras found as well.
            const selectCameraString = Html5QrcodeScannerStrings.selectCamera();
            cameraSelectionContainer.innerText
                = `${selectCameraString} (${this.cameras.length})  `;
        }
 
        let anonymousCameraId = 1;
 
        for (const camera of this.cameras) {
            const value = camera.id;
            let name = camera.label == null ? value : camera.label;
            // If no name is returned by the browser, replace it with custom
            // camera label with a count.
            if (!name || name === "") {
                name = [
                    Html5QrcodeScannerStrings.anonymousCameraPrefix(),
                    anonymousCameraId++
                    ].join(" ");
            }
 
            const option = document.createElement("option");
            option.value = value;
            option.innerText = name;
            this.options.push(option);
            this.selectElement.appendChild(option);
        }
        cameraSelectionContainer.appendChild(this.selectElement);
        parentElement.appendChild(cameraSelectionContainer);
    }
 
    //#region Public APIs
    public disable() {
        this.selectElement.disabled = true;
    }
 
    public isDisabled() {
        return this.selectElement.disabled === true;
    }
 
    public enable() {
        this.selectElement.disabled = false;
    }
 
    public getValue(): string {
        return this.selectElement.value;
    }
 
    public hasValue(value: string): boolean {
        for (const option of this.options) {
            if (option.value === value) {
                return true;
            }
        }
        return false;
    }
 
    public setValue(value: string) {
        if (!this.hasValue(value)) {
            throw new Error(`${value} is not present in the camera list.`);
        }
        this.selectElement.value = value;
    }
 
    public hasSingleItem() {
        return this.cameras.length === 1;
    }
 
    public numCameras() {
        return this.cameras.length;
    }
    //#endregion
 
    /** Creates instance of {@link CameraSelectionUi} and renders it. */
    public static create(
        parentElement: HTMLElement,
        cameras: Array<CameraDevice>): CameraSelectionUi {
        let cameraSelectUi = new CameraSelectionUi(cameras);
        cameraSelectUi.render(parentElement);
        return cameraSelectUi;
    }
}