diet-guard/app/lib/screens/photo_viewer_screen.dart
Krzysztof kuhy Rudnicki feef5984f8 Add photo attach, full-size viewer, and a minimal history screen
Milestone 2 of the diet-app-as-wise-balloon plan, plus feedback from
manually testing it on-device:

- PhotoAttachService wraps image_picker and copies the picked photo into
  <app documents>/images/<uuid>.<ext>, so the file survives after the
  picker's own (possibly cache-cleared) temp copy is gone. Phone-local
  only, per the sync plan: imagePath is never synced.
- PhotoAttachField is a shared attach/preview/remove widget, used
  identically by both the single-item and composite-meal logging
  screens, so logging a multi-item meal can now carry a photo too.
- PhotoViewerScreen gives a full-screen, pinch-to-zoom view of an
  attached photo -- the 64x64 inline thumbnail was too small to
  actually check the photo.
- HistoryScreen lists every logged entry across all days, newest first,
  with a thumbnail when one is attached. There was previously no way to
  confirm what got logged (or whether a photo actually attached) short
  of inspecting food_log.json directly.

Verified on a physical device (BL9000): built, installed, and the user
confirmed the photo-attach flow logs a real entry with a real photo,
visible afterward in the new history list. 88 Flutter tests passing,
`flutter analyze` clean against very_good_analysis.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FU3f5KQ1GHXsbbSecfVEyF
2026-06-22 18:57:58 +02:00

40 lines
1.0 KiB
Dart

/// Full-screen, pinch-to-zoom view of a locally attached meal photo.
library;
import 'dart:io';
import 'package:flutter/material.dart';
/// Shows the image at [path] full-screen, with pinch-to-zoom and a back
/// button to dismiss.
class PhotoViewerScreen extends StatelessWidget {
/// Creates a [PhotoViewerScreen] for the photo at [path].
const PhotoViewerScreen({required this.path, super.key});
/// Local filesystem path to the image to display.
final String path;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.black,
foregroundColor: Colors.white,
),
body: Center(
child: InteractiveViewer(
child: Image.file(
File(path),
errorBuilder: (context, error, stackTrace) => const Icon(
Icons.broken_image,
color: Colors.white,
size: 64,
),
),
),
),
);
}
}