mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 00:36:31 +02:00
Merge upstream/dev into feat/kb-export-and-folder-upload
This commit is contained in:
commit
c30cc08771
61 changed files with 2670 additions and 1474 deletions
108
surfsense_web/lib/desktop-download-utils.ts
Normal file
108
surfsense_web/lib/desktop-download-utils.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import { useEffect, useMemo, useState } from "react";
|
||||
|
||||
export type OSInfo = {
|
||||
os: "macOS" | "Windows" | "Linux";
|
||||
arch: "arm64" | "x64";
|
||||
};
|
||||
|
||||
export function useUserOS(): OSInfo {
|
||||
const [info, setInfo] = useState<OSInfo>({ os: "macOS", arch: "arm64" });
|
||||
useEffect(() => {
|
||||
const ua = navigator.userAgent;
|
||||
let os: OSInfo["os"] = "macOS";
|
||||
let arch: OSInfo["arch"] = "x64";
|
||||
|
||||
if (/Windows/i.test(ua)) {
|
||||
os = "Windows";
|
||||
arch = "x64";
|
||||
} else if (/Linux/i.test(ua)) {
|
||||
os = "Linux";
|
||||
arch = "x64";
|
||||
} else {
|
||||
os = "macOS";
|
||||
arch = /Mac/.test(ua) && !/Intel/.test(ua) ? "arm64" : "arm64";
|
||||
}
|
||||
|
||||
const uaData = (navigator as Navigator & { userAgentData?: { architecture?: string } })
|
||||
.userAgentData;
|
||||
if (uaData?.architecture === "arm") arch = "arm64";
|
||||
else if (uaData?.architecture === "x86") arch = "x64";
|
||||
|
||||
setInfo({ os, arch });
|
||||
}, []);
|
||||
return info;
|
||||
}
|
||||
|
||||
export interface ReleaseAsset {
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export function useLatestRelease() {
|
||||
const [assets, setAssets] = useState<ReleaseAsset[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const controller = new AbortController();
|
||||
fetch("https://api.github.com/repos/MODSetter/SurfSense/releases/latest", {
|
||||
signal: controller.signal,
|
||||
})
|
||||
.then((r) => r.json())
|
||||
.then((data) => {
|
||||
if (data?.assets) {
|
||||
setAssets(
|
||||
data.assets
|
||||
.filter((a: { name: string }) => /\.(exe|dmg|AppImage|deb)$/.test(a.name))
|
||||
.map((a: { name: string; browser_download_url: string }) => ({
|
||||
name: a.name,
|
||||
url: a.browser_download_url,
|
||||
}))
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
return () => controller.abort();
|
||||
}, []);
|
||||
|
||||
return assets;
|
||||
}
|
||||
|
||||
export const ASSET_LABELS: Record<string, string> = {
|
||||
".exe": "Windows (exe)",
|
||||
"-arm64.dmg": "macOS Apple Silicon (dmg)",
|
||||
"-x64.dmg": "macOS Intel (dmg)",
|
||||
"-arm64.zip": "macOS Apple Silicon (zip)",
|
||||
"-x64.zip": "macOS Intel (zip)",
|
||||
".AppImage": "Linux (AppImage)",
|
||||
".deb": "Linux (deb)",
|
||||
};
|
||||
|
||||
export function getAssetLabel(name: string): string {
|
||||
for (const [suffix, label] of Object.entries(ASSET_LABELS)) {
|
||||
if (name.endsWith(suffix)) return label;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
export const GITHUB_RELEASES_URL = "https://github.com/MODSetter/SurfSense/releases/latest";
|
||||
|
||||
export function usePrimaryDownload() {
|
||||
const { os, arch } = useUserOS();
|
||||
const assets = useLatestRelease();
|
||||
|
||||
const { primary, alternatives } = useMemo(() => {
|
||||
if (assets.length === 0) return { primary: null, alternatives: [] };
|
||||
|
||||
const matchers: Record<string, (n: string) => boolean> = {
|
||||
Windows: (n) => n.endsWith(".exe"),
|
||||
macOS: (n) => n.endsWith(`-${arch}.dmg`),
|
||||
Linux: (n) => n.endsWith(".AppImage"),
|
||||
};
|
||||
|
||||
const match = matchers[os];
|
||||
const primary = assets.find((a) => match(a.name)) ?? null;
|
||||
const alternatives = assets.filter((a) => a !== primary);
|
||||
return { primary, alternatives };
|
||||
}, [assets, os, arch]);
|
||||
|
||||
return { os, arch, assets, primary, alternatives };
|
||||
}
|
||||
|
|
@ -92,6 +92,10 @@ export const cacheKeys = {
|
|||
publicChat: {
|
||||
byToken: (shareToken: string) => ["public-chat", shareToken] as const,
|
||||
},
|
||||
github: {
|
||||
repoStars: (username: string, repo: string) =>
|
||||
["github", "repo-stars", username, repo] as const,
|
||||
},
|
||||
publicChatSnapshots: {
|
||||
all: ["public-chat-snapshots"] as const,
|
||||
bySearchSpace: (searchSpaceId: number) =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue