Skip to content

Commit ea7d4fb

Browse files
committed
profile picture correctly uploads and fetches for web
1 parent 329c482 commit ea7d4fb

3 files changed

Lines changed: 116 additions & 33 deletions

File tree

lib/core/services/supabase_service.dart

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:cookethflow/models/flow_manager.dart';
77
import 'package:cookethflow/models/flow_node.dart';
88
import 'package:file_selector/file_selector.dart';
99
import 'package:flutter/material.dart';
10+
import 'package:http/http.dart' as http;
1011
import 'package:path_provider/path_provider.dart';
1112
import 'package:supabase_flutter/supabase_flutter.dart';
1213

@@ -27,6 +28,7 @@ class SupabaseService extends StateHandler {
2728
XFile? get userPfp => _userPfp;
2829
String? get userName => _userName;
2930
String? get email => _email;
31+
String get defaultPfpPath => _defaultPfpPath;
3032

3133
void setUserData(AuthResponse user) {
3234
_userData = user;
@@ -36,6 +38,7 @@ class SupabaseService extends StateHandler {
3638

3739
void setUserPfp(XFile? val) {
3840
_userPfp = val;
41+
print('Updated userPfp: ${val?.name}');
3942
notifyListeners();
4043
}
4144

@@ -379,28 +382,41 @@ class SupabaseService extends StateHandler {
379382
try {
380383
final user = supabase.auth.currentUser;
381384
if (user == null) throw Exception('User not authenticated');
382-
final extension = imageFile.path.split('.').last.toLowerCase();
385+
386+
// Get file extension and MIME type
387+
final extension = imageFile.name.split('.').last.toLowerCase();
383388
final mimeType = _getMimeTypeFromExtension(extension);
384389
final storagePath = '${user.id}/pfp.$extension';
385390

391+
// Remove existing profile picture if it exists
386392
try {
387393
await supabase.storage
388394
.from(_profileBucketName)
389395
.remove(['${user.id}/pfp']);
390396
} catch (e) {
391-
print('No existing profile picture to remove');
397+
print('No existing profile picture to remove: $e');
392398
}
393399

394-
await supabase.storage.from(_profileBucketName).upload(
400+
// Read file bytes for web compatibility
401+
final bytes = await imageFile.readAsBytes();
402+
403+
// Upload to Supabase
404+
await supabase.storage.from(_profileBucketName).uploadBinary(
395405
storagePath,
396-
File(imageFile.path),
406+
bytes,
397407
fileOptions: FileOptions(contentType: mimeType, upsert: true),
398408
);
409+
410+
// Get public URL
399411
final String publicUrl =
400412
supabase.storage.from(_profileBucketName).getPublicUrl(storagePath);
413+
414+
// Update user table with new URL
401415
await supabase
402416
.from('User')
403417
.update({'profile_picture_url': publicUrl}).eq('id', user.id);
418+
419+
// Update local state
404420
setUserPfp(imageFile);
405421
notifyListeners();
406422
return publicUrl;
@@ -430,25 +446,23 @@ class SupabaseService extends StateHandler {
430446
const supportedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
431447

432448
if (supportedExtensions.contains(fileExtension)) {
433-
try {
434-
final response = await supabase.storage
435-
.from(_profileBucketName)
436-
.download('${user.id}/pfp.$fileExtension');
437-
final tempDir = await getTemporaryDirectory();
438-
final file = File('${tempDir.path}/pfp_${user.id}.$fileExtension');
439-
await file.writeAsBytes(response);
440-
setUserPfp(XFile(file.path));
441-
notifyListeners();
442-
return;
443-
} catch (e) {
444-
print('Error downloading profile picture: $e');
445-
}
449+
// For web, store the URL directly instead of downloading
450+
setUserPfp(XFile.fromData(
451+
await http.get(Uri.parse(pfpUrl)).then((res) => res.bodyBytes),
452+
name: 'pfp.$fileExtension',
453+
mimeType: _getMimeTypeFromExtension(fileExtension),
454+
));
455+
notifyListeners();
456+
return;
446457
}
447458
}
459+
// Fallback to default image
448460
setUserPfp(XFile(_defaultPfpPath));
461+
notifyListeners();
449462
} catch (e) {
450463
print('Error fetching profile picture: $e');
451464
setUserPfp(XFile(_defaultPfpPath));
465+
notifyListeners();
452466
}
453467
}
454468

lib/core/widgets/alert_dialogues/popup_box.dart

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import 'dart:io';
1+
import 'dart:io' show File;
22

33
import 'package:cookethflow/core/services/file_services.dart';
44
import 'package:cookethflow/core/services/supabase_service.dart';
55
import 'package:file_selector/file_selector.dart';
6+
import 'package:flutter/foundation.dart';
67
import 'package:flutter/material.dart';
78
import 'package:provider/provider.dart';
89
import 'package:phosphor_flutter/phosphor_flutter.dart';
@@ -79,18 +80,49 @@ class _ProfileDialogState extends State<ProfileDialog> {
7980
height: 150,
8081
decoration: BoxDecoration(
8182
shape: BoxShape.circle,
82-
image: DecorationImage(
83-
image: pv.userPfp != null
84-
? FileImage(File(pv.userPfp!.path))
85-
: const AssetImage('assets/Frame 268.png')
86-
as ImageProvider),
8783
border: Border.all(
8884
color: const Color.fromARGB(255, 0, 0, 0),
8985
width: 1.0,
9086
),
9187
),
9288
child: Stack(
9389
children: [
90+
ClipOval(
91+
child: pv.userPfp != null &&
92+
pv.userPfp!.path != pv.defaultPfpPath
93+
? kIsWeb
94+
? FutureBuilder<Uint8List>(
95+
future: pv.userPfp!.readAsBytes(),
96+
builder: (context, snapshot) {
97+
if (snapshot.hasData) {
98+
return Image.memory(
99+
snapshot.data!,
100+
fit: BoxFit.cover,
101+
width: 150,
102+
height: 150,
103+
);
104+
}
105+
return Image.asset(
106+
'assets/Frame 268.png',
107+
fit: BoxFit.cover,
108+
width: 150,
109+
height: 150,
110+
);
111+
},
112+
)
113+
: Image.file(
114+
File(pv.userPfp!.path),
115+
fit: BoxFit.cover,
116+
width: 150,
117+
height: 150,
118+
)
119+
: Image.asset(
120+
'assets/Frame 268.png',
121+
fit: BoxFit.cover,
122+
width: 150,
123+
height: 150,
124+
),
125+
),
94126
Positioned(
95127
right: 0,
96128
bottom: 0,
@@ -488,4 +520,4 @@ void showPasswordChangeDialog(BuildContext context) {
488520
);
489521
},
490522
);
491-
}
523+
}

lib/core/widgets/drawers/dashboard_drawer.dart

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import 'dart:io';
1+
import 'dart:io' show File;
22

33
import 'package:cookethflow/core/services/supabase_service.dart';
44
import 'package:cookethflow/core/widgets/alert_dialogues/popup_box.dart';
55
import 'package:cookethflow/screens/auth_screens/log_in.dart';
66
import 'package:cookethflow/screens/auth_screens/sign_up.dart';
7+
import 'package:flutter/foundation.dart';
78
import 'package:flutter/material.dart';
89
import 'package:phosphor_flutter/phosphor_flutter.dart';
910
import 'package:provider/provider.dart';
@@ -42,16 +43,52 @@ class DashboardDrawer extends StatelessWidget {
4243
children: [
4344
Row(
4445
children: [
45-
CircleAvatar(
46-
backgroundImage: auth.userPfp != null
47-
? FileImage(File(auth.userPfp!.path))
48-
: const AssetImage('assets/Frame 268.png')
49-
as ImageProvider,
46+
ClipOval(
47+
child: SizedBox(
48+
width: 40,
49+
height: 40,
50+
child: auth.userPfp != null &&
51+
auth.userPfp!.path !=
52+
auth.defaultPfpPath
53+
? kIsWeb
54+
? FutureBuilder<Uint8List>(
55+
future:
56+
auth.userPfp!.readAsBytes(),
57+
builder: (context, snapshot) {
58+
if (snapshot.hasData) {
59+
return Image.memory(
60+
snapshot.data!,
61+
fit: BoxFit.cover,
62+
width: 40,
63+
height: 40,
64+
);
65+
}
66+
return Image.asset(
67+
'assets/Frame 268.png',
68+
fit: BoxFit.cover,
69+
width: 40,
70+
height: 40,
71+
);
72+
},
73+
)
74+
: Image.file(
75+
File(auth.userPfp!.path),
76+
fit: BoxFit.cover,
77+
width: 40,
78+
height: 40,
79+
)
80+
: Image.asset(
81+
'assets/Frame 268.png',
82+
fit: BoxFit.cover,
83+
width: 40,
84+
height: 40,
85+
),
86+
),
5087
),
5188
const SizedBox(width: 12),
5289
Text(
53-
auth.getTruncatedText(auth.userName ?? "UserName"),
54-
// auth.userName ?? "something",
90+
auth.getTruncatedText(
91+
auth.userName ?? "UserName"),
5592
style: const TextStyle(
5693
fontFamily: 'Frederik', fontSize: 20),
5794
),
@@ -197,4 +234,4 @@ class DashboardDrawer extends StatelessWidget {
197234
},
198235
);
199236
}
200-
}
237+
}

0 commit comments

Comments
 (0)