mirror of
https://github.com/TautvydasDerzinskas/Thingport.git
synced 2026-10-18 20:59:55 -05:00
fix: adjust downloads page
This commit is contained in:
1 parent
e78c7c20ac
commit
58c773b955
10 files changed
+135
-116
No files matched your search
@@ -3,7 +3,7 @@ import { prisma } from "../db";
|
||||
// Slicers that register their own URL protocol for opening a remote model directly (e.g.
|
||||
// bambustudio://) -- the only ones worth offering here, since the whole point of this preference
|
||||
// is a future "open in {slicer}" launch via that protocol. Anything else falls under "other".
|
||||
export const SLICER_IDS = ["bambustudio", "orcaslicer", "prusaslicer", "other"] as const;
|
||||
export const SLICER_IDS = ["bambustudio", "orcaslicer", "prusaslicer", "crealityprintlink", "other"] as const;
|
||||
export type SlicerId = (typeof SLICER_IDS)[number];
|
||||
|
||||
function isSlicerId(value: string): value is SlicerId {
|
||||
|
||||
@@ -139,7 +139,7 @@ function AppShell({
|
||||
path="/profile/password"
|
||||
element={<ChangePasswordPage onUnauthorized={onUnauthorized} />}
|
||||
/>
|
||||
<Route path="/download" element={<DownloadPage />} />
|
||||
<Route path="/downloads" element={<DownloadPage />} />
|
||||
<Route
|
||||
path="/admin-settings"
|
||||
element={
|
||||
|
||||
@@ -74,9 +74,9 @@ function useRouteChrome() {
|
||||
} else if (path === "/profile") {
|
||||
title = t("profile.title");
|
||||
onBack = () => navigate(-1);
|
||||
} else if (path === "/download") {
|
||||
} else if (path === "/downloads") {
|
||||
// Overridden by DownloadPage's usePageHeader once translations resolve.
|
||||
title = t("sidebar.downloadBridge");
|
||||
title = t("sidebar.downloads");
|
||||
onBack = () => navigate("/");
|
||||
} else if (path.startsWith("/admin-settings")) {
|
||||
title = t("adminSettings.pageTitle");
|
||||
|
||||
@@ -58,7 +58,7 @@ type Props = {
|
||||
isAdmin: boolean;
|
||||
};
|
||||
|
||||
/** The persistent app-wide navigation rail: Dashboard, Models, Collections, Download Bridge, and
|
||||
/** The persistent app-wide navigation rail: Dashboard, Models, Collections, Downloads, and
|
||||
* (for admins) Administration. Folder browsing lives inside the Models page itself, not here. */
|
||||
export default function Sidebar({ isAdmin }: Props) {
|
||||
const { t } = useTranslation(["app", "common"]);
|
||||
@@ -73,7 +73,7 @@ export default function Sidebar({ isAdmin }: Props) {
|
||||
const onDashboard = location.pathname === "/";
|
||||
const onCollections = location.pathname.startsWith("/models/collections");
|
||||
const onModels = (location.pathname.startsWith("/models") && !onCollections) || location.pathname.startsWith("/authors");
|
||||
const onDownload = location.pathname.startsWith("/download");
|
||||
const onDownload = location.pathname.startsWith("/downloads");
|
||||
const onAdminSettings = location.pathname.startsWith("/admin-settings");
|
||||
const onAdminUsers = location.pathname.startsWith("/admin-users");
|
||||
const onAdminLogs = location.pathname.startsWith("/admin-logs");
|
||||
@@ -189,20 +189,20 @@ export default function Sidebar({ isAdmin }: Props) {
|
||||
{collapsed ? (
|
||||
<CollapsedNavIcon
|
||||
icon={<DownloadIcon fontSize="small" />}
|
||||
label={t("sidebar.downloadBridge")}
|
||||
label={t("sidebar.downloads")}
|
||||
selected={onDownload}
|
||||
onClick={() => navigate("/download")}
|
||||
onClick={() => navigate("/downloads")}
|
||||
/>
|
||||
) : (
|
||||
<ListItemButton
|
||||
selected={onDownload}
|
||||
onClick={() => navigate("/download")}
|
||||
onClick={() => navigate("/downloads")}
|
||||
sx={{ borderRadius: 1, mb: 0.5 }}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: 30 }}>
|
||||
<DownloadIcon fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={t("sidebar.downloadBridge")} primaryTypographyProps={{ variant: "body2" }} />
|
||||
<ListItemText primary={t("sidebar.downloads")} primaryTypographyProps={{ variant: "body2" }} />
|
||||
</ListItemButton>
|
||||
)}
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
// release, so they don't need updating when a new Bridge build ships.
|
||||
const BRIDGE_RELEASES_BASE = "https://github.com/TautvydasDerzinskas/print-stash/releases/latest/download";
|
||||
|
||||
export const BRIDGE_RELEASES_PAGE = "https://github.com/TautvydasDerzinskas/print-stash/releases";
|
||||
|
||||
export type BridgeDownload = { os: "windows" | "macos" | "linux"; label: string; asset: string };
|
||||
|
||||
export const BRIDGE_DOWNLOADS: BridgeDownload[] = [
|
||||
|
||||
@@ -2,11 +2,14 @@ export type SlicerOption = { id: string; label: string };
|
||||
|
||||
// Limited to slicers that register their own URL protocol for opening a remote model directly
|
||||
// (e.g. bambustudio://) -- the only ones a future "open in {slicer}" launch could actually use.
|
||||
// IDs must match backend's services/slicerPreferenceService.ts SLICER_IDS.
|
||||
// IDs must match backend's services/slicerPreferenceService.ts SLICER_IDS, and (id !== "other")
|
||||
// must equal the exact scheme the slicer registers -- e.g. Creality Print's is "crealityprintlink"
|
||||
// (crealityprintlink://open?file=...), not "creality", per its libslic3r/Utils.hpp.
|
||||
export const SLICER_OPTIONS: SlicerOption[] = [
|
||||
{ id: "bambustudio", label: "Bambu Studio" },
|
||||
{ id: "orcaslicer", label: "OrcaSlicer" },
|
||||
{ id: "prusaslicer", label: "PrusaSlicer" },
|
||||
{ id: "crealityprintlink", label: "Creality Print" },
|
||||
{ id: "other", label: "Other / Manual" },
|
||||
];
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
"foldersHeadingWithCount": "Folders ({{count}})",
|
||||
"models": "Models",
|
||||
"collections": "Collections",
|
||||
"downloadBridge": "Download Bridge"
|
||||
"downloads": "Downloads"
|
||||
},
|
||||
"uploadBar": {
|
||||
"uploading": "Uploading…",
|
||||
@@ -419,23 +419,25 @@
|
||||
"download": {
|
||||
"pageTitle": "PrintStash Bridge",
|
||||
"intro": "A small helper app that runs on your computer so \"Open in Slicer\" can hand a model straight to your slicer.",
|
||||
"why": "Bambu Studio's own bambustudio:// link only accepts files from a short allowlist of domains Bambu Lab controls, and a self-hosted PrintStash never qualifies -- so \"Open in Bambu Studio\" would otherwise do nothing. The Bridge listens on its own print-stash:// link instead, downloads the file itself, and hands it to Bambu Studio locally. OrcaSlicer and PrusaSlicer already accept links directly and don't need it.",
|
||||
"downloadHeading": "Download",
|
||||
"install": {
|
||||
"windows": "Run the downloaded .exe once (double-click is fine) -- it installs itself and registers the protocol.",
|
||||
"macos": "chmod +x it, remove the Gatekeeper quarantine flag (xattr -d com.apple.quarantine), then run it once with --install.",
|
||||
"linux": "Mark it executable (chmod +x) and run it once from a terminal."
|
||||
},
|
||||
"footerLinks": "Need the exact commands, or building from source? See the <releases>Bridge releases</releases> page.",
|
||||
"autostart": {
|
||||
"heading": "Run at startup (optional)",
|
||||
"windowsLinuxNote": "Not needed on Windows or Linux -- the OS launches the Bridge fresh, with the link's URL already attached, every time you click \"Open in Bambu Studio\". There's no background process to keep running.",
|
||||
"macosIntro": "Not required on macOS either, for the same reason -- it launches on demand even after a reboot. Adding it as a login item just means the very first click after starting up responds instantly instead of waiting about a second for the app to launch.",
|
||||
"macosGuiHeading": "Easiest: System Settings",
|
||||
"macosGuiSteps": "System Settings -> General -> Login Items & Extensions -> click + and add \"PrintStash Bridge\" from ~/Applications.",
|
||||
"macosLaunchAgentHeading": "Or, a LaunchAgent (for Terminal users)",
|
||||
"macosLaunchAgentIntro": "Save this as ~/Library/LaunchAgents/com.printstash.bridge.plist (replace YOUR_USERNAME with your actual username):",
|
||||
"macosLaunchAgentLoad": "Then load it:"
|
||||
"modal": {
|
||||
"startedNote": "Your download should start automatically. Follow these steps to finish installing:",
|
||||
"windows": {
|
||||
"heading": "Install on Windows",
|
||||
"step1": "Double-click the downloaded .exe (or run it with no arguments from a terminal). It installs itself and registers the protocol automatically."
|
||||
},
|
||||
"linux": {
|
||||
"heading": "Install on Linux",
|
||||
"step1": "If your file manager blocks execution, mark the file as executable first.",
|
||||
"step2": "Then run it once -- double-click, or from a terminal."
|
||||
},
|
||||
"macos": {
|
||||
"heading": "Install on macOS",
|
||||
"step1": "Make it executable.",
|
||||
"step2": "Remove the Gatekeeper quarantine flag -- downloaded files are quarantined automatically.",
|
||||
"step3": "Install it. This copies the app into ~/Applications and registers the print-stash:// link.",
|
||||
"note": "If macOS still refuses to run it, open System Settings -> Privacy & Security and allow it there instead."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
"foldersHeadingWithCount": "Aplankai ({{count}})",
|
||||
"models": "Modeliai",
|
||||
"collections": "Kolekcijos",
|
||||
"downloadBridge": "Atsisiųsti Bridge"
|
||||
"downloads": "Atsisiuntimai"
|
||||
},
|
||||
"uploadBar": {
|
||||
"uploading": "Įkeliama…",
|
||||
@@ -419,23 +419,25 @@
|
||||
"download": {
|
||||
"pageTitle": "PrintStash Bridge",
|
||||
"intro": "Nedidelė pagalbinė programa, veikianti jūsų kompiuteryje, kad „Atverti pjaustyklėje“ galėtų perduoti modelį tiesiai jūsų pjaustyklei.",
|
||||
"why": "Bambu Studio nuosava bambustudio:// nuoroda priima failus tik iš trumpo, Bambu Lab kontroliuojamo domenų sąrašo, o savarankiškai talpinamas PrintStash niekada jame nepasirodys -- todėl „Atverti Bambu Studio“ paprasčiausiai nieko nedarytų. Vietoje to Bridge klausosi savo print-stash:// nuorodos, pats atsisiunčia failą ir perduoda jį Bambu Studio vietoje. OrcaSlicer ir PrusaSlicer nuorodas priima tiesiogiai, todėl jiems Bridge nereikalingas.",
|
||||
"downloadHeading": "Atsisiųsti",
|
||||
"install": {
|
||||
"windows": "Vieną kartą paleiskite atsisiųstą .exe failą (užtenka dvigubo paspaudimo) -- jis pats įsidiegs ir užregistruos protokolą.",
|
||||
"macos": "Suteikite leidimą vykdyti (chmod +x), pašalinkite Gatekeeper karantino žymą (xattr -d com.apple.quarantine), tada vieną kartą paleiskite su --install.",
|
||||
"linux": "Pažymėkite kaip vykdomą (chmod +x) ir vieną kartą paleiskite iš terminalo."
|
||||
},
|
||||
"footerLinks": "Reikia tikslių komandų arba norite susikompiliuoti iš išeitinio kodo? Žr. <releases>Bridge leidimų</releases> puslapį.",
|
||||
"autostart": {
|
||||
"heading": "Automatinis paleidimas paleidžiant sistemą (nebūtina)",
|
||||
"windowsLinuxNote": "„Windows“ ar „Linux“ tai nereikalinga -- kiekvieną kartą paspaudus „Atverti Bambu Studio“, operacinė sistema paleidžia Bridge iš naujo, jau su nuorodos URL. Nėra jokio fone veikiančio proceso, kurį reikėtų palaikyti.",
|
||||
"macosIntro": "Tas pats galioja ir „macOS“ -- ji paleidžia programą pagal poreikį net ir po perkrovimo. Pridėjus ją kaip prisijungimo elementą, tiesiog pirmas paspaudimas po sistemos paleidimo įvyks akimirksniu, o ne po maždaug sekundės, kol programa pasileis.",
|
||||
"macosGuiHeading": "Paprasčiausia: sistemos nustatymai",
|
||||
"macosGuiSteps": "System Settings -> General -> Login Items & Extensions -> spauskite + ir pridėkite „PrintStash Bridge“ iš ~/Applications.",
|
||||
"macosLaunchAgentHeading": "Arba LaunchAgent (naudojantiems terminalą)",
|
||||
"macosLaunchAgentIntro": "Išsaugokite tai kaip ~/Library/LaunchAgents/com.printstash.bridge.plist (pakeiskite YOUR_USERNAME savo naudotojo vardu):",
|
||||
"macosLaunchAgentLoad": "Tada įkelkite jį:"
|
||||
"modal": {
|
||||
"startedNote": "Atsisiuntimas turėtų prasidėti automatiškai. Norėdami baigti diegimą, atlikite šiuos veiksmus:",
|
||||
"windows": {
|
||||
"heading": "Diegimas „Windows“",
|
||||
"step1": "Dukart spustelėkite atsisiųstą .exe failą (arba paleiskite jį be argumentų iš terminalo). Jis pats įsidiegs ir automatiškai užregistruos protokolą."
|
||||
},
|
||||
"linux": {
|
||||
"heading": "Diegimas „Linux“",
|
||||
"step1": "Jei failų tvarkyklė neleidžia vykdyti failo, pirmiausia pažymėkite jį kaip vykdomą.",
|
||||
"step2": "Tada vieną kartą jį paleiskite -- dukart spustelėję arba iš terminalo."
|
||||
},
|
||||
"macos": {
|
||||
"heading": "Diegimas „macOS“",
|
||||
"step1": "Suteikite leidimą vykdyti.",
|
||||
"step2": "Pašalinkite Gatekeeper karantino žymą -- atsisiųsti failai automatiškai pažymimi karantinu.",
|
||||
"step3": "Įdiekite jį. Tai nukopijuos programą į ~/Applications ir užregistruos print-stash:// nuorodą.",
|
||||
"note": "Jei „macOS“ vis tiek atsisako jį paleisti, atidarykite System Settings -> Privacy & Security ir leiskite jį ten."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,41 +1,25 @@
|
||||
import { useTranslation, Trans } from "react-i18next";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import Alert from "@mui/material/Alert";
|
||||
import Box from "@mui/material/Box";
|
||||
import Link from "@mui/material/Link";
|
||||
import Dialog from "@mui/material/Dialog";
|
||||
import DialogTitle from "@mui/material/DialogTitle";
|
||||
import DialogContent from "@mui/material/DialogContent";
|
||||
import DialogActions from "@mui/material/DialogActions";
|
||||
import DownloadIcon from "@mui/icons-material/Download";
|
||||
import LaptopWindowsIcon from "@mui/icons-material/LaptopWindows";
|
||||
import AppleIcon from "@mui/icons-material/Apple";
|
||||
import TerminalIcon from "@mui/icons-material/Terminal";
|
||||
import CableIcon from "@mui/icons-material/Cable";
|
||||
import { usePageHeader } from "../../components/Layout/PageHeaderContext";
|
||||
import { BRIDGE_DOWNLOADS, BRIDGE_RELEASES_PAGE, bridgeDownloadUrl } from "../../constants/bridge";
|
||||
import { BRIDGE_DOWNLOADS, bridgeDownloadUrl, type BridgeDownload } from "../../constants/bridge";
|
||||
|
||||
const OS_ICON = { windows: LaptopWindowsIcon, macos: AppleIcon, linux: TerminalIcon };
|
||||
|
||||
// launchd doesn't expand `~`, so the plist needs an absolute path -- the user has to swap in
|
||||
// their own username either way, since we can't know it here.
|
||||
const MACOS_LAUNCH_AGENT_PLIST = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.printstash.bridge</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/Users/YOUR_USERNAME/Applications/PrintStash Bridge.app/Contents/MacOS/print-stash-bridge</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>`;
|
||||
|
||||
const MACOS_LAUNCH_AGENT_LOAD_CMD = `mkdir -p ~/Library/LaunchAgents
|
||||
# save the file above as ~/Library/LaunchAgents/com.printstash.bridge.plist
|
||||
launchctl load ~/Library/LaunchAgents/com.printstash.bridge.plist`;
|
||||
type InstallStep = { text: string; code?: string };
|
||||
|
||||
function CodeBlock({ children }: { children: string }) {
|
||||
return (
|
||||
@@ -56,9 +40,60 @@ function CodeBlock({ children }: { children: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
function InstallSteps({ steps }: { steps: InstallStep[] }) {
|
||||
return (
|
||||
<Stack spacing={2}>
|
||||
{steps.map((step, i) => (
|
||||
<Stack key={i} direction="row" spacing={1.5}>
|
||||
<Box
|
||||
sx={{
|
||||
width: 22,
|
||||
height: 22,
|
||||
borderRadius: "50%",
|
||||
bgcolor: "primary.main",
|
||||
color: "primary.contrastText",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
fontSize: 12,
|
||||
fontWeight: 600,
|
||||
flexShrink: 0,
|
||||
mt: "1px",
|
||||
}}
|
||||
>
|
||||
{i + 1}
|
||||
</Box>
|
||||
<Box sx={{ flex: 1, minWidth: 0 }}>
|
||||
<Typography variant="body2">{step.text}</Typography>
|
||||
{step.code && <Box sx={{ mt: 1 }}><CodeBlock>{step.code}</CodeBlock></Box>}
|
||||
</Box>
|
||||
</Stack>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DownloadPage() {
|
||||
const { t } = useTranslation(["app", "common"]);
|
||||
usePageHeader({ title: t("sidebar.downloadBridge") });
|
||||
usePageHeader({ title: t("sidebar.downloads") });
|
||||
|
||||
const [installOs, setInstallOs] = useState<BridgeDownload["os"] | null>(null);
|
||||
|
||||
const installSteps: Record<BridgeDownload["os"], InstallStep[]> = {
|
||||
windows: [{ text: t("download.modal.windows.step1") }],
|
||||
linux: [
|
||||
{ text: t("download.modal.linux.step1"), code: "chmod +x print-stash-bridge-linux-amd64" },
|
||||
{ text: t("download.modal.linux.step2"), code: "./print-stash-bridge-linux-amd64" },
|
||||
],
|
||||
macos: [
|
||||
{ text: t("download.modal.macos.step1"), code: "chmod +x ~/Downloads/print-stash-bridge-macos" },
|
||||
{
|
||||
text: t("download.modal.macos.step2"),
|
||||
code: "xattr -d com.apple.quarantine ~/Downloads/print-stash-bridge-macos",
|
||||
},
|
||||
{ text: t("download.modal.macos.step3"), code: "~/Downloads/print-stash-bridge-macos --install" },
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack spacing={3} sx={{ maxWidth: 720 }}>
|
||||
@@ -70,10 +105,6 @@ export default function DownloadPage() {
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
<Alert severity="info" variant="outlined">
|
||||
<Typography variant="body2">{t("download.why")}</Typography>
|
||||
</Alert>
|
||||
|
||||
<Stack spacing={2}>
|
||||
<Typography variant="subtitle1" fontWeight={600}>{t("download.downloadHeading")}</Typography>
|
||||
<Stack direction={{ xs: "column", sm: "row" }} spacing={2}>
|
||||
@@ -84,15 +115,13 @@ export default function DownloadPage() {
|
||||
<Stack spacing={1.5} alignItems="flex-start">
|
||||
<Icon fontSize="large" />
|
||||
<Typography variant="subtitle2" fontWeight={600}>{label}</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{t(`download.install.${os}`)}
|
||||
</Typography>
|
||||
<Button
|
||||
component="a"
|
||||
href={bridgeDownloadUrl(asset)}
|
||||
variant="outlined"
|
||||
size="small"
|
||||
startIcon={<DownloadIcon fontSize="small" />}
|
||||
onClick={() => setInstallOs(os)}
|
||||
>
|
||||
{t("common:download")}
|
||||
</Button>
|
||||
@@ -103,42 +132,27 @@ export default function DownloadPage() {
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
<Stack spacing={1.5}>
|
||||
<Typography variant="subtitle1" fontWeight={600}>{t("download.autostart.heading")}</Typography>
|
||||
<Typography variant="body2" color="text.secondary">{t("download.autostart.windowsLinuxNote")}</Typography>
|
||||
<Typography variant="body2" color="text.secondary">{t("download.autostart.macosIntro")}</Typography>
|
||||
|
||||
<Paper variant="outlined" sx={{ p: 2 }}>
|
||||
<Typography variant="body2" fontWeight={600} sx={{ mb: 0.5 }}>
|
||||
{t("download.autostart.macosGuiHeading")}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">{t("download.autostart.macosGuiSteps")}</Typography>
|
||||
</Paper>
|
||||
|
||||
<Paper variant="outlined" sx={{ p: 2 }}>
|
||||
<Typography variant="body2" fontWeight={600} sx={{ mb: 0.5 }}>
|
||||
{t("download.autostart.macosLaunchAgentHeading")}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 1 }}>
|
||||
{t("download.autostart.macosLaunchAgentIntro")}
|
||||
</Typography>
|
||||
<CodeBlock>{MACOS_LAUNCH_AGENT_PLIST}</CodeBlock>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mt: 1.5, mb: 1 }}>
|
||||
{t("download.autostart.macosLaunchAgentLoad")}
|
||||
</Typography>
|
||||
<CodeBlock>{MACOS_LAUNCH_AGENT_LOAD_CMD}</CodeBlock>
|
||||
</Paper>
|
||||
</Stack>
|
||||
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
<Trans
|
||||
t={t}
|
||||
i18nKey="download.footerLinks"
|
||||
components={{
|
||||
releases: <Link href={BRIDGE_RELEASES_PAGE} target="_blank" rel="noopener noreferrer" />,
|
||||
}}
|
||||
/>
|
||||
</Typography>
|
||||
<Dialog open={installOs !== null} onClose={() => setInstallOs(null)} maxWidth="xs" fullWidth>
|
||||
{installOs && (
|
||||
<>
|
||||
<DialogTitle>{t(`download.modal.${installOs}.heading`)}</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 2.5 }}>
|
||||
{t("download.modal.startedNote")}
|
||||
</Typography>
|
||||
<InstallSteps steps={installSteps[installOs]} />
|
||||
{installOs === "macos" && (
|
||||
<Typography variant="caption" color="text.secondary" sx={{ display: "block", mt: 2.5 }}>
|
||||
{t("download.modal.macos.note")}
|
||||
</Typography>
|
||||
)}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setInstallOs(null)}>{t("common:close")}</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
)}
|
||||
</Dialog>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -91,7 +91,7 @@ export default function SlicerPicker({ onUnauthorized }: Props) {
|
||||
{value === "bambustudio" && (
|
||||
<Typography variant="caption" color="text.secondary" sx={{ display: "block", mt: 1 }}>
|
||||
{t("profile.slicer.bridgeRequiredPrefix")}{" "}
|
||||
<Link component={RouterLink} to="/download">{t("profile.slicer.bridgeRequiredLink")}</Link>
|
||||
<Link component={RouterLink} to="/downloads">{t("profile.slicer.bridgeRequiredLink")}</Link>
|
||||
</Typography>
|
||||
)}
|
||||
{status && <Typography variant="caption" color="error" sx={{ display: "block", mt: 1 }}>{status}</Typography>}
|
||||
|
||||
Reference in new issue
Block a user