aktualizacja struktury katalogów i dodanie mimifikacji
This commit is contained in:
parent
8c68b7a2e8
commit
400620946a
22
Dockerfile
22
Dockerfile
@ -1,27 +1,25 @@
|
|||||||
# Author:Mateusz Kędziora https://mkedziora.pl
|
# Author:Mateusz Kędziora https://mkedziora.pl
|
||||||
|
|
||||||
FROM golang:1.23.2-alpine AS builder
|
FROM golang:1.23.2-alpine AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY go.mod go.sum* ./
|
COPY go.mod go.sum* ./
|
||||||
|
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
|
||||||
COPY *.go ./
|
COPY *.go ./
|
||||||
|
|
||||||
RUN CGO_ENABLED=0 GOOS=linux go build -o main .
|
RUN CGO_ENABLED=0 GOOS=linux go build -o main .
|
||||||
|
|
||||||
|
# Etap minifikacji
|
||||||
|
FROM node:alpine AS minifier
|
||||||
|
WORKDIR /app
|
||||||
|
RUN npm install -g minify
|
||||||
|
COPY public/ ./public/
|
||||||
|
RUN find ./public -name "*.html" -exec minify -o {} {} \;
|
||||||
|
RUN find ./public/css -name "*.css" -exec minify -o {} {} \;
|
||||||
|
RUN find ./public/js -name "*.js" -exec minify -o {} {} \;
|
||||||
|
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
RUN apk --no-cache add ca-certificates
|
RUN apk --no-cache add ca-certificates
|
||||||
|
|
||||||
WORKDIR /root/
|
WORKDIR /root/
|
||||||
|
|
||||||
COPY --from=builder /app/main .
|
COPY --from=builder /app/main .
|
||||||
|
COPY --from=minifier /app/public/ ./public/
|
||||||
COPY public/ ./public
|
|
||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
CMD ["./main"]
|
CMD ["./main"]
|
16
main.go
16
main.go
@ -132,12 +132,20 @@ func main() {
|
|||||||
http.ServeFile(w, r, "public/app.html")
|
http.ServeFile(w, r, "public/app.html")
|
||||||
})
|
})
|
||||||
|
|
||||||
http.HandleFunc("/style_index.css", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/css/index.css", func(w http.ResponseWriter, r *http.Request) {
|
||||||
http.ServeFile(w, r, "public/style_index.css")
|
http.ServeFile(w, r, "public/css/index.css")
|
||||||
})
|
})
|
||||||
|
|
||||||
http.HandleFunc("/style_app.css", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/css/app.css", func(w http.ResponseWriter, r *http.Request) {
|
||||||
http.ServeFile(w, r, "public/style_app.css")
|
http.ServeFile(w, r, "public/css/app.css")
|
||||||
|
})
|
||||||
|
|
||||||
|
http.HandleFunc("/js/index.js", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.ServeFile(w, r, "public/js/index.js")
|
||||||
|
})
|
||||||
|
|
||||||
|
http.HandleFunc("/js/app.js", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.ServeFile(w, r, "public/js/app.js")
|
||||||
})
|
})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>App</title>
|
<title>App</title>
|
||||||
<meta name="robots" content="noindex" />
|
<meta name="robots" content="noindex" />
|
||||||
<link href="/style_app.css" rel="stylesheet" />
|
<link href="/css/app.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@ -14,74 +14,6 @@
|
|||||||
<a href="" id="url" rel="noopener noreferrer" target="_blank"></a>
|
<a href="" id="url" rel="noopener noreferrer" target="_blank"></a>
|
||||||
<button id="startBtn">Start listening</button>
|
<button id="startBtn">Start listening</button>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script src="/js/app.js"></script>
|
||||||
let lastData = "";
|
|
||||||
|
|
||||||
// Pobieranie parametru id z URL
|
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
|
||||||
const id = urlParams.get("id");
|
|
||||||
let new_url = "";
|
|
||||||
let fetchingData;
|
|
||||||
let newWindow;
|
|
||||||
document
|
|
||||||
.getElementById("startBtn")
|
|
||||||
.addEventListener("click", function () {
|
|
||||||
document.getElementById("info").textContent =
|
|
||||||
"Waiting for a new address...";
|
|
||||||
newWindow = window.open("about:blank", "_blank", "");
|
|
||||||
fetchingData = setInterval(checkForNewAddress, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
function checkForNewAddress() {
|
|
||||||
// Dodanie parametru id do URL zapytania
|
|
||||||
|
|
||||||
const apiUrl = id
|
|
||||||
? `/api/get?id=${encodeURIComponent(id)}`
|
|
||||||
: "/api/get";
|
|
||||||
|
|
||||||
fetch(apiUrl, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Cache-Control": "no-cache",
|
|
||||||
Pragma: "no-cache",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Brak danych");
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then((data) => {
|
|
||||||
if (data.data && data.data !== lastData) {
|
|
||||||
lastData = data.data;
|
|
||||||
console.log("Nowy adres:", data.data);
|
|
||||||
|
|
||||||
// Przejście do nowego adresu z resetowaniem nagłówków
|
|
||||||
const url = new URL(data.data);
|
|
||||||
|
|
||||||
const a = document.getElementById("url");
|
|
||||||
a.href = url;
|
|
||||||
a.textContent = url;
|
|
||||||
console.log(newWindow);
|
|
||||||
if (newWindow) {
|
|
||||||
console.log("ustawiono nowy adres");
|
|
||||||
newWindow.location.href = id
|
|
||||||
? `/api/url?id=${encodeURIComponent(id)}`
|
|
||||||
: "/api/url";
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("info").textContent =
|
|
||||||
"The page has opened; if not, click the link below. Link waiting is disabled.";
|
|
||||||
clearInterval(fetchingData);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("Błąd:", error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sprawdzaj co sekundę
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta name="robots" content="noindex" />
|
<meta name="robots" content="noindex" />
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5-qrcode/2.3.8/html5-qrcode.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5-qrcode/2.3.8/html5-qrcode.min.js"></script>
|
||||||
<link href="/style_index.css" rel="stylesheet" />
|
<link href="/css/index.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
@ -56,246 +56,6 @@
|
|||||||
|
|
||||||
<div id="status"></div>
|
<div id="status"></div>
|
||||||
|
|
||||||
<script>
|
<script src="/js/index.js"></script>
|
||||||
let currentStream = null;
|
|
||||||
let html5QrcodeScanner = null;
|
|
||||||
const statusDiv = document.getElementById("status");
|
|
||||||
const startButton = document.getElementById("startButton");
|
|
||||||
const stopButton = document.getElementById("stopButton");
|
|
||||||
const submitUrlButton = document.getElementById("submitUrl");
|
|
||||||
const manualUrlInput = document.getElementById("manualUrl");
|
|
||||||
|
|
||||||
// Funkcja do obsługi i wyświetlania błędów
|
|
||||||
function handleError(error) {
|
|
||||||
console.error("Wystąpił błąd:", error);
|
|
||||||
|
|
||||||
let errorMessage = "Wystąpił nieoczekiwany błąd.";
|
|
||||||
|
|
||||||
if (error instanceof Error) {
|
|
||||||
switch (error.name) {
|
|
||||||
case "NotAllowedError":
|
|
||||||
errorMessage =
|
|
||||||
"Dostęp do kamery został zabroniony. Sprawdź ustawienia przeglądarki.";
|
|
||||||
break;
|
|
||||||
case "NotFoundError":
|
|
||||||
errorMessage =
|
|
||||||
"Nie znaleziono kamery. Sprawdź czy urządzenie ma kamerę.";
|
|
||||||
break;
|
|
||||||
case "NotReadableError":
|
|
||||||
errorMessage =
|
|
||||||
"Kamera jest obecnie używana przez inną aplikację.";
|
|
||||||
break;
|
|
||||||
case "OverconstrainedError":
|
|
||||||
errorMessage =
|
|
||||||
"Nie znaleziono odpowiedniej kamery. Spróbuj ponownie.";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errorMessage =
|
|
||||||
error.message ||
|
|
||||||
"Wystąpił problem z kamerą. Spróbuj odświeżyć stronę.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
statusDiv.textContent = errorMessage;
|
|
||||||
return errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function sendUrl(url) {
|
|
||||||
try {
|
|
||||||
statusDiv.textContent = "Wysyłanie danych...";
|
|
||||||
|
|
||||||
const id = document.getElementById("idInput").value.trim();
|
|
||||||
const expire = document.getElementById("expireInput").value.trim();
|
|
||||||
const body = { value: url };
|
|
||||||
if (id) body.id = id;
|
|
||||||
if (expire) body.expire = expire;
|
|
||||||
|
|
||||||
const response = await fetch("/api/set", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
statusDiv.textContent = "Sukces! URL został przesłany.";
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
throw new Error("Błąd podczas wysyłania danych na serwer");
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
handleError(error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function stopScanner() {
|
|
||||||
try {
|
|
||||||
if (html5QrcodeScanner) {
|
|
||||||
await html5QrcodeScanner.stop();
|
|
||||||
html5QrcodeScanner.clear();
|
|
||||||
html5QrcodeScanner = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentStream) {
|
|
||||||
const tracks = currentStream.getTracks();
|
|
||||||
tracks.forEach((track) => {
|
|
||||||
if (track.readyState === "live") {
|
|
||||||
track.stop();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
currentStream = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.querySelector(".zoom-control").style.display = "none";
|
|
||||||
startButton.style.display = "block";
|
|
||||||
stopButton.style.display = "none";
|
|
||||||
|
|
||||||
const readerElement = document.getElementById("reader");
|
|
||||||
if (readerElement) {
|
|
||||||
readerElement.innerHTML = "";
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
handleError(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
startButton.addEventListener("click", async function () {
|
|
||||||
const zoomControl = document.querySelector(".zoom-control");
|
|
||||||
const zoomSlider = document.getElementById("zoomSlider");
|
|
||||||
const zoomValue = document.querySelector(".zoom-value");
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Najpierw zatrzymaj poprzedni skaner
|
|
||||||
await stopScanner();
|
|
||||||
|
|
||||||
// Poczekaj chwilę przed ponownym uruchomieniem
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
||||||
|
|
||||||
// Sprawdź dostępne urządzenia
|
|
||||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
||||||
const videoDevices = devices.filter(
|
|
||||||
(device) => device.kind === "videoinput"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (videoDevices.length === 0) {
|
|
||||||
throw new Error("Nie znaleziono żadnej kamery w urządzeniu");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preferuj tylną kamerę
|
|
||||||
const camera =
|
|
||||||
videoDevices.find(
|
|
||||||
(device) =>
|
|
||||||
device.label.toLowerCase().includes("back") ||
|
|
||||||
device.label.toLowerCase().includes("tylna")
|
|
||||||
) || videoDevices[videoDevices.length - 1];
|
|
||||||
|
|
||||||
const stream = await navigator.mediaDevices.getUserMedia({
|
|
||||||
video: {
|
|
||||||
deviceId: camera.deviceId,
|
|
||||||
facingMode: { ideal: "environment" },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
currentStream = stream;
|
|
||||||
const track = stream.getVideoTracks()[0];
|
|
||||||
|
|
||||||
if (!track) {
|
|
||||||
throw new Error("Nie udało się uzyskać dostępu do kamery");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sprawdź możliwości kamery
|
|
||||||
const capabilities = track.getCapabilities();
|
|
||||||
if (capabilities && capabilities.zoom) {
|
|
||||||
zoomControl.style.display = "block";
|
|
||||||
zoomSlider.min = capabilities.zoom.min;
|
|
||||||
zoomSlider.max = capabilities.zoom.max;
|
|
||||||
zoomSlider.step =
|
|
||||||
(capabilities.zoom.max - capabilities.zoom.min) / 100;
|
|
||||||
zoomSlider.value = capabilities.zoom.min;
|
|
||||||
zoomValue.textContent = `${capabilities.zoom.min}x`;
|
|
||||||
|
|
||||||
zoomSlider.addEventListener("input", async (e) => {
|
|
||||||
try {
|
|
||||||
const zoomValue = parseFloat(e.target.value);
|
|
||||||
await track.applyConstraints({
|
|
||||||
advanced: [{ zoom: zoomValue }],
|
|
||||||
});
|
|
||||||
document.querySelector(
|
|
||||||
".zoom-value"
|
|
||||||
).textContent = `${zoomValue.toFixed(1)}x`;
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("Nie udało się ustawić zoomu:", error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
zoomControl.style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
html5QrcodeScanner = new Html5Qrcode("reader");
|
|
||||||
const qrConfig = {
|
|
||||||
fps: 10,
|
|
||||||
qrbox: { width: 250, height: 250 },
|
|
||||||
aspectRatio: 1.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
startButton.style.display = "none";
|
|
||||||
stopButton.style.display = "block";
|
|
||||||
statusDiv.textContent = "Skaner jest aktywny...";
|
|
||||||
|
|
||||||
await html5QrcodeScanner.start(
|
|
||||||
{ facingMode: "environment" },
|
|
||||||
qrConfig,
|
|
||||||
async (decodedText) => {
|
|
||||||
await stopScanner();
|
|
||||||
if (await sendUrl(decodedText)) {
|
|
||||||
manualUrlInput.value = decodedText;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
// Ignorujemy błędy skanowania, bo pojawiają się często gdy nie ma kodu QR w kadrze
|
|
||||||
console.debug("Skanowanie:", error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
await stopScanner();
|
|
||||||
handleError(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
stopButton.addEventListener("click", stopScanner);
|
|
||||||
window.addEventListener("beforeunload", stopScanner);
|
|
||||||
document.addEventListener("visibilitychange", () => {
|
|
||||||
if (document.hidden && html5QrcodeScanner) {
|
|
||||||
stopScanner();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
submitUrlButton.addEventListener("click", async () => {
|
|
||||||
const url = manualUrlInput.value.trim();
|
|
||||||
if (!url) {
|
|
||||||
statusDiv.textContent = "Proszę wprowadzić URL";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
new URL(url); // Sprawdź poprawność URL
|
|
||||||
await sendUrl(url);
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof TypeError) {
|
|
||||||
statusDiv.textContent = "Wprowadzony URL jest nieprawidłowy";
|
|
||||||
} else {
|
|
||||||
handleError(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
manualUrlInput.addEventListener("keypress", (e) => {
|
|
||||||
if (e.key === "Enter") {
|
|
||||||
submitUrlButton.click();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
58
public/js/app.js
Normal file
58
public/js/app.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
let lastData = "";
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const id = urlParams.get("id");
|
||||||
|
let new_url = "";
|
||||||
|
let fetchingData;
|
||||||
|
let newWindow;
|
||||||
|
document.getElementById("startBtn").addEventListener("click", function () {
|
||||||
|
document.getElementById("info").textContent = "Waiting for a new address...";
|
||||||
|
newWindow = window.open("about:blank", "_blank", "");
|
||||||
|
fetchingData = setInterval(checkForNewAddress, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
function checkForNewAddress() {
|
||||||
|
// Dodanie parametru id do URL zapytania
|
||||||
|
|
||||||
|
const apiUrl = id ? `/api/get?id=${encodeURIComponent(id)}` : "/api/get";
|
||||||
|
|
||||||
|
fetch(apiUrl, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Cache-Control": "no-cache",
|
||||||
|
Pragma: "no-cache",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Brak danych");
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
if (data.data && data.data !== lastData) {
|
||||||
|
lastData = data.data;
|
||||||
|
console.log("Nowy adres:", data.data);
|
||||||
|
|
||||||
|
// Przejście do nowego adresu z resetowaniem nagłówków
|
||||||
|
const url = new URL(data.data);
|
||||||
|
|
||||||
|
const a = document.getElementById("url");
|
||||||
|
a.href = url;
|
||||||
|
a.textContent = url;
|
||||||
|
console.log(newWindow);
|
||||||
|
if (newWindow) {
|
||||||
|
console.log("ustawiono nowy adres");
|
||||||
|
newWindow.location.href = id
|
||||||
|
? `/api/url?id=${encodeURIComponent(id)}`
|
||||||
|
: "/api/url";
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("info").textContent =
|
||||||
|
"The page has opened; if not, click the link below. Link waiting is disabled.";
|
||||||
|
clearInterval(fetchingData);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Błąd:", error);
|
||||||
|
});
|
||||||
|
}
|
240
public/js/index.js
Normal file
240
public/js/index.js
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
let currentStream = null;
|
||||||
|
let html5QrcodeScanner = null;
|
||||||
|
const statusDiv = document.getElementById("status");
|
||||||
|
const startButton = document.getElementById("startButton");
|
||||||
|
const stopButton = document.getElementById("stopButton");
|
||||||
|
const submitUrlButton = document.getElementById("submitUrl");
|
||||||
|
const manualUrlInput = document.getElementById("manualUrl");
|
||||||
|
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const idParam = urlParams.get("id");
|
||||||
|
document.getElementById("idInput").value = idParam || "";
|
||||||
|
|
||||||
|
// Funkcja do obsługi i wyświetlania błędów
|
||||||
|
function handleError(error) {
|
||||||
|
console.error("Wystąpił błąd:", error);
|
||||||
|
|
||||||
|
let errorMessage = "Wystąpił nieoczekiwany błąd.";
|
||||||
|
|
||||||
|
if (error instanceof Error) {
|
||||||
|
switch (error.name) {
|
||||||
|
case "NotAllowedError":
|
||||||
|
errorMessage =
|
||||||
|
"Dostęp do kamery został zabroniony. Sprawdź ustawienia przeglądarki.";
|
||||||
|
break;
|
||||||
|
case "NotFoundError":
|
||||||
|
errorMessage =
|
||||||
|
"Nie znaleziono kamery. Sprawdź czy urządzenie ma kamerę.";
|
||||||
|
break;
|
||||||
|
case "NotReadableError":
|
||||||
|
errorMessage = "Kamera jest obecnie używana przez inną aplikację.";
|
||||||
|
break;
|
||||||
|
case "OverconstrainedError":
|
||||||
|
errorMessage = "Nie znaleziono odpowiedniej kamery. Spróbuj ponownie.";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorMessage =
|
||||||
|
error.message ||
|
||||||
|
"Wystąpił problem z kamerą. Spróbuj odświeżyć stronę.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
statusDiv.textContent = errorMessage;
|
||||||
|
return errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendUrl(url) {
|
||||||
|
try {
|
||||||
|
statusDiv.textContent = "Wysyłanie danych...";
|
||||||
|
|
||||||
|
const id = document.getElementById("idInput").value.trim();
|
||||||
|
const expire = document.getElementById("expireInput").value.trim();
|
||||||
|
const body = { value: url };
|
||||||
|
if (id) body.id = id;
|
||||||
|
if (expire) body.expire = expire;
|
||||||
|
|
||||||
|
const response = await fetch("/api/set", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
statusDiv.textContent = "Sukces! URL został przesłany.";
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new Error("Błąd podczas wysyłania danych na serwer");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function stopScanner() {
|
||||||
|
try {
|
||||||
|
if (html5QrcodeScanner) {
|
||||||
|
await html5QrcodeScanner.stop();
|
||||||
|
html5QrcodeScanner.clear();
|
||||||
|
html5QrcodeScanner = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentStream) {
|
||||||
|
const tracks = currentStream.getTracks();
|
||||||
|
tracks.forEach((track) => {
|
||||||
|
if (track.readyState === "live") {
|
||||||
|
track.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
currentStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelector(".zoom-control").style.display = "none";
|
||||||
|
startButton.style.display = "block";
|
||||||
|
stopButton.style.display = "none";
|
||||||
|
|
||||||
|
const readerElement = document.getElementById("reader");
|
||||||
|
if (readerElement) {
|
||||||
|
readerElement.innerHTML = "";
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startButton.addEventListener("click", async function () {
|
||||||
|
const zoomControl = document.querySelector(".zoom-control");
|
||||||
|
const zoomSlider = document.getElementById("zoomSlider");
|
||||||
|
const zoomValue = document.querySelector(".zoom-value");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Najpierw zatrzymaj poprzedni skaner
|
||||||
|
await stopScanner();
|
||||||
|
|
||||||
|
// Poczekaj chwilę przed ponownym uruchomieniem
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
|
|
||||||
|
// Sprawdź dostępne urządzenia
|
||||||
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
|
const videoDevices = devices.filter(
|
||||||
|
(device) => device.kind === "videoinput"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (videoDevices.length === 0) {
|
||||||
|
throw new Error("Nie znaleziono żadnej kamery w urządzeniu");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preferuj tylną kamerę
|
||||||
|
const camera =
|
||||||
|
videoDevices.find(
|
||||||
|
(device) =>
|
||||||
|
device.label.toLowerCase().includes("back") ||
|
||||||
|
device.label.toLowerCase().includes("tylna")
|
||||||
|
) || videoDevices[videoDevices.length - 1];
|
||||||
|
|
||||||
|
const stream = await navigator.mediaDevices.getUserMedia({
|
||||||
|
video: {
|
||||||
|
deviceId: camera.deviceId,
|
||||||
|
facingMode: { ideal: "environment" },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
currentStream = stream;
|
||||||
|
const track = stream.getVideoTracks()[0];
|
||||||
|
|
||||||
|
if (!track) {
|
||||||
|
throw new Error("Nie udało się uzyskać dostępu do kamery");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprawdź możliwości kamery
|
||||||
|
const capabilities = track.getCapabilities();
|
||||||
|
if (capabilities && capabilities.zoom) {
|
||||||
|
zoomControl.style.display = "block";
|
||||||
|
zoomSlider.min = capabilities.zoom.min;
|
||||||
|
zoomSlider.max = capabilities.zoom.max;
|
||||||
|
zoomSlider.step = (capabilities.zoom.max - capabilities.zoom.min) / 100;
|
||||||
|
zoomSlider.value = capabilities.zoom.min;
|
||||||
|
zoomValue.textContent = `${capabilities.zoom.min}x`;
|
||||||
|
|
||||||
|
zoomSlider.addEventListener("input", async (e) => {
|
||||||
|
try {
|
||||||
|
const zoomValue = parseFloat(e.target.value);
|
||||||
|
await track.applyConstraints({
|
||||||
|
advanced: [{ zoom: zoomValue }],
|
||||||
|
});
|
||||||
|
document.querySelector(
|
||||||
|
".zoom-value"
|
||||||
|
).textContent = `${zoomValue.toFixed(1)}x`;
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Nie udało się ustawić zoomu:", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
zoomControl.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
html5QrcodeScanner = new Html5Qrcode("reader");
|
||||||
|
const qrConfig = {
|
||||||
|
fps: 10,
|
||||||
|
qrbox: { width: 250, height: 250 },
|
||||||
|
aspectRatio: 1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
startButton.style.display = "none";
|
||||||
|
stopButton.style.display = "block";
|
||||||
|
statusDiv.textContent = "Skaner jest aktywny...";
|
||||||
|
|
||||||
|
await html5QrcodeScanner.start(
|
||||||
|
{ facingMode: "environment" },
|
||||||
|
qrConfig,
|
||||||
|
async (decodedText) => {
|
||||||
|
await stopScanner();
|
||||||
|
if (await sendUrl(decodedText)) {
|
||||||
|
manualUrlInput.value = decodedText;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
// Ignorujemy błędy skanowania, bo pojawiają się często gdy nie ma kodu QR w kadrze
|
||||||
|
console.debug("Skanowanie:", error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
await stopScanner();
|
||||||
|
handleError(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
stopButton.addEventListener("click", stopScanner);
|
||||||
|
window.addEventListener("beforeunload", stopScanner);
|
||||||
|
document.addEventListener("visibilitychange", () => {
|
||||||
|
if (document.hidden && html5QrcodeScanner) {
|
||||||
|
stopScanner();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
submitUrlButton.addEventListener("click", async () => {
|
||||||
|
const url = manualUrlInput.value.trim();
|
||||||
|
if (!url) {
|
||||||
|
statusDiv.textContent = "Proszę wprowadzić URL";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new URL(url); // Sprawdź poprawność URL
|
||||||
|
await sendUrl(url);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof TypeError) {
|
||||||
|
statusDiv.textContent = "Wprowadzony URL jest nieprawidłowy";
|
||||||
|
} else {
|
||||||
|
handleError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
manualUrlInput.addEventListener("keypress", (e) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
submitUrlButton.click();
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user