Skip to content

Commit

Permalink
Merge pull request #33 from portapack-mayhem/button_disable
Browse files Browse the repository at this point in the history
Fixed local cors issue
  • Loading branch information
jLynx authored Jan 14, 2024
2 parents 0f1552a + a5b1d3d commit 72e068b
Show file tree
Hide file tree
Showing 17 changed files with 221 additions and 49 deletions.
1 change: 1 addition & 0 deletions functions/api/fetch_nightly_firmware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,HEAD,POST,PUT,OPTIONS,DELETE",
"Access-Control-Allow-Headers": "*",
"Access-Control-Expose-Headers": "*",
"Access-Control-Max-Age": "86400",
};

Expand Down
1 change: 1 addition & 0 deletions functions/api/fetch_stable_firmware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,HEAD,POST,PUT,OPTIONS,DELETE",
"Access-Control-Allow-Headers": "*",
"Access-Control-Expose-Headers": "*",
"Access-Control-Max-Age": "86400",
};

Expand Down
63 changes: 63 additions & 0 deletions functions/api/get_versions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,HEAD,POST,PUT,OPTIONS,DELETE",
"Access-Control-Allow-Headers": "*",
"Access-Control-Expose-Headers": "*",
"Access-Control-Max-Age": "86400",
};

export const onRequestGet: PagesFunction = async (context) => {
const convertNightlyString = (nightlyTag: string) => {
const parts = nightlyTag.split("-");

// We expect the input to be 'nightly-tag-YYYY-MM-DD' format
const year = parts[2].slice(2); // remove '20' prefix from the year
const month = parts[3];
const day = parts[4];

return `n_${year}${month}${day}`;
};

let apiUrl =
"https://api.github.com/repos/portapack-mayhem/mayhem-firmware/releases";

let apiResponse = await fetch(apiUrl, {
method: "GET",
headers: { "User-Agent": "portapack-mayhem" },
});

if (!apiResponse.ok) {
throw new Error(`HTTP error! status: ${apiResponse.status}`);
}

let apiData: any = await apiResponse.json();

const latestNightlyObject = apiData.find(
(item: any) => item.prerelease === true
);
const nightlyVersion = convertNightlyString(latestNightlyObject.tag_name);

const latestStableObject = apiData.find(
(item: any) => item.prerelease === false
);

const data = {
stable: {
version: latestStableObject.tag_name,
published_at: latestStableObject.published_at,
},
nightly: {
version: nightlyVersion,
published_at: latestNightlyObject.published_at,
},
};

const json = JSON.stringify(data);

return new Response(json, {
headers: {
...corsHeaders,
"content-type": "application/json;charset=UTF-8",
},
});
};
9 changes: 9 additions & 0 deletions src/app/models.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export interface LatestVersions {
stable: VersionDetails;
nightly: VersionDetails;
}

export interface VersionDetails {
version: string;
published_at: string;
}
6 changes: 3 additions & 3 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"use client";

import dynamic from "next/dynamic";
import Controller from "./components/Controller/Controller";
import { Loader } from "./components/Loader/Loader";
import Controller from "@/components/Controller/Controller";
import { Loader } from "@/components/Loader/Loader";

