mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 03:54:17 +02:00
feat(diagnostic, archives): install step 4 — proactive check + reactive banner
Two complementary surfaces for the most-missed install step ("Store sent
files on external storage"):
1. Connection diagnostic check (printer-side variant)
- Reads state.store_to_sdcard, parsed from MQTT home_flag bit 11.
- Pass / fail / skip; instant, no I/O.
- Catches the newer-firmware variant where the toggle moved onto the
printer itself (P2S 01.02 / Studio 2.6+).
An FTP upload-and-verify probe was tried first and rejected. /cache
is always writable from Bambuddy regardless of the slicer setting;
only BambuStudio's own behaviour changes when the toggle flips.
Empirically confirmed against X1C + H2D with the slicer option
toggled off: probe still succeeded, home_flag bit 11 stayed True.
2. Archives-page banner (slicer-side variant)
- The slicer-side toggle is invisible to the printer — older
BambuStudio doesn't push the change to the printer. The diagnostic
can't see it.
- Symptom is deterministic: archiver creates rows with
extra_data.no_3mf_available=True (main.py:2770) when it can't pull
the 3MF from /cache after a slicer-initiated print.
- New endpoint GET /archives/no-3mf-warning returns whether any
archive in the last 30 days has the flag (excluding soft-deleted).
- Amber dismissible banner at the top of /archives; one-shot
localStorage dismissal (matches Layout.tsx update-banner pattern,
but persistent across sessions).
- React-Query disabled after dismissal so the endpoint isn't polled
once the user has been told.
This commit is contained in:
@@ -3771,6 +3771,7 @@ export const api = {
|
||||
return request<Archive[]>(`/archives/search?${params}`);
|
||||
},
|
||||
rebuildSearchIndex: () => request<{ message: string }>('/archives/search/rebuild-index', { method: 'POST' }),
|
||||
getNo3MFWarning: () => request<{ has_fallback: boolean }>('/archives/no-3mf-warning'),
|
||||
updateArchive: (id: number, data: {
|
||||
printer_id?: number | null;
|
||||
project_id?: number | null;
|
||||
|
||||
@@ -635,6 +635,12 @@ export default {
|
||||
// Archives page
|
||||
archives: {
|
||||
title: 'Druckarchiv',
|
||||
no3mfBanner: {
|
||||
title: 'Einige kürzliche Drucke konnten nicht mit Vorschaubild archiviert werden',
|
||||
body: 'Der Slicer hat die .gcode.3mf-Datei nicht auf der SD-Karte des Druckers hinterlegt, daher konnte Bambuddy weder Vorschaubild noch Slicer-Metadaten abrufen. Üblicherweise liegt das daran, dass "Gesendete Dateien auf externem Speicher speichern" im Slicer (Geräte-Tab in Bambu Studio / OrcaSlicer) deaktiviert ist.',
|
||||
docsLink: 'Installationsschritt 4 anzeigen',
|
||||
dismissLabel: 'Hinweis schließen',
|
||||
},
|
||||
searchPlaceholder: 'Archiv durchsuchen...',
|
||||
filterByPrinter: 'Nach Drucker filtern',
|
||||
filterByStatus: 'Nach Status filtern',
|
||||
|
||||
@@ -635,6 +635,12 @@ export default {
|
||||
// Archives page
|
||||
archives: {
|
||||
title: 'Print Archives',
|
||||
no3mfBanner: {
|
||||
title: 'Some recent prints couldn\'t be archived with thumbnails',
|
||||
body: 'The slicer didn\'t leave the .gcode.3mf on the printer\'s SD card, so Bambuddy couldn\'t pull the thumbnail or slicer metadata. This is usually because "Store sent files on external storage" is off in the slicer (Bambu Studio / OrcaSlicer Device tab).',
|
||||
docsLink: 'See install step 4',
|
||||
dismissLabel: 'Dismiss this notice',
|
||||
},
|
||||
searchPlaceholder: 'Search archives...',
|
||||
filterByPrinter: 'Filter by printer',
|
||||
filterByStatus: 'Filter by status',
|
||||
|
||||
@@ -635,6 +635,12 @@ export default {
|
||||
// Archives page
|
||||
archives: {
|
||||
title: 'Archivos de impresión',
|
||||
no3mfBanner: {
|
||||
title: 'Algunas impresiones recientes no se pudieron archivar con miniaturas',
|
||||
body: 'El slicer no dejó el archivo .gcode.3mf en la tarjeta SD de la impresora, así que Bambuddy no pudo recuperar ni la miniatura ni los metadatos del slicer. Esto suele deberse a que "Almacenar archivos enviados en almacenamiento externo" está desactivado en el slicer (pestaña Dispositivo de Bambu Studio / OrcaSlicer).',
|
||||
docsLink: 'Ver paso 4 de instalación',
|
||||
dismissLabel: 'Descartar este aviso',
|
||||
},
|
||||
searchPlaceholder: 'Buscar archivos...',
|
||||
filterByPrinter: 'Filtrar por impresora',
|
||||
filterByStatus: 'Filtrar por estado',
|
||||
|
||||
@@ -635,6 +635,12 @@ export default {
|
||||
// Archives page
|
||||
archives: {
|
||||
title: 'Archives d\'impression',
|
||||
no3mfBanner: {
|
||||
title: 'Certaines impressions récentes n\'ont pas pu être archivées avec leur miniature',
|
||||
body: 'Le slicer n\'a pas laissé le fichier .gcode.3mf sur la carte SD de l\'imprimante, donc Bambuddy n\'a pas pu récupérer la miniature ni les métadonnées slicer. C\'est généralement parce que « Stocker les fichiers envoyés sur stockage externe » est désactivé dans le slicer (onglet Périphérique de Bambu Studio / OrcaSlicer).',
|
||||
docsLink: 'Voir l\'étape 4 de l\'installation',
|
||||
dismissLabel: 'Ignorer ce message',
|
||||
},
|
||||
searchPlaceholder: 'Chercher dans les archives...',
|
||||
filterByPrinter: 'Par imprimante',
|
||||
filterByStatus: 'Par statut',
|
||||
|
||||
@@ -635,6 +635,12 @@ export default {
|
||||
// Archives page
|
||||
archives: {
|
||||
title: 'Archivi di stampa',
|
||||
no3mfBanner: {
|
||||
title: 'Alcune stampe recenti non sono state archiviate con la miniatura',
|
||||
body: 'Lo slicer non ha lasciato il file .gcode.3mf sulla scheda SD della stampante, quindi Bambuddy non ha potuto recuperare né la miniatura né i metadati dello slicer. Solitamente accade perché "Memorizza file inviati su archiviazione esterna" è disattivato nello slicer (scheda Dispositivo di Bambu Studio / OrcaSlicer).',
|
||||
docsLink: 'Vedi passo 4 dell\'installazione',
|
||||
dismissLabel: 'Chiudi questo avviso',
|
||||
},
|
||||
searchPlaceholder: 'Cerca archivi...',
|
||||
filterByPrinter: 'Filtra per stampante',
|
||||
filterByStatus: 'Filtra per stato',
|
||||
|
||||
@@ -634,6 +634,12 @@ export default {
|
||||
// Archives page
|
||||
archives: {
|
||||
title: '印刷アーカイブ',
|
||||
no3mfBanner: {
|
||||
title: '最近の一部の印刷でサムネイル付きのアーカイブができませんでした',
|
||||
body: 'スライサーがプリンターのSDカードに.gcode.3mfファイルを残さなかったため、Bambuddyはサムネイルもスライサーメタデータも取得できませんでした。これは通常、スライサー (Bambu Studio / OrcaSlicer のデバイスタブ) で「送信ファイルを外部ストレージに保存」がオフになっていることが原因です。',
|
||||
docsLink: 'インストール手順4を参照',
|
||||
dismissLabel: 'この通知を閉じる',
|
||||
},
|
||||
searchPlaceholder: 'アーカイブを検索...',
|
||||
filterByPrinter: 'プリンターで絞り込み',
|
||||
filterByStatus: 'ステータスで絞り込み',
|
||||
|
||||
@@ -592,6 +592,12 @@ export default {
|
||||
},
|
||||
archives: {
|
||||
title: '인쇄 아카이브',
|
||||
no3mfBanner: {
|
||||
title: '최근 일부 인쇄가 썸네일과 함께 아카이브되지 않았습니다',
|
||||
body: '슬라이서가 프린터의 SD 카드에 .gcode.3mf 파일을 남기지 않아서 Bambuddy가 썸네일이나 슬라이서 메타데이터를 가져올 수 없었습니다. 일반적으로 슬라이서 (Bambu Studio / OrcaSlicer 장치 탭)에서 "전송된 파일을 외부 저장소에 저장"이 꺼져 있을 때 발생합니다.',
|
||||
docsLink: '설치 단계 4 보기',
|
||||
dismissLabel: '이 알림 닫기'
|
||||
},
|
||||
searchPlaceholder: '아카이브 검색...',
|
||||
filterByPrinter: '프린터별 필터',
|
||||
filterByStatus: '상태별 필터',
|
||||
|
||||
@@ -635,6 +635,12 @@ export default {
|
||||
// Archives page
|
||||
archives: {
|
||||
title: 'Arquivos de Impressão',
|
||||
no3mfBanner: {
|
||||
title: 'Algumas impressões recentes não puderam ser arquivadas com miniaturas',
|
||||
body: 'O fatiador não deixou o arquivo .gcode.3mf no cartão SD da impressora, então o Bambuddy não conseguiu obter nem a miniatura nem os metadados do fatiador. Normalmente isso acontece porque "Armazenar arquivos enviados no armazenamento externo" está desligado no fatiador (aba Dispositivo do Bambu Studio / OrcaSlicer).',
|
||||
docsLink: 'Ver passo 4 da instalação',
|
||||
dismissLabel: 'Dispensar este aviso',
|
||||
},
|
||||
searchPlaceholder: 'Pesquisar arquivos...',
|
||||
filterByPrinter: 'Filtrar por impressora',
|
||||
filterByStatus: 'Filtrar por status',
|
||||
|
||||
@@ -635,6 +635,12 @@ export default {
|
||||
// Arşivler sayfası
|
||||
archives: {
|
||||
title: 'Baskı Arşivleri',
|
||||
no3mfBanner: {
|
||||
title: 'Bazı son baskılar küçük resimlerle birlikte arşivlenemedi',
|
||||
body: 'Dilimleyici yazıcının SD kartına .gcode.3mf dosyasını bırakmadı, bu nedenle Bambuddy küçük resmi veya dilimleyici meta verilerini alamadı. Bu genellikle dilimleyicide (Bambu Studio / OrcaSlicer\'in Cihaz sekmesi) "Gönderilen dosyaları harici depolamada sakla" seçeneğinin kapalı olmasından kaynaklanır.',
|
||||
docsLink: 'Kurulum adımı 4\'ü görüntüle',
|
||||
dismissLabel: 'Bu bildirimi kapat',
|
||||
},
|
||||
searchPlaceholder: 'Arşivlerde ara...',
|
||||
filterByPrinter: 'Yazıcıya göre filtrele',
|
||||
filterByStatus: 'Duruma göre filtrele',
|
||||
|
||||
@@ -635,6 +635,12 @@ export default {
|
||||
// Archives page
|
||||
archives: {
|
||||
title: '打印归档',
|
||||
no3mfBanner: {
|
||||
title: '最近的一些打印未能附带缩略图归档',
|
||||
body: '切片机没有在打印机的 SD 卡上留下 .gcode.3mf 文件,因此 Bambuddy 无法获取缩略图或切片机元数据。这通常是因为切片机 (Bambu Studio / OrcaSlicer 的设备选项卡) 中"将发送的文件存储在外部存储中"已关闭。',
|
||||
docsLink: '查看安装步骤 4',
|
||||
dismissLabel: '关闭此通知',
|
||||
},
|
||||
searchPlaceholder: '搜索归档...',
|
||||
filterByPrinter: '按打印机筛选',
|
||||
filterByStatus: '按状态筛选',
|
||||
|
||||
@@ -635,6 +635,12 @@ export default {
|
||||
// Archives page
|
||||
archives: {
|
||||
title: '列印歸檔',
|
||||
no3mfBanner: {
|
||||
title: '最近的一些列印未能附帶縮圖封存',
|
||||
body: '切片機沒有在印表機的 SD 卡上留下 .gcode.3mf 檔案,因此 Bambuddy 無法取得縮圖或切片機中繼資料。這通常是因為切片機 (Bambu Studio / OrcaSlicer 的裝置分頁) 中「將傳送的檔案儲存在外部儲存中」已關閉。',
|
||||
docsLink: '檢視安裝步驟 4',
|
||||
dismissLabel: '關閉此通知',
|
||||
},
|
||||
searchPlaceholder: '搜尋歸檔...',
|
||||
filterByPrinter: '按印表機篩選',
|
||||
filterByStatus: '按狀態篩選',
|
||||
|
||||
@@ -2563,6 +2563,23 @@ export function ArchivesPage() {
|
||||
const [uploadFiles, setUploadFiles] = useState<File[]>([]);
|
||||
const [isDraggingOver, setIsDraggingOver] = useState(false);
|
||||
const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set());
|
||||
// Install-step-4 nudge — covers the slicer-side variant of "Store sent files
|
||||
// on external storage" that the connection diagnostic can't detect (printer
|
||||
// never hears about it). Symptom: archive created via no-3MF fallback. Once
|
||||
// dismissed, never shown again — fixing step 4 stops new fallbacks anyway.
|
||||
const [no3MFWarningDismissed, setNo3MFWarningDismissed] = useState(
|
||||
() => localStorage.getItem('archiveNo3MFWarningDismissed') === 'true',
|
||||
);
|
||||
const { data: no3MFWarning } = useQuery({
|
||||
queryKey: ['archives', 'no-3mf-warning'],
|
||||
queryFn: api.getNo3MFWarning,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
enabled: !no3MFWarningDismissed,
|
||||
});
|
||||
const dismissNo3MFWarning = () => {
|
||||
localStorage.setItem('archiveNo3MFWarningDismissed', 'true');
|
||||
setNo3MFWarningDismissed(true);
|
||||
};
|
||||
const [isSelectionMode, setIsSelectionMode] = useState(false);
|
||||
const [showBulkDeleteConfirm, setShowBulkDeleteConfirm] = useState(false);
|
||||
const [showBatchTag, setShowBatchTag] = useState(false);
|
||||
@@ -3200,6 +3217,37 @@ export function ArchivesPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{no3MFWarning?.has_fallback && !no3MFWarningDismissed && (
|
||||
<div className="mb-6 rounded-lg border border-amber-500/30 bg-amber-500/10 px-4 py-3 flex items-start gap-3">
|
||||
<AlertCircle className="w-5 h-5 text-amber-400 flex-shrink-0 mt-0.5" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="text-sm font-medium text-amber-200">
|
||||
{t('archives.no3mfBanner.title')}
|
||||
</div>
|
||||
<div className="text-xs text-amber-200/80 mt-1">
|
||||
{t('archives.no3mfBanner.body')}{' '}
|
||||
<a
|
||||
href="https://bambuddy.cool/wiki/getting-started/#step-4-enable-store-sent-files-on-external-storage"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="underline hover:text-amber-100 inline-flex items-center gap-1"
|
||||
>
|
||||
{t('archives.no3mfBanner.docsLink')}
|
||||
<ExternalLink className="w-3 h-3" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={dismissNo3MFWarning}
|
||||
className="text-amber-200/60 hover:text-amber-200 flex-shrink-0 p-1 -m-1"
|
||||
title={t('archives.no3mfBanner.dismissLabel')}
|
||||
aria-label={t('archives.no3mfBanner.dismissLabel')}
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-8">
|
||||
<div>
|
||||
<div className="flex items-start gap-3">
|
||||
|
||||
Reference in New Issue
Block a user