feat(photos): camera-or-gallery picker + swipeable full-screen viewer
- Adding a photo (quick-add and detail) now offers a Camera / Gallery chooser (shared pickPhoto helper); camera errors on desktop degrade gracefully. - Full-screen viewer: pinch-to-zoom pans only while zoomed, so a plain horizontal swipe pages between photos again. 54 tests green; Linux runs.
This commit is contained in:
parent
4b209d6752
commit
c789cd1027
8 changed files with 136 additions and 40 deletions
|
|
@ -1,46 +1,28 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
import '../data/variety_repository.dart';
|
||||
import '../i18n/strings.g.dart';
|
||||
import '../state/quick_add_cubit.dart';
|
||||
import 'photo_pick.dart';
|
||||
import 'quantity_picker.dart';
|
||||
|
||||
/// Picks a photo and returns its bytes (or null if cancelled). Injected so
|
||||
/// widget tests can supply a fake instead of the camera plugin.
|
||||
typedef PhotoPicker = Future<Uint8List?> Function();
|
||||
|
||||
Future<void> showQuickAddSheet(
|
||||
BuildContext context, {
|
||||
required VarietyRepository repository,
|
||||
PhotoPicker? photoPicker,
|
||||
}) {
|
||||
return showModalBottomSheet<void>(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (_) => BlocProvider(
|
||||
create: (_) => QuickAddCubit(repository),
|
||||
child: QuickAddSheet(photoPicker: photoPicker ?? _cameraPhotoPicker),
|
||||
child: const QuickAddSheet(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<Uint8List?> _cameraPhotoPicker() async {
|
||||
final file = await ImagePicker().pickImage(
|
||||
source: ImageSource.camera,
|
||||
maxWidth: 1280,
|
||||
imageQuality: 80,
|
||||
);
|
||||
return file?.readAsBytes();
|
||||
}
|
||||
|
||||
class QuickAddSheet extends StatelessWidget {
|
||||
const QuickAddSheet({required this.photoPicker, super.key});
|
||||
|
||||
final PhotoPicker photoPicker;
|
||||
const QuickAddSheet({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -111,7 +93,7 @@ class QuickAddSheet extends StatelessWidget {
|
|||
label: Text(t.quickAdd.more),
|
||||
),
|
||||
),
|
||||
if (state.expanded) _MoreSection(photoPicker: photoPicker),
|
||||
if (state.expanded) const _MoreSection(),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
|
|
@ -136,9 +118,7 @@ class QuickAddSheet extends StatelessWidget {
|
|||
}
|
||||
|
||||
class _MoreSection extends StatelessWidget {
|
||||
const _MoreSection({required this.photoPicker});
|
||||
|
||||
final PhotoPicker photoPicker;
|
||||
const _MoreSection();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -162,7 +142,7 @@ class _MoreSection extends StatelessWidget {
|
|||
alignment: Alignment.centerLeft,
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () async {
|
||||
final bytes = await photoPicker();
|
||||
final bytes = await pickPhoto(context);
|
||||
if (bytes != null) cubit.photoPicked(bytes);
|
||||
},
|
||||
icon: const Icon(Icons.photo_camera_outlined),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue