revalidate config changes, check on focus changes

pull/302/head
Ben Phelps 2 years ago
parent 5f0c1ec70a
commit c980c70798

@ -0,0 +1,27 @@
import { join } from "path";
import { createHash } from "crypto";
import { readFileSync } from "fs";
import checkAndCopyConfig from "utils/config/config";
const configs = ["docker.yaml", "settings.yaml", "services.yaml", "bookmarks.yaml"];
function hash(buffer) {
const hashSum = createHash("sha256");
hashSum.update(buffer);
return hashSum.digest("hex");
}
export default async function handler(req, res) {
const hashes = configs.map((config) => {
checkAndCopyConfig(config);
const configYaml = join(process.cwd(), "config", config);
return hash(readFileSync(configYaml, "utf8"));
});
const combinedHash = hash(hashes.join(""));
res.send({
hash: combinedHash,
});
}

@ -3,7 +3,7 @@ import useSWR, { SWRConfig } from "swr";
import Head from "next/head";
import dynamic from "next/dynamic";
import { useTranslation } from "next-i18next";
import { useEffect, useContext } from "react";
import { useEffect, useContext, useState } from "react";
import { BiError } from "react-icons/bi";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
@ -17,6 +17,7 @@ import { ColorContext } from "utils/contexts/color";
import { ThemeContext } from "utils/contexts/theme";
import { SettingsContext } from "utils/contexts/settings";
import { bookmarksResponse, servicesResponse, widgetsResponse } from "utils/config/api-response";
import useWindowFocus from "utils/hooks/window-focus";
const ThemeToggle = dynamic(() => import("components/toggles/theme"), {
ssr: false,
@ -49,6 +50,7 @@ export async function getStaticProps() {
"/api/services": services,
"/api/bookmarks": bookmarks,
"/api/widgets": widgets,
"/api/hash": false,
},
...(await serverSideTranslations(settings.language ?? "en")),
},
@ -67,7 +69,47 @@ export async function getStaticProps() {
}
export default function Index({ initialSettings, fallback }) {
const windowFocused = useWindowFocus();
const [stale, setStale] = useState(false);
const { data: errorsData } = useSWR("/api/validate");
const { data: hashData, mutate: mutateHash } = useSWR("/api/hash");
useEffect(() => {
if (windowFocused) {
mutateHash();
}
}, [windowFocused, mutateHash]);
useEffect(() => {
if (hashData) {
if (typeof window !== "undefined") {
const previousHash = localStorage.getItem("hash");
if (!previousHash) {
localStorage.setItem("hash", hashData.hash);
}
if (previousHash && previousHash !== hashData.hash) {
setStale(true);
localStorage.setItem("hash", hashData.hash);
fetch("/api/revalidate").then((res) => {
if (res.ok) {
window.location.reload();
}
});
}
}
}
}, [hashData]);
if (stale) {
return (
<div className="flex items-center justify-center h-screen">
<div className="w-24 h-24 border-2 border-theme-400 border-solid rounded-full animate-spin border-t-transparent" />
</div>
);
}
if (errorsData && errorsData.length > 0) {
return (

@ -0,0 +1,26 @@
import { useState, useEffect } from "react";
const hasFocus = () => typeof document !== "undefined" && document.hasFocus();
const useWindowFocus = () => {
const [focused, setFocused] = useState(hasFocus);
useEffect(() => {
setFocused(hasFocus());
const onFocus = () => setFocused(true);
const onBlur = () => setFocused(false);
window.addEventListener("focus", onFocus);
window.addEventListener("blur", onBlur);
return () => {
window.removeEventListener("focus", onFocus);
window.removeEventListener("blur", onBlur);
};
}, []);
return focused;
};
export default useWindowFocus;
Loading…
Cancel
Save