fix(library): preview sidecar-sliced .gcode.3mf rows as G-code, not ZIP bytes (#1709)

slice_and_persist writes a .gcode.3mf ZIP container but persisted the row
  with file_type="gcode". The G-code preview endpoint short-circuits on
  file_type == "gcode" and returns the bytes as text/plain, so the embedded
  viewer received the raw ZIP body instead of the embedded toolpath.

  - Persist file_type="gcode.3mf" on sliced rows (matches _classify_file_type
    and external-scan rows).
  - get_gcode also routes to the unzip branch when the filename ends with
    .gcode.3mf, so rows already written under the bug self-heal on first
    preview without a DB migration.
  - Extend FileManagerPage badge + viewer-eye gate and ProjectDetailPage badge
    to accept "gcode.3mf"; isSlicedFilename / isSliceableFilename already do.
  - Add test_library_get_gcode_recovers_legacy_gcode_type_for_3mf: legacy
    row preview must be text/plain, contain G28, and NOT start with PK.
This commit is contained in:
maziggy
2026-06-12 10:42:02 +02:00
parent 908227e4df
commit 857a071306
7 changed files with 55 additions and 17 deletions
+2 -2
View File
@@ -2164,7 +2164,7 @@ export function FileManagerPage() {
<div>
<span className={`text-xs px-1.5 py-0.5 rounded font-medium ${
file.file_type === '3mf' ? 'bg-bambu-green/20 text-bambu-green'
: file.file_type === 'gcode' ? 'bg-blue-500/20 text-blue-400'
: (file.file_type === 'gcode' || file.file_type === 'gcode.3mf') ? 'bg-blue-500/20 text-blue-400'
: file.file_type === 'stl' ? 'bg-purple-500/20 text-purple-400'
: 'bg-bambu-gray/20 text-bambu-gray'
}`}>
@@ -2223,7 +2223,7 @@ export function FileManagerPage() {
<Cog className="w-4 h-4" />
</button>
)}
{(file.file_type === '3mf' || file.file_type === 'gcode' || file.file_type === 'stl') && (
{(file.file_type === '3mf' || file.file_type === 'gcode' || file.file_type === 'gcode.3mf' || file.file_type === 'stl') && (
<button
onClick={() => {
if (!hasPermission('library:read')) return;
+1 -1
View File
@@ -949,7 +949,7 @@ export function ProjectDetailPage() {
</p>
<span className={`text-xs px-1.5 py-0.5 rounded font-medium ${
file.file_type === '3mf' ? 'bg-bambu-green/20 text-bambu-green'
: file.file_type === 'gcode' ? 'bg-blue-500/20 text-blue-400'
: (file.file_type === 'gcode' || file.file_type === 'gcode.3mf') ? 'bg-blue-500/20 text-blue-400'
: 'bg-bambu-gray/20 text-bambu-gray'
}`}>
{file.file_type.toUpperCase()}