- Slicer Protocol:

- Add utils/slicer.ts with OS detection for protocol handler
  - Windows: bambustudio://, macOS/Linux: bambustudioopen://
  - Update all usages in ArchivesPage.tsx and ModelViewerModal.tsx
This commit is contained in:
maziggy
2026-01-01 07:52:47 +01:00
parent 2457577f54
commit 01bc211616
5 changed files with 474 additions and 403 deletions
+2 -2
View File
@@ -4,6 +4,7 @@ import { ModelViewer } from './ModelViewer';
import { GcodeViewer } from './GcodeViewer';
import { Button } from './Button';
import { api } from '../api/client';
import { openInSlicer } from '../utils/slicer';
type ViewTab = '3d' | 'gcode';
@@ -55,11 +56,10 @@ export function ModelViewerModal({ archiveId, title, onClose }: ModelViewerModal
}, [archiveId]);
const handleOpenInSlicer = () => {
// Use bambustudioopen:// protocol like MakerWorld does
// URL must include .3mf filename for Bambu Studio to recognize the format
const filename = title || 'model';
const downloadUrl = `${window.location.origin}${api.getArchiveForSlicer(archiveId, filename)}`;
window.location.href = `bambustudioopen://${encodeURIComponent(downloadUrl)}`;
openInSlicer(downloadUrl);
};
return (
+7 -6
View File
@@ -42,6 +42,7 @@ import {
FolderKanban,
} from 'lucide-react';
import { api } from '../api/client';
import { openInSlicer } from '../utils/slicer';
import { useIsMobile } from '../hooks/useIsMobile';
import type { Archive, ProjectListItem } from '../api/client';
import { Card, CardContent } from '../components/Card';
@@ -233,7 +234,7 @@ function ArchiveCard({
onClick: () => {
const filename = archive.print_name || archive.filename || 'model';
const downloadUrl = `${window.location.origin}${api.getArchiveForSlicer(archive.id, filename)}`;
window.location.href = `bambustudioopen://${encodeURIComponent(downloadUrl)}`;
openInSlicer(downloadUrl);
},
},
] : [
@@ -243,7 +244,7 @@ function ArchiveCard({
onClick: () => {
const filename = archive.print_name || archive.filename || 'model';
const downloadUrl = `${window.location.origin}${api.getArchiveForSlicer(archive.id, filename)}`;
window.location.href = `bambustudioopen://${encodeURIComponent(downloadUrl)}`;
openInSlicer(downloadUrl);
},
},
]),
@@ -498,7 +499,7 @@ function ArchiveCard({
// Open source 3MF in Bambu Studio - use filename in URL for slicer compatibility
const sourceName = (archive.print_name || archive.filename || 'source').replace(/\.gcode\.3mf$/i, '') + '_source';
const downloadUrl = `${window.location.origin}${api.getSource3mfForSlicer(archive.id, sourceName)}`;
window.location.href = `bambustudioopen://${encodeURIComponent(downloadUrl)}`;
openInSlicer(downloadUrl);
}}
title="Open source 3MF in Bambu Studio (right-click for more options)"
>
@@ -684,7 +685,7 @@ function ArchiveCard({
onClick={() => {
const filename = archive.print_name || archive.filename || 'model';
const downloadUrl = `${window.location.origin}${api.getArchiveForSlicer(archive.id, filename)}`;
window.location.href = `bambustudioopen://${encodeURIComponent(downloadUrl)}`;
openInSlicer(downloadUrl);
}}
title="Open in Bambu Studio"
>
@@ -700,7 +701,7 @@ function ArchiveCard({
onClick={() => {
const filename = archive.print_name || archive.filename || 'model';
const downloadUrl = `${window.location.origin}${api.getArchiveForSlicer(archive.id, filename)}`;
window.location.href = `bambustudioopen://${encodeURIComponent(downloadUrl)}`;
openInSlicer(downloadUrl);
}}
title="Open in Bambu Studio to slice"
>
@@ -1850,7 +1851,7 @@ export function ArchivesPage() {
onClick={() => {
const filename = archive.print_name || archive.filename || 'model';
const downloadUrl = `${window.location.origin}${api.getArchiveForSlicer(archive.id, filename)}`;
window.location.href = `bambustudioopen://${encodeURIComponent(downloadUrl)}`;
openInSlicer(downloadUrl);
}}
title="Slice"
>
+70
View File
@@ -0,0 +1,70 @@
/**
* Utility for opening files in Bambu Studio slicer
*
* The URL protocol handler is OS-specific:
* - Windows: bambustudio://
* - macOS/Linux: bambustudioopen://
*/
type Platform = 'windows' | 'macos' | 'linux' | 'unknown';
/**
* Detect the user's operating system
*/
export function detectPlatform(): Platform {
const userAgent = navigator.userAgent.toLowerCase();
const platform = navigator.platform?.toLowerCase() || '';
if (userAgent.includes('win') || platform.includes('win')) {
return 'windows';
}
if (userAgent.includes('mac') || platform.includes('mac')) {
return 'macos';
}
if (userAgent.includes('linux') || platform.includes('linux')) {
return 'linux';
}
return 'unknown';
}
/**
* Get the appropriate slicer protocol for the current OS
*/
export function getSlicerProtocol(): string {
const platform = detectPlatform();
switch (platform) {
case 'windows':
return 'bambustudio://';
case 'macos':
case 'linux':
default:
return 'bambustudioopen://';
}
}
/**
* Open a URL in Bambu Studio slicer
* @param downloadUrl - The URL to the file to open (will be encoded)
*/
export function openInSlicer(downloadUrl: string): void {
const protocol = getSlicerProtocol();
window.location.href = `${protocol}${encodeURIComponent(downloadUrl)}`;
}
/**
* Build a full download URL for a file
* @param path - The API path (e.g., from api.getArchiveForSlicer())
*/
export function buildDownloadUrl(path: string): string {
return `${window.location.origin}${path}`;
}
/**
* Convenience function to open an archive in the slicer
* @param path - The API path to the archive
*/
export function openArchiveInSlicer(path: string): void {
const downloadUrl = buildDownloadUrl(path);
openInSlicer(downloadUrl);
}
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -23,7 +23,7 @@
<!-- Splash screens for iOS -->
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
<script type="module" crossorigin src="/assets/index-VFINsn3X.js"></script>
<script type="module" crossorigin src="/assets/index-DNsmdSrp.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BmBv9fEm.css">
</head>
<body>