Einzelstueck-QR ueber Custom-Scheme statt Universal Link

Universal Links (Associated Domains) sind an eine feste Domain gebunden - fuer
einen selbstgehosteten Dienst untauglich (jede Instanz hat eine andere URL) und
die Domain stand im offenen Quellcode (Leak). Jetzt tragen Einzelstueck-QRs das
Custom-Scheme vorrania://i/<UID>: Die normale Kamera-App oeffnet die App weiterhin,
aber ohne Domain-Bindung und ohne Server im Code. applinks-Eintrag entfernt.

Web: itemDeepLink()-Helfer, genutzt in Einzelstuecke-Liste/-Etiketten und im
P-touch-Export. Lagerort-QRs bleiben unveraendert (https).
iOS: Router erkennt vorrania://i/<UID> und oeffnet das Einzelstueck am aktiven Server.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-30 11:34:37 +02:00
parent 48d47f1d39
commit f981f41d94
5 changed files with 36 additions and 15 deletions

View File

@@ -3,10 +3,11 @@ import { api } from "../api";
import { useConfirm } from "../confirm";
import Icon from "../components/Icon";
import { asTree } from "../categoryTree";
import { itemDeepLink } from "../qr";
// Baut die Etiketten-CSV mit wählbarem Trennzeichen (BOM für Excel-Umlaute).
// QR-Inhalt = Link aufs Stück.
function buildLabelCsv(rows, origin, delim = ",") {
function buildLabelCsv(rows, delim = ",") {
const head = ["QR-Inhalt", "UID", "Produkt", "Marke", "Kategorie", "Lagerort"];
const delimRe = delim === "\t" ? "\\t" : delim;
const needsQuote = new RegExp(`[${delimRe}"\\n\\r]`);
@@ -20,7 +21,7 @@ function buildLabelCsv(rows, origin, delim = ",") {
};
const lines = [head.map(esc).join(delim)];
for (const r of rows) {
lines.push([`${origin}/i/${r.uid}`, r.uid, r.product, r.brand, r.category, r.location]
lines.push([itemDeepLink(r.uid), r.uid, r.product, r.brand, r.category, r.location]
.map(esc).join(delim));
}
return "" + lines.join("\r\n");
@@ -161,7 +162,7 @@ export default function Transfer() {
try {
const rows = await api.labelRows([...selCats]);
if (!rows.length) { setLabelInfo("Keine Einzelstücke in der Auswahl."); return; }
const csv = buildLabelCsv(rows, window.location.origin, labelDelim);
const csv = buildLabelCsv(rows, labelDelim);
const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");