Skip to content

Commit

Permalink
improved scanning
Browse files Browse the repository at this point in the history
Co-Authored-By: Bloxs <51055767+Blocksnmore@users.noreply.github.com>
  • Loading branch information
quick007 and Blocksnmore committed Mar 21, 2024
1 parent cf2ead4 commit 90b3111
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 70 deletions.
7 changes: 5 additions & 2 deletions fresh.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ import * as $events_editing_ticketSettings from "./islands/events/editing/ticket
import * as $events_list_exportTicketData from "./islands/events/list/exportTicketData.tsx";
import * as $events_list_filters from "./islands/events/list/filters.tsx";
import * as $events_list_ticketDropdown from "./islands/events/list/ticketDropdown.tsx";
import * as $events_scanning from "./islands/events/scanning.tsx";
import * as $events_scanning_index from "./islands/events/scanning/index.tsx";
import * as $events_scanning_scanning_types from "./islands/events/scanning/scanning.types.ts";
import * as $events_teams_filters from "./islands/events/teams/filters.tsx";
import * as $events_teams_invite from "./islands/events/teams/invite.tsx";
import * as $events_teams_manage from "./islands/events/teams/manage.tsx";
Expand Down Expand Up @@ -199,7 +200,9 @@ const manifest = {
"./islands/events/list/exportTicketData.tsx": $events_list_exportTicketData,
"./islands/events/list/filters.tsx": $events_list_filters,
"./islands/events/list/ticketDropdown.tsx": $events_list_ticketDropdown,
"./islands/events/scanning.tsx": $events_scanning,
"./islands/events/scanning/index.tsx": $events_scanning_index,
"./islands/events/scanning/scanning.types.ts":
$events_scanning_scanning_types,
"./islands/events/teams/filters.tsx": $events_teams_filters,
"./islands/events/teams/invite.tsx": $events_teams_invite,
"./islands/events/teams/manage.tsx": $events_teams_manage,
Expand Down
121 changes: 57 additions & 64 deletions islands/events/scanning.tsx → islands/events/scanning/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,44 @@ import { BarcodeDetector } from "npm:barcode-detector";
// import { BarcodeDetector } from "https://fastly.jsdelivr.net/npm/barcode-detector@2/dist/es/pure.min.js";
import { Ticket } from "@/utils/db/kv.types.ts";
import { useSignal } from "@preact/signals";
import Dropdown from "../components/pickers/dropdown.tsx";
import Dropdown from "../../components/pickers/dropdown.tsx";
import CameraRotate from "$tabler/camera-rotate.tsx";
import CameraPlus from "$tabler/camera-plus.tsx";
import Popup from "@/components/popup.tsx";
import {
ScanningState,
TicketState,
} from "@/islands/events/scanning/scanning.types.ts";

// Chatgpt fucked this up too much so we're abandoning rotations - Bloxs
// Should've paid attention in trig class - LS

export default function Scanner({ eventID }: { eventID: string }) {
const error = useSignal<string | null>(null);
const isInitialized = useSignal(false);
const currentTicket = useSignal<
| { code: string; status: "invalid" | "loading"; ticketData: null }
| {
code: string;
status: "used" | "valid" | "inactive";
ticketData: Ticket;
}
| null
>(null);
const currentTicket = useSignal<TicketState | null>(null);
const cameraIds = useSignal<MediaDeviceInfo[]>([]);
const currentCamera = useSignal<string>("");
const isCameraSwitching = useSignal(false);
const cameraSwitchPopupOpen = useSignal(false);
const scanningState = useSignal<ScanningState>(ScanningState.READY);

const scanCode = async (code: string) => {
try {
const res = await fetch(`/api/events/scanned`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ ticketID: code, eventID: eventID }),
});

if (res.status != 200) return false;
return true;
} catch {
return false;
}
};

