Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Sam Heinz
2025-05-13 00:58:31 +10:00
244 changed files with 7969 additions and 5013 deletions
@@ -64,7 +64,7 @@ export default function Buttons({ item }: { item: Script }) {
icon: <Code className="h-4 w-4" />,
text: "Install Source",
},
updateSourceUrl && {
updateSourceUrl && item.updateable && {
href: updateSourceUrl,
icon: <RefreshCcw className="h-4 w-4" />,
text: "Update Source",
+67 -18
View File
@@ -8,7 +8,7 @@ import {
} from "@/components/ui/command";
import { basePath } from "@/config/siteConfig";
import { fetchCategories } from "@/lib/data";
import { Category } from "@/lib/types";
import { Category, Script } from "@/lib/types";
import { cn } from "@/lib/utils";
import Image from "next/image";
import { useRouter } from "next/navigation";
@@ -16,6 +16,10 @@ import React from "react";
import { Badge } from "./ui/badge";
import { Button } from "./ui/button";
import { DialogTitle } from "./ui/dialog";
import { Sparkles } from "lucide-react";
import { TooltipContent, TooltipProvider } from "./ui/tooltip";
import { TooltipTrigger } from "./ui/tooltip";
import { Tooltip } from "./ui/tooltip";
export const formattedBadge = (type: string) => {
switch (type) {
@@ -31,11 +35,19 @@ export const formattedBadge = (type: string) => {
return null;
};
// random Script
function getRandomScript(categories: Category[]): Script | null {
const allScripts = categories.flatMap((cat) => cat.scripts || []);
if (allScripts.length === 0) return null;
const idx = Math.floor(Math.random() * allScripts.length);
return allScripts[idx];
}
export default function CommandMenu() {
const [open, setOpen] = React.useState(false);
const [links, setLinks] = React.useState<Category[]>([]);
const router = useRouter();
const [isLoading, setIsLoading] = React.useState(false);
const router = useRouter();
React.useEffect(() => {
const down = (e: KeyboardEvent) => {
@@ -45,7 +57,6 @@ export default function CommandMenu() {
setOpen((open) => !open);
}
};
document.addEventListener("keydown", down);
return () => document.removeEventListener("keydown", down);
}, []);
@@ -63,23 +74,61 @@ export default function CommandMenu() {
});
};
const openRandomScript = async () => {
if (links.length === 0) {
setIsLoading(true);
try {
const categories = await fetchCategories();
setLinks(categories);
const randomScript = getRandomScript(categories);
if (randomScript) {
router.push(`/scripts?id=${randomScript.slug}`);
}
} finally {
setIsLoading(false);
}
} else {
const randomScript = getRandomScript(links);
if (randomScript) {
router.push(`/scripts?id=${randomScript.slug}`);
}
}
};
return (
<>
<Button
variant="outline"
className={cn(
"relative h-9 w-full justify-start rounded-[0.5rem] bg-muted/50 text-sm font-normal text-muted-foreground shadow-none sm:pr-12 md:w-40 lg:w-64",
)}
onClick={() => {
fetchSortedCategories();
setOpen(true);
}}
>
<span className="inline-flex">Search scripts...</span>
<kbd className="pointer-events-none absolute right-[0.3rem] top-[0.45rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex">
<span className="text-xs"></span>K
</kbd>
</Button>
<div className="flex gap-2">
<Button
variant="outline"
className={cn(
"relative h-9 w-full justify-start rounded-[0.5rem] bg-muted/50 text-sm font-normal text-muted-foreground shadow-none sm:pr-12 md:w-40 lg:w-64",
)}
onClick={() => {
fetchSortedCategories();
setOpen(true);
}}
>
<span className="inline-flex">Search scripts...</span>
<kbd className="pointer-events-none absolute right-[0.3rem] top-[0.45rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex">
<span className="text-xs"></span>K
</kbd>
</Button>
<TooltipProvider>
<Tooltip delayDuration={100}>
<TooltipTrigger asChild>
<Button variant="outline" size="icon" onClick={openRandomScript} disabled={isLoading} className="hidden lg:flex">
<Sparkles className="size-4" />
<span className="sr-only">Open Random Script</span>
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Open Random Script</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
<CommandDialog open={open} onOpenChange={setOpen}>
<DialogTitle className="sr-only">Search scripts</DialogTitle>
<CommandInput placeholder="Search for a script..." />
+1 -1
View File
@@ -12,7 +12,7 @@ export default function Footer() {
<p>
Website built by the community. The source code is available on{" "}
<Link
href={`https://github.com/community-scripts/${basePath}/frontend`}
href={`https://github.com/community-scripts/${basePath}/tree/main/frontend`}
target="_blank"
rel="noreferrer"
className="font-semibold underline-offset-2 duration-300 hover:underline"
@@ -41,8 +41,8 @@ export default function CodeCopyButton({
return (
<div className="mt-4 flex">
<Card className="flex items-center overflow-x-auto bg-primary-foreground pl-4">
<div className="overflow-x-auto whitespace-pre-wrap text-nowrap break-all pr-4 text-sm">
<Card className="flex items-center overflow-x-auto bg-primary-foreground pl-4 [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-muted-foreground/20">
<div className="overflow-x-auto whitespace-pre-wrap text-nowrap break-all pr-4 text-sm [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-muted-foreground/20">
{!isMobile && children ? children : "Copy install command"}
</div>
<button
+5
View File
@@ -34,4 +34,9 @@ export const FAQ_Items = [
content:
"If an LXC script fails, run it again using Verbose mode. Standard mode hides detailed output for neatness, showing only progress. Verbose mode displays all messages, which helps you (and us) diagnose the error. Include this verbose output if you report the issue.",
},
{
title: "What does \"Updatable\" and \"Not updatable\" mean?",
content:
"Updatable means that script has a function that is used to update the installed application to the latest version available. Not updatable means that script doesn't have a function that can safely update the application to the latest version available, so only the LXC OS is updated.",
},
];