Updated swiping page
parent
9c25f2402d
commit
f38493fc79
|
@ -8,7 +8,8 @@ class MatchedScreen extends StatelessWidget {
|
||||||
final VoidCallback onMessageButtonPressed;
|
final VoidCallback onMessageButtonPressed;
|
||||||
final VoidCallback onContinueButtonPressed;
|
final VoidCallback onContinueButtonPressed;
|
||||||
|
|
||||||
const MatchedScreen({super.key,
|
const MatchedScreen({
|
||||||
|
super.key,
|
||||||
required this.user1Name,
|
required this.user1Name,
|
||||||
required this.user2Name,
|
required this.user2Name,
|
||||||
required this.user1ImageUrl,
|
required this.user1ImageUrl,
|
||||||
|
@ -35,13 +36,20 @@ class MatchedScreen extends StatelessWidget {
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
// TODO imageUrl cant be null or empty with NetworkImage
|
||||||
CircleAvatar(
|
CircleAvatar(
|
||||||
backgroundImage: NetworkImage(user1ImageUrl),
|
backgroundColor: Colors.blueGrey[300],
|
||||||
|
backgroundImage: (user1ImageUrl.isEmpty)
|
||||||
|
? null
|
||||||
|
: NetworkImage(user1ImageUrl),
|
||||||
radius: 50,
|
radius: 50,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 24),
|
const SizedBox(width: 24),
|
||||||
CircleAvatar(
|
CircleAvatar(
|
||||||
backgroundImage: NetworkImage(user2ImageUrl),
|
backgroundColor: Colors.blueGrey[300],
|
||||||
|
backgroundImage: (user2ImageUrl.isEmpty)
|
||||||
|
? null
|
||||||
|
: NetworkImage(user2ImageUrl),
|
||||||
radius: 50,
|
radius: 50,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:cofounderella/components/chat_bubble.dart';
|
|
||||||
import 'package:cofounderella/components/my_textfield.dart';
|
|
||||||
import 'package:cofounderella/services/auth/auth_service.dart';
|
|
||||||
import 'package:cofounderella/services/chat/chat_service.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../components/chat_bubble.dart';
|
||||||
|
import '../components/my_textfield.dart';
|
||||||
|
import '../services/auth/auth_service.dart';
|
||||||
|
import '../services/chat/chat_service.dart';
|
||||||
|
|
||||||
class ChatPage extends StatefulWidget {
|
class ChatPage extends StatefulWidget {
|
||||||
final String receiverEmail;
|
final String receiverEmail;
|
||||||
final String receiverID;
|
final String receiverID;
|
||||||
|
@ -152,7 +153,7 @@ class _ChatPageState extends State<ChatPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ChatBubble(
|
ChatBubble(
|
||||||
message: data["message"],
|
message: data['message'],
|
||||||
isCurrentUser: isCurrentUser,
|
isCurrentUser: isCurrentUser,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -169,8 +170,8 @@ class _ChatPageState extends State<ChatPage> {
|
||||||
Expanded(
|
Expanded(
|
||||||
child: MyTextField(
|
child: MyTextField(
|
||||||
controller: _messageController,
|
controller: _messageController,
|
||||||
hintText: "Type a message",
|
hintText: 'Type a message',
|
||||||
obscureText: false, // TODO make this optional
|
obscureText: false,
|
||||||
focusNode: myFocusNode,
|
focusNode: myFocusNode,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -19,7 +19,15 @@ class UserProfilePage extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserProfilePageState extends State<UserProfilePage> {
|
class UserProfilePageState extends State<UserProfilePage> {
|
||||||
|
/// List with [all] user profiles
|
||||||
List<UserProfile> userProfiles = [];
|
List<UserProfile> userProfiles = [];
|
||||||
|
|
||||||
|
/// The current's user profile
|
||||||
|
UserProfile? currentUserProfile;
|
||||||
|
|
||||||
|
/// Other users that yet did either not receive a swipe status
|
||||||
|
List<UserProfile> potentialUserProfiles = []; // potential users for matching
|
||||||
|
|
||||||
late final SwipableStackController _controller;
|
late final SwipableStackController _controller;
|
||||||
|
|
||||||
// get instance of firestore and auth
|
// get instance of firestore and auth
|
||||||
|
@ -44,14 +52,32 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _fetchUserProfiles() async {
|
Future<void> _fetchUserProfiles() async {
|
||||||
final querySnapshot = await FirebaseFirestore.instance
|
final usersSnapshot = await FirebaseFirestore.instance
|
||||||
.collection(Constants.dbCollectionUsers)
|
.collection(Constants.dbCollectionUsers)
|
||||||
.get();
|
.get();
|
||||||
final users = await Future.wait(querySnapshot.docs.map((doc) async {
|
final String currentUserId = _authService.getCurrentUser()!.uid;
|
||||||
final languagesSnapshot =
|
|
||||||
await doc.reference.collection(Constants.dbCollectionLanguages).get();
|
// Fetch the list of profiles the current user has already swiped
|
||||||
final locationsSnapshot =
|
final QuerySnapshot swipesSnapshot = await FirebaseFirestore.instance
|
||||||
await doc.reference.collection(Constants.dbCollectionLocations).get();
|
.collection(Constants.dbCollectionUsers)
|
||||||
|
.doc(currentUserId)
|
||||||
|
.collection(Constants.dbCollectionSwipes)
|
||||||
|
.get();
|
||||||
|
final Set<String> likedUserIds = swipesSnapshot.docs
|
||||||
|
.where((doc) => doc['liked'] == true)
|
||||||
|
.map((doc) => doc.id)
|
||||||
|
.toSet();
|
||||||
|
|
||||||
|
List<UserProfile> allUsers = [];
|
||||||
|
List<UserProfile> showProfiles = [];
|
||||||
|
|
||||||
|
for (var userDoc in usersSnapshot.docs) {
|
||||||
|
final languagesSnapshot = await userDoc.reference
|
||||||
|
.collection(Constants.dbCollectionLanguages)
|
||||||
|
.get();
|
||||||
|
final locationsSnapshot = await userDoc.reference
|
||||||
|
.collection(Constants.dbCollectionLocations)
|
||||||
|
.get();
|
||||||
|
|
||||||
final languages = languagesSnapshot.docs.map((doc) {
|
final languages = languagesSnapshot.docs.map((doc) {
|
||||||
final data = doc.data();
|
final data = doc.data();
|
||||||
|
@ -63,13 +89,10 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
final mainDoc = locationsSnapshot.docs.firstWhereOrNull(
|
final mainDoc = locationsSnapshot.docs
|
||||||
(doc) => doc.id == Constants.dbDocMainLocation,
|
.firstWhereOrNull((doc) => doc.id == Constants.dbDocMainLocation);
|
||||||
);
|
final secondaryDoc = locationsSnapshot.docs
|
||||||
final secondaryDoc = locationsSnapshot.docs.firstWhereOrNull(
|
.firstWhereOrNull((doc) => doc.id == Constants.dbDocSecondLocation);
|
||||||
(doc) => doc.id == Constants.dbDocSecondLocation,
|
|
||||||
);
|
|
||||||
|
|
||||||
final locations = {
|
final locations = {
|
||||||
Constants.dbDocMainLocation:
|
Constants.dbDocMainLocation:
|
||||||
mainDoc != null ? _createLocationFromDoc(mainDoc.data()) : null,
|
mainDoc != null ? _createLocationFromDoc(mainDoc.data()) : null,
|
||||||
|
@ -78,9 +101,9 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
: null,
|
: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
final data = doc.data();
|
final data = userDoc.data();
|
||||||
return UserProfile(
|
UserProfile userProfile = UserProfile(
|
||||||
id: doc.id,
|
id: userDoc.id,
|
||||||
uid: data[Constants.dbFieldUsersID] ?? '',
|
uid: data[Constants.dbFieldUsersID] ?? '',
|
||||||
email: data[Constants.dbFieldUsersEmail] ?? '',
|
email: data[Constants.dbFieldUsersEmail] ?? '',
|
||||||
name: data[Constants.dbFieldUsersName] ?? '',
|
name: data[Constants.dbFieldUsersName] ?? '',
|
||||||
|
@ -93,12 +116,22 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
languages: languages,
|
languages: languages,
|
||||||
locations: locations,
|
locations: locations,
|
||||||
);
|
);
|
||||||
}).toList());
|
|
||||||
|
// add profiles accordingly
|
||||||
|
allUsers.add(userProfile);
|
||||||
|
// Exclude the current user's profile and the already liked profiles
|
||||||
|
if (userDoc.id != currentUserId && !likedUserIds.contains(userDoc.id)) {
|
||||||
|
showProfiles.add(userProfile);
|
||||||
|
}
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
userProfiles = users;
|
userProfiles = allUsers;
|
||||||
|
potentialUserProfiles = showProfiles;
|
||||||
|
currentUserProfile =
|
||||||
|
allUsers.firstWhereOrNull((x) => x.uid == currentUserId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MyLocation? _createLocationFromDoc(Map<String, dynamic>? data) {
|
MyLocation? _createLocationFromDoc(Map<String, dynamic>? data) {
|
||||||
if (data == null || data.isEmpty) return null;
|
if (data == null || data.isEmpty) return null;
|
||||||
|
@ -117,7 +150,7 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
|
|
||||||
void _swipeLeft() {
|
void _swipeLeft() {
|
||||||
_controller.next(
|
_controller.next(
|
||||||
swipeDirection: SwipeDirection.left, duration: Durations.extralong4);
|
swipeDirection: SwipeDirection.left, duration: Durations.extralong1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _swipeRight() {
|
void _swipeRight() {
|
||||||
|
@ -127,7 +160,7 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
|
|
||||||
void _skip() {
|
void _skip() {
|
||||||
_controller.next(
|
_controller.next(
|
||||||
swipeDirection: SwipeDirection.up, duration: Durations.extralong2);
|
swipeDirection: SwipeDirection.up, duration: Durations.long4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save swipe status to database
|
/// Save swipe status to database
|
||||||
|
@ -151,7 +184,7 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
return userProfiles.firstWhere((x) => x.uid == userId);
|
return userProfiles.firstWhere((x) => x.uid == userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether the swiped user has also swiped current user to the right
|
/// Check whether the swiped user has also swiped to the right
|
||||||
Future<void> _checkForMatch(swipedUserId) async {
|
Future<void> _checkForMatch(swipedUserId) async {
|
||||||
String currentUserId = _authService.getCurrentUser()!.uid;
|
String currentUserId = _authService.getCurrentUser()!.uid;
|
||||||
|
|
||||||
|
@ -185,11 +218,8 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
// TODO Notification and further logic, e.g. initialization of the chat
|
// TODO Notify other user?
|
||||||
//
|
//
|
||||||
print(
|
|
||||||
'We have a match between ${getUserProfile(currentUserId).name} and ${getUserProfile(swipedUserId).name}');
|
|
||||||
|
|
||||||
showMatchedScreen(currentUserId, swipedUserId);
|
showMatchedScreen(currentUserId, swipedUserId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,10 +258,32 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (userProfiles.isEmpty) {
|
if (potentialUserProfiles.isEmpty) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('User Profiles')),
|
appBar: AppBar(title: const Text('User Profiles')),
|
||||||
body: const Center(child: CircularProgressIndicator()),
|
body: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.person_search, size: 64),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Text(
|
||||||
|
'${userProfiles.length > 1 ? 'No new' : 'No'} profiles available at the moment.',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold, fontSize: 18),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 60),
|
||||||
|
const Text(
|
||||||
|
'Please check back later, perhaps tomorrow.',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,13 +305,14 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
stackClipBehaviour: Clip.none,
|
stackClipBehaviour: Clip.none,
|
||||||
swipeAnchor: SwipeAnchor.bottom,
|
swipeAnchor: SwipeAnchor.bottom,
|
||||||
itemCount: userProfiles.length+1, // +1 for rerun option
|
// item count +1 for additional end page
|
||||||
|
itemCount: potentialUserProfiles.length + 1,
|
||||||
onSwipeCompleted: (index, direction) {
|
onSwipeCompleted: (index, direction) {
|
||||||
//
|
//
|
||||||
// Swipe logic goes here
|
// Swipe logic
|
||||||
//
|
//
|
||||||
String swipedUserId =
|
String swipedUserId =
|
||||||
userProfiles[_controller.currentIndex].id;
|
potentialUserProfiles[_controller.currentIndex].id;
|
||||||
if (direction == SwipeDirection.right) {
|
if (direction == SwipeDirection.right) {
|
||||||
_saveSwipeAction(swipedUserId, SwipeDirection.right);
|
_saveSwipeAction(swipedUserId, SwipeDirection.right);
|
||||||
_checkForMatch(swipedUserId);
|
_checkForMatch(swipedUserId);
|
||||||
|
@ -269,40 +322,15 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
},
|
},
|
||||||
horizontalSwipeThreshold: 0.8,
|
horizontalSwipeThreshold: 0.8,
|
||||||
verticalSwipeThreshold: 0.8,
|
verticalSwipeThreshold: 0.8,
|
||||||
/*overlayBuilder: (context, properties) {
|
|
||||||
final opacity = min(properties.swipeProgress, 1.0);
|
|
||||||
final isRight = properties.direction == SwipeDirection.right;
|
|
||||||
return Opacity(
|
|
||||||
opacity: isRight ? opacity : 0,
|
|
||||||
child: CardLabel.right(),
|
|
||||||
);
|
|
||||||
},*/
|
|
||||||
builder: (context, properties) {
|
builder: (context, properties) {
|
||||||
|
if (properties.index == potentialUserProfiles.length) {
|
||||||
if (properties.index == userProfiles.length) {
|
|
||||||
return Center(
|
return Center(
|
||||||
child: Column( // Show end message and restart button
|
child: _buildLastCard(), // last card
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const Text('That\'s all.\nDo you want to do another run?',
|
|
||||||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)
|
|
||||||
),
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
_controller.currentIndex = 0; // Restart swiping from the beginning
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: const Text('Rerun'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final userProfile =
|
final userProfile = potentialUserProfiles[
|
||||||
userProfiles[properties.index % userProfiles.length];
|
properties.index % potentialUserProfiles.length];
|
||||||
return Container(
|
return Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
@ -311,34 +339,7 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
),
|
),
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Card(
|
_buildUserCard(userProfile),
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text(userProfile.name,
|
|
||||||
style: const TextStyle(fontSize: 24)),
|
|
||||||
Text(userProfile.email,
|
|
||||||
style: const TextStyle(fontSize: 24)),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Text(
|
|
||||||
'Has skills and experience in: ${userProfile.skills.join(', ')}'),
|
|
||||||
Text(
|
|
||||||
'Seeks someone with skills in: ${userProfile.skillsSought.join(', ')}'),
|
|
||||||
Text('Risk type: ${userProfile.risk}'),
|
|
||||||
Text(
|
|
||||||
'Speaks: ${userProfile.languages.map((lang) => lang.name).join(', ')}'),
|
|
||||||
Text(
|
|
||||||
'Lives in: ${userProfile.locations['main']?.locality ?? 'N/A'}'),
|
|
||||||
Text(
|
|
||||||
'Second home: ${userProfile.locations['secondary']?.locality ?? 'N/A'}'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (properties.stackIndex == 0 &&
|
if (properties.stackIndex == 0 &&
|
||||||
properties.direction != null)
|
properties.direction != null)
|
||||||
CardOverlay(
|
CardOverlay(
|
||||||
|
@ -352,7 +353,78 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Positioned(
|
_buildSwipeButtons(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildUserCard(UserProfile userProfile) {
|
||||||
|
return Card(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(userProfile.name, style: const TextStyle(fontSize: 24)),
|
||||||
|
Text(userProfile.email, style: const TextStyle(fontSize: 24)),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
'Has skills and experience in: ${userProfile.skills.join(', ')}'),
|
||||||
|
Text(
|
||||||
|
'Seeks someone with skills in: ${userProfile.skillsSought.join(', ')}'),
|
||||||
|
Text('Risk type: ${userProfile.risk}'),
|
||||||
|
Text(
|
||||||
|
'Speaks: ${userProfile.languages.map((lang) => lang.name).join(', ')}'),
|
||||||
|
Text(
|
||||||
|
'Lives in: ${userProfile.locations[Constants.dbDocMainLocation]?.locality ?? 'N/A'}'),
|
||||||
|
Text(
|
||||||
|
'Second home: ${userProfile.locations[Constants.dbDocSecondLocation]?.locality ?? 'N/A'}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildLastCard() {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
// Show reached end message and restart button
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.person_search, size: 64),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
const Text('You\'ve viewed all available profiles.',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
|
||||||
|
const SizedBox(height: 60),
|
||||||
|
const Text(
|
||||||
|
'Would you like to do another run and see the remaining profiles again?',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
// Restart swiping from the beginning
|
||||||
|
_controller.currentIndex = 0;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: const Text('Another run'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSwipeButtons() {
|
||||||
|
return Positioned(
|
||||||
bottom: 16,
|
bottom: 16,
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
|
@ -360,6 +432,7 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
|
heroTag: 'myFABUndo',
|
||||||
tooltip: 'Undo last action',
|
tooltip: 'Undo last action',
|
||||||
shape: const CircleBorder(),
|
shape: const CircleBorder(),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
@ -371,34 +444,59 @@ class UserProfilePageState extends State<UserProfilePage> {
|
||||||
width: 72,
|
width: 72,
|
||||||
height: 72,
|
height: 72,
|
||||||
child: FloatingActionButton(
|
child: FloatingActionButton(
|
||||||
|
heroTag: 'myFABSwipeLeft',
|
||||||
shape: const CircleBorder(),
|
shape: const CircleBorder(),
|
||||||
onPressed: _swipeLeft,
|
onPressed: _swipeLeft,
|
||||||
child:
|
child: Stack(
|
||||||
const Icon(Icons.cancel, color: Colors.red, size: 64),
|
// to deal with icons inner transparency
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 48.0,
|
||||||
|
height: 48.0,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white70,
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Icon(Icons.cancel, color: Colors.red, size: 72),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 72,
|
width: 72,
|
||||||
height: 72,
|
height: 72,
|
||||||
child: FloatingActionButton(
|
child: FloatingActionButton(
|
||||||
|
heroTag: 'myFABSwipeRight',
|
||||||
shape: const CircleBorder(),
|
shape: const CircleBorder(),
|
||||||
onPressed: _swipeRight,
|
onPressed: _swipeRight,
|
||||||
child: const Icon(Icons.check_circle,
|
child: Stack(
|
||||||
color: Colors.green, size: 64),
|
// to deal with icons inner transparency
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 48.0,
|
||||||
|
height: 48.0,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white70,
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Icon(Icons.check_circle, color: Colors.green, size: 72),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
tooltip: 'Skip profile',
|
tooltip: 'Skip profile',
|
||||||
|
heroTag: 'myFABSkip',
|
||||||
shape: const CircleBorder(),
|
shape: const CircleBorder(),
|
||||||
onPressed: _skip,
|
onPressed: _skip,
|
||||||
child: const Icon(Icons.skip_next),
|
child: const Icon(Icons.skip_next),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,9 +525,9 @@ class CardOverlay extends StatelessWidget {
|
||||||
: Alignment.center),
|
: Alignment.center),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
direction == SwipeDirection.right
|
direction == SwipeDirection.right
|
||||||
? Icons.check_circle
|
? Icons.thumb_up
|
||||||
: (direction == SwipeDirection.left
|
: (direction == SwipeDirection.left
|
||||||
? Icons.cancel
|
? Icons.thumb_down
|
||||||
: Icons.skip_next),
|
: Icons.skip_next),
|
||||||
size: 100,
|
size: 100,
|
||||||
color: direction == SwipeDirection.right
|
color: direction == SwipeDirection.right
|
||||||
|
|
Loading…
Reference in New Issue