feat(profile): User profile pic upload finished + BloC event for that

This commit is contained in:
2024-04-24 17:04:25 +03:00
parent 7680abb61b
commit 782ecbcd5c
3 changed files with 71 additions and 14 deletions

View File

@@ -1,4 +1,6 @@
//import 'package:eatvio_app/presentation/auth/auth_screen/auth_screen.dart';
import 'dart:async';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import '/core/app_export.dart';
@@ -7,6 +9,7 @@ import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:hive/hive.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:image_picker/image_picker.dart';
part 'my_profile_event.dart';
part 'my_profile_state.dart';
@@ -15,6 +18,7 @@ part 'my_profile_state.dart';
class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
MyProfileBloc(MyProfileState initialState) : super(initialState) {
on<MyProfileInitialEvent>(_onInitialize);
on<UploadAvatar>(_uploadAvatar);
}
Future<void> _onInitialize(
@@ -242,4 +246,35 @@ class MyProfileBloc extends Bloc<MyProfileEvent, MyProfileState> {
return "экстремальный (несколько интенсивных тренировок в день)";
}
} // колхоз, но свитчкейсы в дарте странно ведут себя при сравнении double
Future<void> _uploadAvatar(
UploadAvatar event, Emitter<MyProfileState> emit) async {
if (state is MyProfileLoadedState) {
var currentState = state as MyProfileLoadedState;
await uploadImageToServer(event.image.path, currentState.token);
}
}
Future<String> uploadImageToServer(String imagePath, String? token) async {
String url = '${dotenv.env['SERVER_ROOT']!}/profile/photo/upload';
print(url);
var request = http.MultipartRequest('POST', Uri.parse(url));
request.headers['Authorization'] = 'Bearer $token';
request.files.add(await http.MultipartFile.fromPath('photo', imagePath));
var client = http.Client();
var streamedResponse = await client.send(request);
if (streamedResponse.statusCode == 200) {
var response = await http.Response.fromStream(streamedResponse);
var imageUrl = response.body;
print('Image successfully uploaded');
return imageUrl;
} else {
throw Exception(
'Failed to upload image. Status code: ${streamedResponse.statusCode} ${streamedResponse}}');
}
}
}

View File

@@ -14,3 +14,10 @@ class MyProfileInitialEvent extends MyProfileEvent {
@override
List<Object?> get props => [];
}
class UploadAvatar extends MyProfileEvent {
UploadAvatar(this.image);
final XFile image;
@override
List<Object> get props => [image];
}

View File

@@ -5,6 +5,7 @@ import 'package:eatvio_app/widgets/app_bar/appbar_subtitle.dart';
import 'package:eatvio_app/widgets/custom_bottom_bar.dart';
import 'package:eatvio_app/widgets/custom_text_form_field.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:image_picker/image_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter/services.dart';
@@ -139,27 +140,41 @@ class MyProfileScreen extends StatelessWidget {
/// Section Widget
_buildInfo(BuildContext context, MyProfileLoadedState state) {
print(state.user?['profile_photo_url']);
return Column(children: [
CachedNetworkImage(
imageUrl: state.user?['profile_photo_url'],
imageBuilder: (context, imageProvider) => CircleAvatar(
backgroundImage: imageProvider,
radius: 60,
),
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => CircleAvatar(
child: Icon(Icons.person),
backgroundColor: Colors.grey[200],
radius: 60,
),
),
GestureDetector(
onTap: addImage(context),
child: CachedNetworkImage(
imageUrl:
dotenv.env['STORAGE_URL']! + state.user?['profile_photo_path'],
imageBuilder: (context, imageProvider) => CircleAvatar(
backgroundImage: imageProvider,
radius: 60,
),
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => CircleAvatar(
child: Icon(Icons.person),
backgroundColor: Colors.grey[200],
radius: 60,
),
)),
AppbarSubtitle(text: state.user?['name']),
SizedBox(height: 20.v),
Text(state.userDetails?['additional_info']),
]);
}
addImage(BuildContext context) {
return () async {
final picker = ImagePicker();
List<XFile>? images = await picker.pickMultiImage();
if (images.isNotEmpty) {
for (var image in images) {
context.read<MyProfileBloc>().add(UploadAvatar(image));
}
}
};
}
onTapSettings(BuildContext context) {
return () {
Navigator.pushNamed(context, AppRoutes.mySettings);