useEffect(() => {
(async () => {
Expand Down Expand Up @@ -99,21 +113,16 @@ export default function Scanner({ eventID }: { eventID: string }) {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;

const checkedCodes: Map<
string,
| { status: "loading" | "invalid"; checkedAt: number }
| {
status: "valid" | "used" | "inactive";
ticketData: Ticket;
checkedAt: number;
}
> = new Map();
const checkedCodes: Map<string, TicketState> = new Map();

setInterval(() => {
for (const [code, codeData] of checkedCodes) {
const timeSinceScan = Date.now() - codeData.checkedAt;

if (codeData.status == "loading" && timeSinceScan > 5 * 1000) {
if (
codeData.status === ScanningState.LOADING &&
timeSinceScan > 5 * 1000
) {
checkedCodes.delete(code);
}

Expand Down Expand Up @@ -152,19 +161,21 @@ export default function Scanner({ eventID }: { eventID: string }) {

if (res.status == 400 || res.status == 500) {
checkedCodes.set(code, {
status: "invalid",
status: ScanningState.INVALID,
checkedAt: Date.now(),
});
} else {
checkedCodes.set(code, {
status: data.hasBeenUsed ? "used" : "valid",
status: data.hasBeenUsed
? ScanningState.USED
: ScanningState.VALID,
ticketData: data,
checkedAt: Date.now(),
});
}
} catch {
checkedCodes.set(code, {
status: "invalid",
status: ScanningState.INVALID,
checkedAt: Date.now(),
});
}
Expand Down Expand Up @@ -229,10 +240,10 @@ export default function Scanner({ eventID }: { eventID: string }) {

if (
code.boundingBox.width * code.boundingBox.height >
largestCode.size
largestCode.size
) {
largestCode.size =
code.boundingBox.width * code.boundingBox.height;
largestCode.size = code.boundingBox.width *
code.boundingBox.height;
largestCode.code = code;
}
}
Expand All @@ -249,7 +260,7 @@ export default function Scanner({ eventID }: { eventID: string }) {

if (!checkedCodes.has(code.rawValue)) {
checkedCodes.set(code.rawValue, {
status: "loading",
status: ScanningState.LOADING,
checkedAt: Date.now(),
});

Expand All @@ -263,16 +274,15 @@ export default function Scanner({ eventID }: { eventID: string }) {

const codeData = checkedCodes.get(code.rawValue)!;

const ticketObj = {
code: code.rawValue,
const ticketObj: TicketState = {
status: codeData.status,
ticketData: Object.hasOwn(codeData, "ticketData")
? (codeData as { ticketData: Ticket }).ticketData
: null,
};
checkedAt: codeData.checkedAt,
} as TicketState;

if (currentTicket.value != ticketObj) {
// @ts-expect-error Types be like
currentTicket.value = ticketObj;
}

Expand All @@ -296,47 +306,30 @@ export default function Scanner({ eventID }: { eventID: string }) {
bottomY = Math.max(bottomY, point.y);
}

const padding = 20;
const canvasArea = canvas.width * canvas.height;
const codeArea = largestCode.size;

const ratio = codeArea / canvasArea;

// TODO: @lukas add all of your'e dum scaling stuff here

const padding = 16;

leftX -= padding;
rightX += padding;

topY -= padding;
bottomY += padding;

ctx.lineWidth = 5;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.roundRect(leftX, topY, rightX - leftX, bottomY - topY, 20);
ctx.stroke();
ctx.closePath();

switch (codeData.status) {
case "loading": {
updateStringIfChanged("Loading...");
break;
}

case "invalid": {
updateStringIfChanged("Invalid code!");
break;
}

case "valid": {
updateStringIfChanged("Scan ticket");
break;
}

case "used": {
updateStringIfChanged("Ticket already used!");
break;
}

case "inactive": {
updateStringIfChanged("Unactivated ticket!");
break;
}
}
scanningState.value = codeData.status;
} else {
scanningState.value = ScanningState.READY;
currentTicket.value = null;
}
}
Expand Down Expand Up @@ -387,17 +380,17 @@ export default function Scanner({ eventID }: { eventID: string }) {
className={` h-max bg-gray-200 max-h-[70vh] w-max max-w-full transition-all ${
isCameraSwitching.value && "blur brightness-90"
}`}
></canvas>
>
</canvas>
{/* Camera switching */}
<div class="absolute top-4 right-4">
{cameraIds.value.length === 1 && (
<button
class=""
onClick={() => {
currentCamera.value =
cameraIds.value.find(
({ deviceId }) => deviceId !== currentCamera.value,
)?.deviceId || "";
currentCamera.value = cameraIds.value.find(
({ deviceId }) => deviceId !== currentCamera.value,
)?.deviceId || "";
}}
>
<CameraRotate class="size-6 text-white" />
Expand Down
18 changes: 18 additions & 0 deletions islands/events/scanning/scanning.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Ticket } from "@/utils/db/kv.types.ts";

export enum ScanningState {
LOADING = 'loading',
READY = 'ready',
INVALID = 'invalid',
VALID = 'valid',
USED = 'used',
INACTIVE = 'inactive',
}

export type TicketState =
| { status: ScanningState.LOADING | ScanningState.INVALID; checkedAt: number }
| {
status: ScanningState.VALID | ScanningState.USED | ScanningState.INACTIVE;
ticketData: Ticket;
checkedAt: number;
};
2 changes: 0 additions & 2 deletions routes/api/events/ticket/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ export const handler: Handlers = {
});
}

const showTime = event.value.showTimes.find((time) => time.id === showTimeID)

const deletion = await kv
.atomic()
.delete(["ticket", eventID, showTimeID, ticketID])
Expand Down
2 changes: 1 addition & 1 deletion routes/events/(pages)/attending/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TicketContext } from "@/routes/events/(pages)/attending/_layout.tsx";
import { defineRoute, RouteContext } from "$fresh/server.ts";
import EventHeader from "@/components/layout/eventEditNavbar.tsx";
import Scanner from "@/islands/events/scanning.tsx";
import Scanner from "../../../../islands/events/scanning/index.tsx";
import { badEventRequest } from "@/routes/events/[id]/_layout.tsx";
import ImagekitImage from "@/components/imagekitimg.tsx";
import CTA from "@/components/buttons/cta.tsx";
Expand Down
2 changes: 1 addition & 1 deletion routes/events/[id]/scanning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
badEventRequest,
EventContext,
} from "@/routes/events/[id]/_layout.tsx";
import Scanner from "@/islands/events/scanning.tsx";
import Scanner from "../../../islands/events/scanning/index.tsx";
import EventHeader from "@/components/layout/eventEditNavbar.tsx";

export default defineRoute((req, ctx: RouteContext<void, EventContext>) => {
Expand Down

0 comments on commit 90b3111

Please sign in to comment.