Haystack/frontend/src/ProtectedRoute.tsx

69 lines
2.1 KiB
TypeScript

import { Navigate } from "@solidjs/router";
import { platform } from "@tauri-apps/plugin-os";
import { jwtDecode } from "jwt-decode";
import { type Component, type ParentProps, Show, useContext } from "solid-js";
import { save_token } from "tauri-plugin-ios-shared-token-api";
import { Notifications, NotificationsContext } from "./notifications";
import { useSearchImageContext } from "./contexts/SearchImageContext";
export const isTokenValid = (): boolean => {
const token = localStorage.getItem("access");
if (token == null) {
return false;
}
try {
jwtDecode(token);
return true;
} catch (err) {
return false;
}
};
const WithNotifications: Component<ParentProps> = (props) => {
const { onRefetchImages } = useSearchImageContext();
const notifications = Notifications(onRefetchImages);
return (
<NotificationsContext.Provider value={notifications}>
{props.children}
</NotificationsContext.Provider>
);
};
export const useNotifications = () => {
const notifications = useContext(NotificationsContext);
if (notifications == null) {
throw new Error("Notifications must be defined when using this hook");
}
return notifications;
};
export const ProtectedRoute: Component<ParentProps> = (props) => {
const isValid = isTokenValid();
if (isValid) {
const token = localStorage.getItem("access");
if (token == null) {
throw new Error("unreachable");
}
if (platform() === "ios") {
// iOS share extension is a seperate process to the App.
// Therefore, we need to share our access token somewhere both the App & Share Extension can access
// This involves App Groups.
save_token(token)
.then(() => console.log("Saved token!!!"))
.catch((e) => console.error(e));
}
}
return (
<Show when={isValid} fallback={<Navigate href="/login" />}>
<WithNotifications>{props.children}</WithNotifications>
</Show>
);
};