pogdark-app-flutter/lib/profile_screen.dart
whysman b8dd01fc37
All checks were successful
Build Flutter Web and Docker Image for Local Registry / Build Flutter Web App (push) Successful in 3m13s
Added caching of images to reduce flickering
2024-11-10 02:18:16 -05:00

163 lines
4.8 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
import 'shared_preferences_provider.dart';
class ProfileScreen extends StatefulWidget {
final bool isEditing;
final VoidCallback onClose;
const ProfileScreen(
{super.key, required this.isEditing, required this.onClose});
@override
ProfileScreenState createState() => ProfileScreenState();
}
class ProfileScreenState extends State<ProfileScreen> {
final TextEditingController _nameController = TextEditingController();
late String? imageData;
bool isNameEmpty = true;
final ImagePicker _picker = ImagePicker();
Image? _cachedImage; // Cache the Image widget
@override
void initState() {
super.initState();
final prefsProvider =
Provider.of<SharedPreferencesProvider>(context, listen: false);
_nameController.text = prefsProvider.getUserName();
imageData = prefsProvider.getUserLogo();
_cachedImage = _buildLogoImage(imageData); // Initialize the cached image
_nameController.addListener(_checkNameField);
isNameEmpty = _nameController.text.trim().isEmpty;
}
void _checkNameField() {
setState(() {
isNameEmpty = _nameController.text.trim().isEmpty;
});
}
Future<void> _pickImage() async {
final pickedFile = await _picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
late final Uint8List imageBytes;
if (kIsWeb) {
imageBytes = await pickedFile.readAsBytes();
} else {
imageBytes = await File(pickedFile.path).readAsBytes();
}
setState(() {
if (mounted) {
final prefsProvider =
Provider.of<SharedPreferencesProvider>(context, listen: false);
imageData = base64Encode(imageBytes);
prefsProvider.setUserLogo(imageData!); // Cache the image data
_cachedImage = _buildLogoImage(imageData); // Update the cached image
}
});
}
}
void _saveProfile() async {
String name = _nameController.text.trim();
if (name.isNotEmpty) {
final prefsProvider =
Provider.of<SharedPreferencesProvider>(context, listen: false);
await prefsProvider.setUserName(name);
await prefsProvider.setUserLogo(imageData);
widget.onClose();
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Name cannot be empty!')),
);
return;
}
}
@override
void dispose() {
_nameController.removeListener(_checkNameField);
_nameController.dispose();
super.dispose();
}
Image _buildLogoImage(String? logo) {
if (logo != null) {
return Image.memory(base64Decode(logo));
} else {
return Image.asset('assets/default_logo.png');
}
}
@override
Widget build(BuildContext context) {
return Center(
child: Material(
color: Colors.white,
borderRadius: BorderRadius.circular(20.0),
elevation: 10.0,
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Align(
alignment: Alignment.topRight,
child: IconButton(
icon: const Icon(Icons.close),
onPressed: isNameEmpty ? null : widget.onClose,
color: isNameEmpty ? Colors.grey : Colors.black,
),
),
Text(
widget.isEditing
? 'Edit Your Information'
: 'Tell Us About Yourself',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 20),
CircleAvatar(
radius: 50,
backgroundImage: _cachedImage?.image,
),
const SizedBox(height: 20),
TextField(
controller: _nameController,
decoration: const InputDecoration(
labelText: 'Your Pet\'s Name',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _pickImage,
child: const Text('Upload Profile Image'),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _saveProfile,
child: Text(widget.isEditing ? 'Save Changes' : 'Continue'),
),
],
),
),
),
);
}
}