Release 1.1.0: QR-Reportimport, Regal-Auswahlmodal, Einlagern/Auslagern-Verknuepfungen aus Reifenlager, Stabilitaetsfixes
This commit is contained in:
1 parent
cba9414e92
commit
3404fb9875
25 files changed
+5106
-744
No files matched your search
@@ -0,0 +1,88 @@
|
||||
// QR code scanner interop (html5-qrcode) for Blazor.
|
||||
// Usage from .NET: qrScanner.start(elementId, dotNetRef) / qrScanner.stop()
|
||||
window.qrScanner = (function () {
|
||||
let scanner = null;
|
||||
let lastText = null;
|
||||
let lastTime = 0;
|
||||
|
||||
async function ensureLib() {
|
||||
if (window.Html5Qrcode) return;
|
||||
await new Promise((resolve, reject) => {
|
||||
const s = document.createElement('script');
|
||||
s.src = 'lib/html5-qrcode/html5-qrcode.min.js';
|
||||
s.onload = resolve;
|
||||
s.onerror = () => reject(new Error('QR-Bibliothek konnte nicht geladen werden.'));
|
||||
document.head.appendChild(s);
|
||||
});
|
||||
}
|
||||
|
||||
async function start(elementId, dotNetRef) {
|
||||
await stop();
|
||||
await ensureLib();
|
||||
|
||||
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
||||
throw new Error('Kamera wird von diesem Browser nicht unterstützt (HTTPS erforderlich).');
|
||||
}
|
||||
|
||||
scanner = new Html5Qrcode(elementId, {
|
||||
formatsToSupport: [Html5QrcodeSupportedFormats.QR_CODE],
|
||||
verbose: false
|
||||
});
|
||||
|
||||
const config = {
|
||||
fps: 10,
|
||||
qrbox: (w, h) => {
|
||||
const size = Math.max(180, Math.min(w, h) * 0.7);
|
||||
return { width: size, height: size };
|
||||
},
|
||||
aspectRatio: 1.0
|
||||
};
|
||||
|
||||
const onSuccess = (text) => {
|
||||
const now = Date.now();
|
||||
if (text === lastText && now - lastTime < 2500) return;
|
||||
lastText = text;
|
||||
lastTime = now;
|
||||
dotNetRef.invokeMethodAsync('OnQrScanned', text);
|
||||
};
|
||||
|
||||
try {
|
||||
await scanner.start({ facingMode: 'environment' }, config, onSuccess, () => { });
|
||||
} catch (e) {
|
||||
// Fallback: any camera
|
||||
const cams = await Html5Qrcode.getCameras();
|
||||
if (!cams || cams.length === 0) throw new Error('Keine Kamera gefunden.');
|
||||
await scanner.start(cams[0].id, config, onSuccess, () => { });
|
||||
}
|
||||
}
|
||||
|
||||
async function stop() {
|
||||
if (!scanner) return;
|
||||
try {
|
||||
if (scanner.isScanning) await scanner.stop();
|
||||
scanner.clear();
|
||||
} catch (e) { /* ignore */ }
|
||||
scanner = null;
|
||||
lastText = null;
|
||||
}
|
||||
|
||||
// Short audio feedback ("success" | "error") via Web Audio, no asset required.
|
||||
function playSound(type) {
|
||||
try {
|
||||
const Ctx = window.AudioContext || window.webkitAudioContext;
|
||||
if (!Ctx) return;
|
||||
const ctx = new Ctx();
|
||||
const osc = ctx.createOscillator();
|
||||
const gain = ctx.createGain();
|
||||
osc.type = 'sine';
|
||||
osc.frequency.value = type === 'error' ? 220 : 880;
|
||||
gain.gain.value = 0.08;
|
||||
osc.connect(gain).connect(ctx.destination);
|
||||
osc.start();
|
||||
osc.stop(ctx.currentTime + (type === 'error' ? 0.25 : 0.12));
|
||||
osc.onended = () => ctx.close().catch(() => { });
|
||||
} catch (e) { /* audio is best-effort */ }
|
||||
}
|
||||
|
||||
return { start, stop, playSound };
|
||||
})();
|
||||
@@ -0,0 +1 @@
|
||||
var __Html5QrcodeLibrary__;(()=>{var t={449:function(t,e,r){!function(t){"use strict";function e(t){return null==t}var n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])};var i,o=function(t){function e(e){var r,n,i,o=this.constructor,s=t.call(this,e)||this;return Object.defineProperty(s,"name",{value:o.name,enumerable:!1}),r=s,n=o.prototype,(i=Object.setPrototypeOf)?i(r,n):r.__proto__=n,function(t,e){void 0===e&&(e=t.constructor);var r=Error.captureStackTrace;r&&r(t,e)}(s),s}return function(t,e){function r(){this.constructor=t}n(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}(e,t),e}(Error);class s extends o{constructor(t=undefined){super(t),this.message=t}getKind(){return this.constructor.kind}}s.kind="Exception";class a extends s{}a.kind="ArgumentException";class c extends s{}c.kind="IllegalArgumentException";class l{constructor(t){if(this.binarizer=t,null===t)throw new c("Binarizer must be non-null.")}getWidth(){return this.binarizer.getWidth()}getHeight(){return this.binarizer.getHeight()}getBlackRow(t,e){return this.binarizer.getBlackRow(t,e)}getBlackMatrix(){return null!==this.matrix&&void 0!==this.matrix||(this.matrix=this.binarizer.getBlackMatrix()),this.matrix}isCropSupported(){return this.binarizer.getLuminanceSource().isCropSupported()}crop(t,e,r,n){const i=this.binarizer.getLuminanceSource().crop(t,e,r,n);return new l(this.binarizer.createBinarizer(i))}isRotateSupported(){return this.binarizer.getLuminanceSource().isRotateSupported()}rotateCounterClockwise(){const t=this.binarizer.getLuminanceSource().rotateCounterClockwise();return new l(this.binarizer.createBinarizer(t))}rotateCounterClockwise45(){const t=this.binarizer.getLuminanceSource().rotateCounterClockwise45();return new l(this.binarizer.createBinarizer(t))}toString(){try{return this.getBlackMatrix().toString()}catch(t){return""}}}class h extends s{static getChecksumInstance(){return new h}}h.kind="ChecksumException";class u{constructor(t){this.source=t}getLuminanceSource(){return this.source}getWidth(){return this.source.getWidth()}getHeight(){return this.source.getHeight()}}class d{static arraycopy(t,e,r,n,i){for(;i--;)r[n++]=t[e++]}static currentTimeMillis(){return Date.now()}}class f extends s{}f.kind="IndexOutOfBoundsException";class g extends f{constructor(t=undefined,e=undefined){super(e),this.index=t,this.message=e}}g.kind="ArrayIndexOutOfBoundsException";class w{static fill(t,e){for(let r=0,n=t.length;r<n;r++)t[r]=e}static fillWithin(t,e,r,n){w.rangeCheck(t.length,e,r);for(let i=e;i<r;i++)t[i]=n}static rangeCheck(t,e,r){if(e>r)throw new c("fromIndex("+e+") > toIndex("+r+")");if(e<0)throw new g(e);if(r>t)throw new g(r)}static asList(...t){return t}static create(t,e,r){return Array.from({length:t}).map((t=>Array.from({length:e}).fill(r)))}static createInt32Array(t,e,r){return Array.from({length:t}).map((t=>Int32Array.from({length:e}).fill(r)))}static equals(t,e){if(!t)return!1;if(!e)return!1;if(!t.length)return!1;if(!e.length)return!1;if(t.length!==e.length)return!1;for(let r=0,n=t.length;r<n;r++)if(t[r]!==e[r])return!1;return!0}static hashCode(t){if(null===t)return 0;let e=1;for(const r of t)e=31*e+r;return e}static fillUint8Array(t,e){for(let r=0;r!==t.length;r++)t[r]=e}static copyOf(t,e){return t.slice(0,e)}static copyOfUint8Array(t,e){if(t.length<=e){const r=new Uint8Array(e);return r.set(t),r}return t.slice(0,e)}static copyOfRange(t,e,r){const n=r-e,i=new Int32Array(n);return d.arraycopy(t,e,i,0,n),i}static binarySearch(t,e,r){void 0===r&&(r=w.numberComparator);let n=0,i=t.length-1;for(;n<=i;){const o=i+n>>1,s=r(e,t[o]);if(s>0)n=o+1;else{if(!(s<0))return o;i=o-1}}return-n-1}static numberComparator(t,e){return t-e}}class m{static numberOfTrailingZeros(t){let e;if(0===t)return 32;let r=31;return e=t<<16,0!==e&&(r-=16,t=e),e=t<<8,0!==e&&(r-=8,t=e),e=t<<4,0!==e&&(r-=4,t=e),e=t<<2,0!==e&&(r-=2,t=e),r-(t<<1>>>31)}static numberOfLeadingZeros(t){if(0===t)return 32;let e=1;return t>>>16==0&&(e+=16,t<<=16),t>>>24==0&&(e+=8,t<<=8),t>>>28==0&&(e+=4,t<<=4),t>>>30==0&&(e+=2,t<<=2),e-=t>>>31,e}static toHexString(t){return t.toString(16)}static toBinaryString(t){return String(parseInt(String(t),2))}static bitCount(t){return t=(t=(858993459&(t-=t>>>1&1431655765))+(t>>>2&858993459))+(t>>>4)&252645135,63&(t+=t>>>8)+(t>>>16)}static truncDivision(t,e){return Math.trunc(t/e)}static parseInt(t,e=undefined){return parseInt(t,e)}}m.MIN_VALUE_32_BITS=-2147483648,m.MAX_VALUE=Number.MAX_SAFE_INTEGER;class p{constructor(t,e){void 0===t?(this.size=0,this.bits=new Int32Array(1)):(this.size=t,this.bits=null==e?p.makeArray(t):e)}getSize(){return this.size}getSizeInBytes(){return Math.floor((this.size+7)/8)}ensureCapacity(t){if(t>32*this.bits.length){const e=p.makeArray(t);d.arraycopy(this.bits,0,e,0,this.bits.length),this.bits=e}}get(t){return 0!=(this.bits[Math.floor(t/32)]&1<<(31&t))}set(t){this.bits[Math.floor(t/32)]|=1<<(31&t)}fLine truncated
|
||||
Reference in new issue
Block a user