const Home = () => {
const SerialLoader = dynamic(
async () => await import("./components/SerialLoader/SerialLoader"),
async () => await import("@/components/SerialLoader/SerialLoader"),
{
loading: () => <Loader />,
ssr: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
"use client";

import React, { ChangeEvent, useEffect, useRef, useState } from "react";
import { parseDirectories } from "@/app/utils/fileUtils";
import { downloadFileFromUrl, useWriteCommand } from "@/app/utils/serialUtils";
import { LatestVersions } from "@/app/models";
import { parseDirectories } from "@/utils/fileUtils";
import { downloadFileFromUrl, useWriteCommand } from "@/utils/serialUtils";
import {
getVersionLink,
getVersionType,
nightlyVersionFormat,
} from "@/utils/versionUtils";
import { DeviceButtons } from "../DeviceButtons/DeviceButtons";
import { FileBrowser, FileStructure } from "../FileBrowser/FileBrowser";
import HotkeyButton from "../HotkeyButton/HotkeyButton";
Expand All @@ -25,6 +31,7 @@ const Controller = () => {
const [firmwarModalOpen, setFirmwarModalOpen] = useState<boolean>(false);
const [setupComplete, setSetupComplete] = useState<boolean>(false);
const [dirStructure, setDirStructure] = useState<FileStructure[]>();
const [latestVersion, setLatestVersion] = useState<LatestVersions>();
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
const firmwareFileInputRef = useRef<HTMLInputElement>(null);
Expand Down Expand Up @@ -73,6 +80,8 @@ const Controller = () => {

setConsoleMessageList("");
setSetupComplete(true);

setLatestVersion(await getLatestVersions());
};

const fetchFolderStructure = async () => {
Expand All @@ -91,6 +100,16 @@ const Controller = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [serial]);

const getLatestVersions = async () => {
const apiResponse = await fetch("https://hackrf.app/api/get_versions");

if (!apiResponse.ok) {
console.error("Network response was not ok");
}

return await apiResponse.json<LatestVersions>();
};

const renderFrame = () => {
const width = 241;
const height = 321;
Expand Down Expand Up @@ -209,7 +228,7 @@ const Controller = () => {
}
};

const flashLatestFirmware = async () => {
const flashLatestNightlyFirmware = async () => {
const fileBlob = await downloadFileFromUrl(
"https://hackrf.app/api/fetch_nightly_firmware"
);
Expand Down Expand Up @@ -333,6 +352,7 @@ const Controller = () => {
<input
ref={firmwareFileInputRef}
type="file"
accept=".tar"
style={{ display: "none" }}
onClick={() => {
if (fileInputRef.current) {
Expand Down Expand Up @@ -412,39 +432,76 @@ const Controller = () => {
closeModal={() => setFirmwarModalOpen(false)}
className="w-[40%]"
>
<div className="flex flex-col gap-3">
<p>Select from the available options</p>
<button
disabled={disableTransmitAction}
onClick={() => flashLatestFirmware()}
className="rounded bg-blue-400 p-2 text-white disabled:opacity-50"
>
Update to latest nightly release
</button>
<button
disabled={disableTransmitAction}
onClick={() => {
setSelectedUploadFolder("/FIRMWARE");
firmwareFileInputRef.current?.click();
}}
className="rounded bg-blue-400 p-2 text-white disabled:opacity-50"
>
Flash custom firmware
</button>
<button
onClick={() => flashLatestFirmware()}
// disabled={disableTransmitAction}
disabled={true} // This is disabled as there is no stable firmware that will work with the current version of the webapp
className="rounded bg-blue-400 p-2 text-white disabled:opacity-50"
>
Update to latest stable release
</button>
<textarea
className="h-full w-full rounded bg-gray-200 p-2 text-black"
readOnly
value={updateStatus}
/>
</div>
{nightlyVersionFormat(deviceVersion) < 240114 &&
getVersionType(deviceVersion) == "nightly" ? (
<p>
sorry your version is too old. Please manually update to the latest
nightly
</p>
) : (
<div className="flex flex-col gap-3">
<p>
Current installed version:{" "}
<a
className="text-blue-300 underline transition-colors duration-200 hover:text-blue-400"
href={getVersionLink(deviceVersion)}
target="_blank"
>
{deviceVersion} - {getVersionType(deviceVersion)}
</a>
</p>
<div className="flex flex-col gap-1">
<p>
Latest Stable:{" "}
<a
className="text-blue-300 underline transition-colors duration-200 hover:text-blue-400"
href={getVersionLink(latestVersion?.stable.version)}
target="_blank"
>
{latestVersion?.stable.version}
</a>
</p>
<p>
Latest Nightly:{" "}
<a
className="text-blue-300 underline transition-colors duration-200 hover:text-blue-400"
href={getVersionLink(latestVersion?.nightly.version)}
target="_blank"
>
{latestVersion?.nightly.version}
</a>
</p>
</div>

<p>Select from the available options</p>
<button
disabled={disableTransmitAction}
onClick={() => flashLatestNightlyFirmware()}
className="rounded bg-blue-400 p-2 text-white disabled:opacity-50"
>
Update to latest nightly release
</button>
<button
disabled={disableTransmitAction}
onClick={() => {
setSelectedUploadFolder("/FIRMWARE");
firmwareFileInputRef.current?.click();
}}
className="rounded bg-blue-400 p-2 text-white disabled:opacity-50"
>
Flash custom firmware
</button>
<button
onClick={() => flashLatestNightlyFirmware()}
// disabled={disableTransmitAction}
disabled={true} // This is disabled as there is no stable firmware that will work with the current version of the webapp
className="rounded bg-blue-400 p-2 text-white disabled:opacity-50"
>
Update to latest stable release
</button>
<p>{updateStatus}</p>
</div>
)}
</Modal>
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect } from "react";
import { useWriteCommand } from "@/app/utils/serialUtils";
import { useWriteCommand } from "@/utils/serialUtils";
import HotkeyButton from "../HotkeyButton/HotkeyButton";

export const DeviceButtons = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Dispatch, RefObject, SetStateAction, useState } from "react";
import { parseDirectories } from "@/app/utils/fileUtils";
import { useWriteCommand } from "@/app/utils/serialUtils";
import { parseDirectories } from "@/utils/fileUtils";
import { useWriteCommand } from "@/utils/serialUtils";

// Define FileType
export type FileType = "file" | "folder";
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
8 changes: 1 addition & 7 deletions src/app/utils/serialUtils.tsx → src/utils/serialUtils.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
Dispatch,
SetStateAction,
useCallback,
useEffect,
useState,
} from "react";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { hexToBytes } from "./fileUtils";
import { useSerial } from "../components/SerialLoader/SerialLoader";
import { DataPacket } from "../components/SerialProvider/SerialProvider";
Expand Down
47 changes: 47 additions & 0 deletions src/utils/versionUtils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
type Version = "stable" | "nightly" | "custom" | "unknown";

export const nightlyVersionFormat = (input: string): number => {
const removedPrefix = input.replace("n_", "");
const number = parseInt(removedPrefix);
return number;
};

const nightlyToDate = (input: string): string => {
const prefixRemoved = input.replace("n_", "");

const year = "20" + prefixRemoved.slice(0, 2);
const month = prefixRemoved.slice(2, 4);
const day = prefixRemoved.slice(4, 8);

return `${year}-${month}-${day}`;
};

export const getVersionType = (versionString: string): Version => {
const stableRegex = /^v?\d+\.\d+\.\d+$/;
const nightlyRegex = /^n_\d+$/;
const customRegex = /^[a-f0-9]+$/;

if (stableRegex.test(versionString)) {
return "stable";
} else if (nightlyRegex.test(versionString)) {
return "nightly";
} else if (customRegex.test(versionString)) {
return "custom";
} else {
return "unknown";
}
};

export const getVersionLink = (versionString: string = ""): string => {
const type = getVersionType(versionString);
if (type === "stable") {
return `https://github.com/portapack-mayhem/mayhem-firmware/releases/tag/${versionString}`;
} else if (type === "nightly") {
return `https://github.com/portapack-mayhem/mayhem-firmware/releases/tag/nightly-tag-${nightlyToDate(
versionString
)}`;
} else if (type === "custom") {
return `https://github.com/portapack-mayhem/mayhem-firmware/commit/${versionString}`;
}
return "";
};

0 comments on commit 72e068b

Please sign in to comment.