Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable changes contributed via pull request are documented in this file.

## [Unreleased]

### Refined interface
- New default **Graphite** theme: ash-gray surfaces with a faint aubergine cast, no decorative borders, and one accent used only for selection, focus, active filter pills and the "new" dot. The other themes in Settings now only change that accent. The styles live in `refined.css`, loaded after the existing sheets.
- Thumbnails sit on the card surface instead of dark blue. Settings → Model Background Color has a new **Match interface (Default)** option. On first launch, a saved Dark Blue background or Modern Cyan theme, which older versions saved whenever Settings was saved, moves to the new defaults once. A theme picked after that is kept.
- The search field is the lead control of the sidebar: taller, with a magnifier, a ⌘/ (Ctrl+/) hint, and a submit arrow that lights up once you type.
- Scan Directory and View Entire Library become one compact row of quiet buttons, **Scan folder** and **Show all**, so they no longer compete with search. Both keep their behavior.
- Sidebar: one-line brand row with the model count, tool tabs with line icons instead of colored round buttons, 40px controls with matching square helper buttons, and the same inset on both edges.
- Library: Detailed cards are clear containers (surface, hairline edge, soft depth, rating row on its own hairline) and fill the width like the Preview wall, photo thumbnails get a margin and rounded corners, and all three views share one inset. "Not printed" is no longer badged on every card, because it is the default state; other print states show a colored dot.
- List view is one table: a tinted sticky header, hairline rows edge to edge, centered cells, sizes right-aligned, and group rows in the same type as model rows.
- Dialogs share one flat style with a single light primary button. The Server/Docker touch layout keeps its own design and was checked for regressions.

## [3.0.1] - 2026-10-18

- Upgrading from 2.x keeps models that were marked Printed. The 3.0.0 migration had filled every row with Unprinted because SQLite applies `DEFAULT` on `ADD COLUMN`, so the backfill never ran. Opening 3.0.1 also repairs databases that already hit that bug (`printed = 1` still in the DB).
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ RUN rm -rf node_modules/better-sqlite3/build || true && \
npx electron-builder install-app-deps

# Copy application files
COPY main.js db-repair.js bundle-keys.js zip-extract.js preload.js input-dialog-preload.js input-dialog.html renderer.js notes-markdown.js dedup-preferred.js organize-library.js organize-library-ui.js organize-library.css index.html styles.css theme.css notes-markdown.css preview-wall.css thumbnail-progress.css thumbnail-progress.js ./
COPY main.js db-repair.js bundle-keys.js zip-extract.js preload.js input-dialog-preload.js input-dialog.html renderer.js notes-markdown.js dedup-preferred.js organize-library.js organize-library-ui.js organize-library.css index.html styles.css theme.css refined.css notes-markdown.css preview-wall.css thumbnail-progress.css thumbnail-progress.js ./
COPY printer-manager.js printer-discovery.js slicer-detect.js printer-management.js printer-management.css parts-stock.js parts-stock.css ./
COPY manifest.webmanifest sw.js pwa.js mobile-ui.js mobile-ui.css ./
COPY server-bridge.js scan-worker.js scan-skip.js parse-worker.js scheduled-backup.js missing-thumbnails-query.js primary-thumbnails-query.js delete-model-file.js flatten-3mf-stl.js thumbnail-worker.js ./
Expand All @@ -118,7 +118,7 @@ COPY *.png *.jpg *.bmp ./
COPY guide/ ./guide/

# Fail the build if required app modules were omitted from COPY above
RUN for f in db-repair.js bundle-keys.js zip-extract.js thumbnail-compress.js threemf-mesh-extract.js print-events.js folder-tree-lib.js mcp-server.js server-tls.js extension-inbox.js sidebar-layout.js folder-tree.js extract-lys-preview.js extract-f3d-preview.js extract-chitubox-preview.js extract-voxl-preview.js parse-lys-geometry.js step-assembly.js manifest.webmanifest sw.js pwa.js mobile-ui.js mobile-ui.css theme.css notes-markdown.js notes-markdown.css dedup-preferred.js organize-library.js organize-library-ui.js organize-library.css printer-manager.js printer-discovery.js slicer-detect.js printer-management.js printer-management.css parts-stock.js parts-stock.css scheduled-backup.js missing-thumbnails-query.js primary-thumbnails-query.js delete-model-file.js scan-skip.js slicer-launch.js slicer-protocol.js helper/printventory-helper.js helper/install-bundle.js library-context.js folder-tags.js grid-refresh.js stl-sanity.js thumbnail-skip.js ai-rate-limit.js support-logs.js support-webhook.json input-dialog-preload.js input-dialog.html; do \
RUN for f in db-repair.js bundle-keys.js zip-extract.js thumbnail-compress.js threemf-mesh-extract.js print-events.js folder-tree-lib.js mcp-server.js server-tls.js extension-inbox.js sidebar-layout.js folder-tree.js extract-lys-preview.js extract-f3d-preview.js extract-chitubox-preview.js extract-voxl-preview.js parse-lys-geometry.js step-assembly.js manifest.webmanifest sw.js pwa.js mobile-ui.js mobile-ui.css theme.css refined.css notes-markdown.js notes-markdown.css dedup-preferred.js organize-library.js organize-library-ui.js organize-library.css printer-manager.js printer-discovery.js slicer-detect.js printer-management.js printer-management.css parts-stock.js parts-stock.css scheduled-backup.js missing-thumbnails-query.js primary-thumbnails-query.js delete-model-file.js scan-skip.js slicer-launch.js slicer-protocol.js helper/printventory-helper.js helper/install-bundle.js library-context.js folder-tags.js grid-refresh.js stl-sanity.js thumbnail-skip.js ai-rate-limit.js support-logs.js support-webhook.json input-dialog-preload.js input-dialog.html; do \
test -f "$f" || (echo "Missing required app file: $f" >&2; exit 1); \
done

Expand Down
10 changes: 5 additions & 5 deletions grid-refresh.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,14 @@
const view = spec.view || 'detailed';
const previewColumns = Math.max(1, Math.round(Number(spec.previewColumns) || 6));
const previewGap = spec.previewGap == null ? 2 : Number(spec.previewGap);
// Preview tiles use the full grid box. Detailed and list sit inside 20px of padding.
// Detailed and preview sit inside 20px of padding; list rows pad themselves.
const contentWidth = Math.max(0, gridWidth - 40);
const available = view === 'preview' ? gridWidth : contentWidth;
const tile = previewTilePx(gridWidth, previewColumns, previewGap);
const available = view === 'list' ? gridWidth : contentWidth;
const tile = previewTilePx(contentWidth, previewColumns, previewGap);
const detailedColumns = detailedColumnCount(contentWidth, spec.itemWidth || 300);
const columns = view === 'list' ? 1 : (view === 'preview' ? previewColumns : detailedColumns);
const rowHeight = view === 'preview' ? tile : (view === 'list' ? 56 : (Number(spec.itemHeight) || 520));
const verticalGap = view === 'preview' ? previewGap : (view === 'list' ? 6 : 20);
const verticalGap = view === 'preview' ? previewGap : (view === 'list' ? 0 : 20);
const next = {
width: gridWidth,
columns: columns,
Expand All @@ -124,7 +124,7 @@
detailedColumns: detailedColumns,
columns: columns,
rowHeight: rowHeight,
list: listViewScrollWidth(spec.columnWidths || [], contentWidth),
list: listViewScrollWidth(spec.columnWidths || [], available),
reposition: virtualGridGeometryChanged(spec.previous || null, next),
layout: next
};
Expand Down
47 changes: 23 additions & 24 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<link rel="stylesheet" href="thumbnail-progress.css">
<link rel="stylesheet" href="mobile-ui.css">
<link rel="stylesheet" href="organize-library.css">
<link rel="stylesheet" href="refined.css">
<script src="vendor/three.min.js"></script>
<script src="vendor/STLLoader.js"></script>
<script src="vendor/3MFLoader.js"></script>
Expand Down Expand Up @@ -129,31 +130,26 @@ <h2 id="mobile-more-title">More</h2>
</section>
<div class="sidebar">
<div class="sidebar-chrome">
<img src="logo.png" alt="Printventory Logo" id="logo">
<div class="model-stats">
<div id="view-count" class="model-count">0 models in view</div>
<div id="total-count" class="model-count">0 models total</div>
</div>
<div class="icon-buttons-container">
<button id="dup-button" class="icon-button" title="De-Dup">
<img src="dup.png" alt="De-Dup">
</button>
<button id="tag-button" class="icon-button" title="Tag - Tag Manager">
<img src="tag.png" alt="Tag Manager">
</button>
<button id="filament-button" class="icon-button" title="Filament - Filament Manager">
<img src="filament.png" alt="Filament Manager">
</button>
<button id="printer-button" class="icon-button" title="Printer - Printer Manager">
<img src="printer.png" alt="Printer Manager">
</button>
<button id="roulette-button" class="icon-button" title="Roulette - Print Roulette">
<img src="roulette.png" alt="Print Roulette">
</button>
<div class="sidebar-brand">
<img src="logo-mark.png" alt="Printventory" id="logo">
<div class="sidebar-brand-text">
<div class="sidebar-brand-name">Printventory</div>
<div class="model-stats">
<div id="view-count" class="model-count">0 models in view</div>
<div id="total-count" class="model-count">0 models total</div>
</div>
</div>
</div>
<button id="scan-directory-button">Scan Directory</button>
<nav class="icon-buttons-container sidebar-tools" aria-label="Tools">
<button id="dup-button" class="icon-button" title="De-Dup"><svg class="tool-icon" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"/></svg><span>Dupes</span></button>
<button id="tag-button" class="icon-button" title="Tag Manager"><svg class="tool-icon" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12.6 2.6A2 2 0 0 0 11.2 2H4a2 2 0 0 0-2 2v7.2a2 2 0 0 0 .6 1.4l8.7 8.7a2.4 2.4 0 0 0 3.4 0l6.6-6.6a2.4 2.4 0 0 0 0-3.4z"/><circle cx="7.5" cy="7.5" r="1.2"/></svg><span>Tags</span></button>
<button id="filament-button" class="icon-button" title="Filament Manager"><svg class="tool-icon" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="3.5"/><path d="M12 3v5.5"/></svg><span>Filament</span></button>
<button id="printer-button" class="icon-button" title="Printer Manager"><svg class="tool-icon" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="4" y="3" width="16" height="18" rx="2"/><path d="M4 8h16"/><path d="M10 12h4l-1 3h-2z"/><path d="M8 18h8"/></svg><span>Printers</span></button>
<button id="roulette-button" class="icon-button" title="Print Roulette"><svg class="tool-icon" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3.5" y="3.5" width="17" height="17" rx="3.5"/><circle cx="8.5" cy="8.5" r="1" fill="currentColor"/><circle cx="12" cy="12" r="1" fill="currentColor"/><circle cx="15.5" cy="15.5" r="1" fill="currentColor"/></svg><span>Roulette</span></button>
</nav>
<button id="scan-directory-button" title="Scan a folder: add it to the library or pick up new files"><svg class="tool-icon" viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><path d="M12 11v5M9.5 13.5h5"/></svg><span>Scan folder</span></button>
<button id="scan-stl-home-button" class="secondary-button" style="display: none;">Scan STL Home</button>
<button id="view-library-button">View Entire Library</button>
<button id="view-library-button" title="View the entire library (clears filters)"><svg class="tool-icon" viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3.5" y="3.5" width="7" height="7" rx="1.5"/><rect x="13.5" y="3.5" width="7" height="7" rx="1.5"/><rect x="3.5" y="13.5" width="7" height="7" rx="1.5"/><rect x="13.5" y="13.5" width="7" height="7" rx="1.5"/></svg><span>Show all</span></button>
<div id="view-library-message" class="library-view-banner">
<!-- Updated text will appear here -->
</div>
Expand Down Expand Up @@ -191,6 +187,7 @@ <h2 id="mobile-more-title">More</h2>
<input type="search" id="search-filter-input" placeholder="Search models" enterkeyhint="search" autocomplete="off">
<button id="filter-search-button" class="icon-button" title="Add this text to the active query (all fields)">🔍</button>
<button id="clear-filter-search-button" class="icon-button" title="Clear search">×</button>
<kbd class="search-shortcut-hint" aria-hidden="true">Ctrl /</kbd>
</div>
<label class="search-notes-toggle" title="Include notes in all-fields search. Turn off to skip long imported descriptions. A search limited to the Notes field still matches notes.">
<input type="checkbox" id="search-include-notes" checked>
Expand Down Expand Up @@ -1867,7 +1864,8 @@ <h3>Theme Settings</h3>
<div class="form-group">
<label for="ui-theme">UI Theme:</label>
<select id="ui-theme">
<option value="modern-cyan">Modern Cyan (Default)</option>
<option value="graphite">Graphite (Default)</option>
<option value="modern-cyan">Modern Cyan</option>
<option value="modern-purple">Modern Purple</option>
<option value="modern-green">Modern Green</option>
<option value="modern-orange">Modern Orange</option>
Expand All @@ -1879,6 +1877,7 @@ <h3>Theme Settings</h3>
<div class="form-group">
<label for="model-background-color">Model Background Color:</label>
<select id="model-background-color">
<option value="">Match interface (Default)</option>
<option value="#070147">Dark Blue</option>
<option value="#1a1a1a">Dark Gray</option>
<option value="#000000">Black</option>
Expand Down
Binary file added logo-mark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,12 @@
"mobile-ui.css",
"styles.css",
"theme.css",
"refined.css",
"preview-wall.css",
"thumbnail-progress.css",
"thumbnail-progress.js",
"logo.png",
"logo-mark.png",
"pwa-icon-192.png",
"pwa-icon-512.png",
"apple-touch-icon.png",
Expand Down
Loading