diff --git a/.gitea/workflows/build-docker.yaml b/.gitea/workflows/build-docker.yaml index 79b5b32..1eb4a7f 100644 --- a/.gitea/workflows/build-docker.yaml +++ b/.gitea/workflows/build-docker.yaml @@ -2,8 +2,6 @@ name: Build dev docker image on: push: - branches: - - main tags: - '*' workflow_dispatch: @@ -84,6 +82,6 @@ jobs: tag_name: ${{ gitea.ref_name }} name: ${{ gitea.ref_name }} body: | - "## Docker images" - "`gitea.furb.it/${{ gitea.repository }}:${{ gitea.ref_name }}`" - "`gitea.furb.it/${{ gitea.repository }}:latest`" \ No newline at end of file + ## Docker images + `gitea.furb.it/${{ gitea.repository }}:${{ gitea.ref_name }}` + `gitea.furb.it/${{ gitea.repository }}:latest` \ No newline at end of file diff --git a/.gitea/workflows/test-build.yaml b/.gitea/workflows/test-build.yaml new file mode 100644 index 0000000..c66791b --- /dev/null +++ b/.gitea/workflows/test-build.yaml @@ -0,0 +1,35 @@ +name: Build dev docker image + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + + # Checkout repository for build + - name: Checkout beer-inventory repository + uses: actions/checkout@v4 + with: + ref: ${{ gitea.ref }} + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + # Install NPM packages + - name: Install NPM packages + run: npm ci + + # Build project + - name: Build project + run: | + npx zenstack generate + npx remix vite:build diff --git a/app/root.tsx b/app/root.tsx index 9f5d2f4..8a94a87 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -8,7 +8,7 @@ import { isRouteErrorResponse, useRouteError } from "@remix-run/react"; -import type { PropsWithChildren } from "react"; +import React, { useEffect, useState, type PropsWithChildren } from "react"; import stylesheet from "bootstrap/dist/css/bootstrap.min.css?url"; @@ -53,6 +53,45 @@ export default function App() { export function ErrorBoundary() { const error = useRouteError(); + const [isOnline, setIsOnline] = useState( + typeof navigator !== "undefined" ? navigator.onLine : true + ); + + const tryRefresh = async () => { + if (typeof window === "undefined") return; + try { + const res = await fetch(window.location.href, { method: "GET", cache: "no-store" }); + if (res && res.ok) { + window.location.reload(); + } + } catch (e) { + // network still down; ignore, we'll retry on the next interval or when online + } + }; + + useEffect(() => { + if (typeof window === "undefined") return; + + const handleOnline = () => { + setIsOnline(true); + tryRefresh(); + }; + const handleOffline = () => setIsOnline(false); + + window.addEventListener("online", handleOnline); + window.addEventListener("offline", handleOffline); + + const hourly = window.setInterval(() => { + tryRefresh(); + }, 60 * 60 * 1000); + + return () => { + window.removeEventListener("online", handleOnline); + window.removeEventListener("offline", handleOffline); + window.clearInterval(hourly); + }; + }, []); + if (isRouteErrorResponse(error)) { return (

{error.status}

{error.statusText} +
+ + +
Status: {isOnline ? "Online" : "Offline"}. Will retry automatically every hour.
+
@@ -84,6 +142,25 @@ export function ErrorBoundary() {

App Error

{errorMessage} +
+ + +
Status: {isOnline ? "Online" : "Offline"}. Will retry automatically every hour.
+
diff --git a/app/routes/scan/route.tsx b/app/routes/scan/route.tsx index fa1244a..d69cb0f 100644 --- a/app/routes/scan/route.tsx +++ b/app/routes/scan/route.tsx @@ -65,6 +65,7 @@ export async function action({ export default function ScanRoute() { const aData = useActionData(); const lData = useLoaderData(); + const fullscreenBtnRef = useRef(null); const [lastScanned, setLastScanned] = useState<{name:string;image:string|null} | null>(null); const [showLastScanned, setShowLastScanned] = useState(false); @@ -76,6 +77,19 @@ export default function ScanRoute() { window.setTimeout(() => inputRef.current?.focus(), 0); }; + const toggleFullscreen = async () => { + if (typeof document === "undefined") return; + try { + if (document.fullscreenElement) { + await document.exitFullscreen(); + } else { + await document.documentElement.requestFullscreen(); + } + } catch (e) { + // ignore errors (user gesture required in some contexts) + } + }; + useEffect(() => { focusInput(); }, []); @@ -116,8 +130,8 @@ export default function ScanRoute() { -

History

-
+

fullscreenBtnRef.current?.click()} style={{cursor: 'pointer'}}>History

+
@@ -139,9 +153,16 @@ export default function ScanRoute() { -

Scan Barcode

+

fullscreenBtnRef.current?.click()} style={{cursor: 'pointer'}}>Scan Barcode

+ {/* Hidden fullscreen toggle button - triggered by clicking the h3 headers */} +