route avatar crop and profile view through AppRoutes

This commit is contained in:
2026-07-12 23:32:48 +02:00
parent db329c7299
commit 564a334cdc
4 changed files with 33 additions and 21 deletions
+26
View File
@@ -37,8 +37,10 @@ import '../view/pages/talk/talk_navigator.dart';
import '../view/pages/ticker/ticker_page_view.dart';
import '../view/pages/timetable/custom_events/custom_events_view.dart';
import '../view/pages/timetable/subject_colors/subject_colors_view.dart';
import '../widget/avatar_crop_page.dart';
import '../widget/debug/cache_view.dart';
import '../widget/file_viewer.dart';
import '../widget/large_profile_picture_view.dart';
import '../widget/user_avatar.dart';
/// Single entry point for full-page navigations. Dialogs and bottom sheets
@@ -95,6 +97,30 @@ class AppRoutes {
pushScreen(context, withNavBar: false, screen: const SubjectColorsView());
}
/// Opens the full-screen cropper on [imageBytes] and resolves to the cropped
/// bytes (or null if cancelled). [aspectRatio] defaults to 1:1 for avatars;
/// pass null for a free-form crop (e.g. chat backgrounds).
static Future<Uint8List?> openAvatarCrop(
BuildContext context, {
required Uint8List imageBytes,
double? aspectRatio = 1,
}) {
return Navigator.of(context).push<Uint8List>(
MaterialPageRoute(
fullscreenDialog: true,
builder: (_) =>
AvatarCropPage(imageBytes: imageBytes, aspectRatio: aspectRatio),
),
);
}
/// Opens the tappable, zoomable profile-picture viewer for [id].
static void openLargeProfilePicture(BuildContext context, String id) {
Navigator.of(context).push(
MaterialPageRoute<void>(builder: (_) => LargeProfilePictureView(id: id)),
);
}
/// Opens the picker for choosing a foreign timetable element and resolves to
/// the selected element (or null if dismissed). The timetable view renders
/// the chosen plan inline. Gated behind the `viewForeignTimetables`
@@ -5,6 +5,7 @@ import '../../../../api/marianumcloud/cloud_users/cloud_users_actions.dart';
import '../../../../api/marianumconnect/queries/auth_logout/auth_logout.dart';
import '../../../../model/account_data.dart';
import '../../../../push/push_registration.dart';
import '../../../../routing/app_routes.dart';
import '../../../../state/app/modules/account/bloc/account_bloc.dart';
import '../../../../state/app/modules/account/bloc/account_state.dart';
import '../../../../widget/app_progress_indicator.dart';
@@ -12,7 +13,6 @@ import '../../../../widget/async_action_button.dart';
import '../../../../widget/avatar_actions_sheet.dart';
import '../../../../widget/confirm_dialog.dart';
import '../../../../widget/demo_restricted.dart';
import '../../../../widget/large_profile_picture_view.dart';
import '../../../../widget/user_avatar.dart';
// Display-name is process-wide stable until the user logs out; cache it so
@@ -107,12 +107,8 @@ class _AccountSectionState extends State<AccountSection> {
children: [
Center(
child: GestureDetector(
onTap: () => Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) =>
LargeProfilePictureView(id: username),
),
),
onTap: () =>
AppRoutes.openLargeProfilePicture(context, username),
child: UserAvatar(
key: ValueKey(_avatarVersion),
id: username,
+2 -7
View File
@@ -3,7 +3,7 @@ import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'avatar_crop_page.dart';
import '../routing/app_routes.dart';
import 'file_pick.dart';
/// Result of the user's choice inside [showAvatarActionsSheet]. The sheet
@@ -107,10 +107,5 @@ Future<Uint8List?> _pickAndCrop(
if (picked == null) return null;
final bytes = await picked.readAsBytes();
if (!context.mounted) return null;
return Navigator.of(context).push<Uint8List>(
MaterialPageRoute(
fullscreenDialog: true,
builder: (_) => AvatarCropPage(imageBytes: bytes),
),
);
return AppRoutes.openAvatarCrop(context, imageBytes: bytes);
}
+2 -7
View File
@@ -3,7 +3,7 @@ import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'avatar_crop_page.dart';
import '../routing/app_routes.dart';
import 'file_pick.dart';
/// Bottom sheet with "from gallery" and "take photo" actions for choosing a
@@ -61,12 +61,7 @@ Future<Uint8List?> showChatBackgroundPickerSheet(BuildContext context) async {
Future<Uint8List?> cropChatBackgroundImage(
BuildContext context,
Uint8List bytes,
) => Navigator.of(context).push<Uint8List>(
MaterialPageRoute(
fullscreenDialog: true,
builder: (_) => AvatarCropPage(imageBytes: bytes, aspectRatio: null),
),
);
) => AppRoutes.openAvatarCrop(context, imageBytes: bytes, aspectRatio: null);
Future<Uint8List?> _pickRaw(Future<XFile?> Function() pick) async {
final picked = await pick();