Skip to content
Draft
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
7 changes: 7 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,13 @@ asserted in `shutdown_when_done_test.dart`:
exact vertically (stretched horizontally by SAR). The shortcuts reach the
widget's zoom through `MainViewModel.previewZoom`
(`ComparisonZoomController`); `before_after_comparison_test.dart` covers it.
- **Preview view mode (Original / Split / Processed)** is
`MainViewModel.previewViewMode` (shortcuts B / S / P), passed into the
controlled `BeforeAfterComparisonWidget`, so it survives scrubber moves and
new previews. The divider spans the full 0–1 of the panel (it was 5–95%,
which hid a typical left crop); line and handle are drawn inset at the
edges. Each mode draws only its side at its own aspect, and 1:1 measures the
frame on screen (Original: the source; otherwise the processed frame).
- **Themes** are `AppTheme` in `theme_service.dart`, persisted as `appTheme`
and provided above the MaterialApp. Theme-specific decoration beyond
`ColorScheme` (Pride's stripe) goes through the `AppDecorations` theme
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ Every filter explains in place what it does and when to use it. Where two filter
<summary><b>Preview, timeline and trimming</b></summary>

- **Click** a thumbnail to jump there, or **drag** to scrub. The transport buttons step a frame at a time or jump to either end.
- **Original / Split / Processed** (B / S / P) above the preview show either frame whole or both side by side; in Split, drag the divider all the way to either edge.
- Zoom the preview with the **mouse wheel** or **pinch**; **double-click** resets it. **1:1** shows actual pixels, the way to judge fine detail, and **Fit** shows the whole frame.
- The **mouse wheel** or **pinch** also zooms the timeline around the cursor, and **Shift+wheel** or a **two-finger swipe** pans it.
- **Set In** / **Set Out** process only part of the source, handy for trying settings on a short section.
Expand All @@ -185,6 +186,7 @@ Every button with a shortcut shows it in its tooltip, and **?** lists them all.
| Go to in / out point | ⇧I / ⇧O | Shift+I / Shift+O |
| Clear in and out points | ⌥X | Alt+X |
| Preview at actual pixels (1:1) / fit | ⌘1 / ⌘0 | Ctrl+1 / Ctrl+0 |
| Show original / split / processed | B / S / P | B / S / P |
| Zoom timeline in / out / to fit | = / - / \ | = / - / \ |
| Add videos | ⌘O | Ctrl+O |
| Start processing | ⌘↩ | Ctrl+Enter |
Expand Down
15 changes: 15 additions & 0 deletions app/lib/models/app_shortcut.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ enum AppShortcut {
alternates: [LogicalKeyboardKey.numpad0],
primary: true,
),
previewOriginal(
'Show original (before)',
AppShortcutGroup.preview,
LogicalKeyboardKey.keyB,
),
previewSplit(
'Split original / processed',
AppShortcutGroup.preview,
LogicalKeyboardKey.keyS,
),
previewProcessed(
'Show processed',
AppShortcutGroup.preview,
LogicalKeyboardKey.keyP,
),
zoomIn(
'Zoom in',
AppShortcutGroup.zoom,
Expand Down
13 changes: 13 additions & 0 deletions app/lib/viewmodels/main_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import '../services/failure_log_writer.dart';
import '../services/job_runner.dart';
import '../services/system_shutdown.dart';
import '../services/worker_manager.dart';
import '../widgets/comparison_view_mode.dart';
import '../widgets/comparison_zoom_controller.dart';

/// The display aspect a processed preview is drawn at: its stored size with
Expand Down Expand Up @@ -151,6 +152,18 @@ class MainViewModel extends ChangeNotifier {
/// view state held by the comparison; this lets the shortcuts reach it.
final ComparisonZoomController previewZoom = ComparisonZoomController();

/// Original / Split / Processed on the before/after preview. Held here, not
/// in the comparison or on a queue item, so it survives scrubber moves, new
/// previews and switching videos.
ComparisonViewMode _previewViewMode = ComparisonViewMode.split;
ComparisonViewMode get previewViewMode => _previewViewMode;

void setPreviewViewMode(ComparisonViewMode mode) {
if (mode == _previewViewMode) return;
_previewViewMode = mode;
notifyListeners();
}

// Shut down when the queue finishes (issue #123). Armed for one run only:
// _stopProcessing disarms it, so a run the user cancelled can't leave it
// armed, invisibly, for the next one.
Expand Down
4 changes: 4 additions & 0 deletions app/lib/views/main_window.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import '../services/theme_service.dart';
import '../models/app_shortcut.dart';
import '../widgets/app_shortcut_scope.dart';
import '../widgets/dynamic_range_badge.dart';
import '../widgets/comparison_view_mode.dart';
import 'keyboard_shortcuts_dialog.dart';
import 'video_file_picker.dart';
import '../viewmodels/main_viewmodel.dart';
Expand Down Expand Up @@ -112,6 +113,9 @@ class MainWindow extends StatelessWidget {
AppShortcut.previewActualSize:
whenPreviewing(viewModel.previewZoom.showActualSize),
AppShortcut.previewFit: whenPreviewing(viewModel.previewZoom.fit),
for (final mode in ComparisonViewMode.values)
mode.shortcut:
whenPreviewing(() => viewModel.setPreviewViewMode(mode)),
AppShortcut.zoomIn: whenPreviewing(viewModel.zoomIn),
AppShortcut.zoomOut: whenPreviewing(viewModel.zoomOut),
AppShortcut.zoomToFit: whenPreviewing(viewModel.resetTimelineZoom),
Expand Down
2 changes: 2 additions & 0 deletions app/lib/views/preview_panel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class _PreviewPanelState extends State<PreviewPanel> {
beforeAspectRatio: viewModel.sourceDisplayAspect,
afterAspectRatio: viewModel.comparisonAfterAspect,
zoomController: viewModel.previewZoom,
viewMode: viewModel.previewViewMode,
onViewModeChanged: viewModel.setPreviewViewMode,
),
),

Expand Down
Loading
Loading