implemented avatar management for user profiles and chat rooms, including 1:1 cropping, integrated OCS and Spreed avatar APIs, added cache invalidation logic, and updated the account settings view to display user info and profile pictures.
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:crop_your_image/crop_your_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'app_progress_indicator.dart';
|
||||
|
||||
/// Full-screen 1:1 cropper. Pure-Flutter so it inherits the app theme and
|
||||
/// MediaQuery insets (no UCrop / native Activity needed). Returns the
|
||||
/// cropped JPEG/PNG bytes via Navigator pop, or `null` on cancel.
|
||||
class AvatarCropPage extends StatefulWidget {
|
||||
final Uint8List imageBytes;
|
||||
const AvatarCropPage({required this.imageBytes, super.key});
|
||||
|
||||
@override
|
||||
State<AvatarCropPage> createState() => _AvatarCropPageState();
|
||||
}
|
||||
|
||||
class _AvatarCropPageState extends State<AvatarCropPage> {
|
||||
final _controller = CropController();
|
||||
bool _busy = false;
|
||||
|
||||
void _confirm() {
|
||||
if (_busy) return;
|
||||
setState(() => _busy = true);
|
||||
_controller.crop();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
appBar: AppBar(
|
||||
title: const Text('Zuschneiden'),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
tooltip: 'Abbrechen',
|
||||
onPressed: _busy ? null : () => Navigator.of(context).pop(),
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: _busy
|
||||
? Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: AppProgressIndicator.small(
|
||||
color: theme.colorScheme.onSurface,
|
||||
),
|
||||
)
|
||||
: const Icon(Icons.check),
|
||||
tooltip: 'Bestätigen',
|
||||
onPressed: _busy ? null : _confirm,
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
// Pinch-Zoom (interactive: true) lässt zwei-Finger-Gesten direkt am
|
||||
// Bildschirmrand starten und triggert dann die Android-Zurückgeste.
|
||||
// Crop-Rahmen mit Eck-Dots reicht für Avatar-Auswahl völlig aus.
|
||||
child: Crop(
|
||||
image: widget.imageBytes,
|
||||
controller: _controller,
|
||||
aspectRatio: 1.0,
|
||||
interactive: false,
|
||||
baseColor: theme.colorScheme.surface,
|
||||
maskColor: Colors.black.withValues(alpha: 0.6),
|
||||
cornerDotBuilder: (size, _) =>
|
||||
DotControl(color: theme.colorScheme.primary),
|
||||
onCropped: (result) {
|
||||
if (!mounted) return;
|
||||
switch (result) {
|
||||
case CropSuccess(:final croppedImage):
|
||||
Navigator.of(context).pop(croppedImage);
|
||||
case CropFailure():
|
||||
setState(() => _busy = false);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Bild konnte nicht zugeschnitten werden'),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user