Added Settings Option to show only profiles from the same country.

master
Rafael 2024-08-16 13:55:11 +02:00
parent d567956d90
commit 77ffb5ffcf
7 changed files with 294 additions and 32 deletions

View File

@ -69,4 +69,5 @@ class Constants {
static const String pathLanguagesJson = 'lib/assets/languages.json';
static const String prefKeyThemeDarkMode = 'theme_dark_mode';
static const String prefKeySameCountry = 'match_same_country';
}

View File

@ -12,6 +12,7 @@ import 'pages/liked_users_page.dart';
import 'pages/user_matching_page.dart';
import 'pages/user_profile_page.dart';
import 'services/swipe_stream_service.dart';
import 'settings/settings_provider.dart';
void main() async {
// Firebase stuff
@ -23,6 +24,7 @@ void main() async {
// Init SharedPreferences
final prefs = await SharedPreferences.getInstance();
final isDarkMode = prefs.getBool(Constants.prefKeyThemeDarkMode) ?? false;
final onlySameCountry = prefs.getBool(Constants.prefKeySameCountry) ?? false;
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
@ -70,6 +72,10 @@ void main() async {
create: (context) => ThemeProvider(initialIsDarkMode: isDarkMode)),
Provider<FlutterLocalNotificationsPlugin>.value(
value: flutterLocalNotificationsPlugin),
ChangeNotifierProvider(
create: (context) =>
SettingsProvider(showSameCountry: onlySameCountry),
),
],
child: const MyApp(),
),

View File

@ -3,6 +3,8 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../settings/settings_provider.dart';
class SettingsPage extends StatelessWidget {
const SettingsPage({super.key});
@ -13,12 +15,15 @@ class SettingsPage extends StatelessWidget {
appBar: AppBar(
title: const Text("Settings"),
),
body: Container(
body: SingleChildScrollView(
child: Column(
children: [
Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.secondaryContainer,
borderRadius: BorderRadius.circular(12),
),
margin: const EdgeInsets.all(25),
margin: const EdgeInsets.all(16),
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -38,6 +43,37 @@ class SettingsPage extends StatelessWidget {
],
),
),
Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.secondaryContainer,
borderRadius: BorderRadius.circular(12),
),
margin: const EdgeInsets.all(16),
padding: const EdgeInsets.all(16),
child: Consumer<SettingsProvider>(
builder: (context, settingsProvider, child) {
return Padding(
padding: const EdgeInsets.all(0.0),
child: Column(
children: settingsProvider.settingsOptions.map((option) {
return SwitchListTile(
title: Text(option.title),
subtitle: (option.subtitle.isNotEmpty
? Text(option.subtitle)
: null),
value: option.getValue(),
onChanged: option.onChanged,
contentPadding: EdgeInsets.zero,
);
}).toList(),
),
);
},
),
),
],
),
),
);
}
}

View File

@ -2,6 +2,7 @@ import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:percent_indicator/circular_percent_indicator.dart';
import 'package:provider/provider.dart';
import 'package:swipable_stack/swipable_stack.dart';
import '../components/card_overlay.dart';
@ -14,7 +15,9 @@ import '../models/user_profile.dart';
import '../services/auth/auth_service.dart';
import '../services/swipe_stream_service.dart';
import '../services/user_service.dart';
import '../settings/settings_provider.dart';
import '../utils/helper.dart';
import '../utils/helper_locations.dart';
import '../utils/list_utils.dart';
import '../utils/math.dart';
import 'chat_page.dart';
@ -37,6 +40,7 @@ class UserMatchingPageState extends State<UserMatchingPage> {
List<UserProfile> potentialUserProfiles = [];
late final SwipableStackController _controller;
late final bool _showSameCountry;
// get instance of firestore and auth
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
@ -48,6 +52,8 @@ class UserMatchingPageState extends State<UserMatchingPage> {
void initState() {
super.initState();
_controller = SwipableStackController()..addListener(_listenController);
_showSameCountry =
Provider.of<SettingsProvider>(context, listen: false).showSameCountry;
_fetchUserProfiles();
}
@ -91,6 +97,17 @@ class UserMatchingPageState extends State<UserMatchingPage> {
.map((doc) => doc.id)
.toSet();
// Fetch the current user's location
QuerySnapshot locationSnapshot = await _firestore
.collection(Constants.dbCollectionUsers)
.doc(currentUserId)
.collection(Constants.dbCollectionLocations)
.get();
List<String?> userLoc = [];
for (var doc in locationSnapshot.docs) {
userLoc.add(getCountryIsoCode(doc[Constants.dbFieldLocationCountry]));
}
for (var userDoc in usersSnapshot.docs) {
UserProfile userProfile =
await UserService.getUserProfileFromDocument(userDoc);
@ -99,12 +116,20 @@ class UserMatchingPageState extends State<UserMatchingPage> {
allUsers.add(userProfile);
// Exclude (1) the current user's profile, (2) the already liked profiles
// (3) users that were disliked less than 24 hours ago
// and (4) not active profile
// and (4) not active profiles
if (userDoc.id != currentUserId &&
!likedUserIds.contains(userDoc.id) &&
!dislikedUserIds.contains(userDoc.id) &&
(userProfile.active ?? false)) {
showProfiles.add(userProfile);
// (5) apply additional settings
if (_showSameCountry &&
userProfile.locations.values.firstWhereOrNull((x) =>
x != null &&
userLoc.contains(getCountryIsoCode(x.country))) ==
null) {
showProfiles.remove(userProfile);
}
}
} // end for
@ -284,7 +309,7 @@ class UserMatchingPageState extends State<UserMatchingPage> {
}
return Scaffold(
appBar: AppBar(title: const Text('Find your Match')),
appBar: AppBar(title: const Text('Swipe and Find your Match')),
body: SafeArea(
top: false,
child: Stack(
@ -534,9 +559,9 @@ class UserMatchingPageState extends State<UserMatchingPage> {
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
/*FloatingActionButton(
heroTag: 'myFABUndo',
tooltip: 'Undo last action',
shape: const CircleBorder(),
@ -544,12 +569,13 @@ class UserMatchingPageState extends State<UserMatchingPage> {
_controller.rewind(duration: Durations.extralong4);
},
child: const Icon(Icons.undo),
),
),*/
SizedBox(
width: 72,
height: 72,
child: FloatingActionButton(
heroTag: 'myFABSwipeLeft',
tooltip: 'Does not fit',
shape: const CircleBorder(),
onPressed: _swipeLeft,
child: Stack(
@ -569,11 +595,22 @@ class UserMatchingPageState extends State<UserMatchingPage> {
),
),
),
const SizedBox(width: 12),
FloatingActionButton.extended(
//icon: const Icon(Icons.skip_next),
label: const Text('Skip'),
tooltip: 'Skip profile',
heroTag: 'myFABSkip',
shape: const CircleBorder(),
onPressed: _skip,
),
const SizedBox(width: 12),
SizedBox(
width: 72,
height: 72,
child: FloatingActionButton(
heroTag: 'myFABSwipeRight',
tooltip: "Interesting",
shape: const CircleBorder(),
onPressed: _swipeRight,
child: Stack(
@ -593,13 +630,6 @@ class UserMatchingPageState extends State<UserMatchingPage> {
),
),
),
FloatingActionButton(
tooltip: 'Skip profile',
heroTag: 'myFABSkip',
shape: const CircleBorder(),
onPressed: _skip,
child: const Icon(Icons.skip_next),
),
],
),
);

View File

@ -0,0 +1,13 @@
class SettingsOption {
final String title;
final String subtitle;
final bool Function() getValue;
final void Function(bool) onChanged;
SettingsOption({
required this.title,
this.subtitle = '',
required this.getValue,
required this.onChanged,
});
}

View File

@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../constants.dart';
import 'settings_options.dart';
class SettingsProvider extends ChangeNotifier {
bool showSameCountry;
SettingsProvider({
this.showSameCountry = false, // default value
});
void toggleShowSameCountries() async {
showSameCountry = !showSameCountry;
notifyListeners();
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool(Constants.prefKeySameCountry, showSameCountry);
}
List<SettingsOption> get settingsOptions => [
SettingsOption(
title: "Match within my country",
subtitle: 'Show profiles from your country only',
getValue: () => showSameCountry,
onChanged: (value) => toggleShowSameCountries(),
),
];
}

View File

@ -0,0 +1,146 @@
Map<String, String> countryToIsoCode = {
// Europe
'Germany': 'DE',
'Deutschland': 'DE',
'Österreich': 'AT',
'Austria': 'AT',
'Belgien': 'BE',
'Belgium': 'BE',
'Belgique': 'BE',
'België': 'BE',
'Bulgarien': 'BG',
'Bulgaria': 'BG',
'България': 'BG',
'Kroatien': 'HR',
'Croatia': 'HR',
'Hrvatska': 'HR',
'Zypern': 'CY',
'Cyprus': 'CY',
'Κύπρος': 'CY',
'Tschechien': 'CZ',
'Czech Republic': 'CZ',
'Česká republika': 'CZ',
'Dänemark': 'DK',
'Denmark': 'DK',
'Danmark': 'DK',
'Estland': 'EE',
'Estonia': 'EE',
'Eesti': 'EE',
'Finnland': 'FI',
'Finland': 'FI',
'Suomi': 'FI',
'Frankreich': 'FR',
'France': 'FR',
'Griechenland': 'GR',
'Greece': 'GR',
'Ελλάδα': 'GR',
'Ungarn': 'HU',
'Hungary': 'HU',
'Magyarország': 'HU',
'Island': 'IS',
'Iceland': 'IS',
'Ísland': 'IS',
'Irland': 'IE',
'Ireland': 'IE',
'Éire': 'IE',
'Italien': 'IT',
'Italy': 'IT',
'Italia': 'IT',
'Lettland': 'LV',
'Latvia': 'LV',
'Latvija': 'LV',
'Litauen': 'LT',
'Lithuania': 'LT',
'Lietuva': 'LT',
'Luxemburg': 'LU',
'Luxembourg': 'LU',
'Malta': 'MT',
'Netherlands': 'NL',
'Niederlande': 'NL',
'Nederland': 'NL',
'Polen': 'PL',
'Poland': 'PL',
'Polska': 'PL',
'Portugal': 'PT',
'Rumänien': 'RO',
'Romania': 'RO',
'România': 'RO',
'Slowakei': 'SK',
'Slovakia': 'SK',
'Slovensko': 'SK',
'Slowenien': 'SI',
'Slovenia': 'SI',
'Slovenija': 'SI',
'Spanien': 'ES',
'Spain': 'ES',
'España': 'ES',
'Schweden': 'SE',
'Sweden': 'SE',
'Sverige': 'SE',
'Schweiz': 'CH',
'Switzerland': 'CH',
'Suisse': 'CH',
'Svizzera': 'CH',
'Беларусь': 'BY',
'Belarus': 'BY',
'Weißrussland': 'BY',
'Bosnien und Herzegowina': 'BA',
'Bosnia and Herzegovina': 'BA',
'Bosna i Hercegovina': 'BA',
'Nordmazedonien': 'MK',
'North Macedonia': 'MK',
'Северна Македонија': 'MK',
'Serbien': 'RS',
'Serbia': 'RS',
'Србија': 'RS',
'Montenegro': 'ME',
'Albanien': 'AL',
'Albania': 'AL',
'Shqipëri': 'AL',
'Türkei': 'TR',
'Turkey': 'TR',
'Türkiye': 'TR',
'Russland': 'RU',
'Russia': 'RU',
'Россия': 'RU',
'Ukraine': 'UA',
'Україна': 'UA',
// Asia
'China': 'CN',
'中国': 'CN',
'Zhōngguó': 'CN',
'Japan': 'JP',
'日本': 'JP',
'Nihon': 'JP',
'Südkorea': 'KR',
'South Korea': 'KR',
'대한민국': 'KR',
'Daehanminguk': 'KR',
'Indien': 'IN',
'India': 'IN',
'भारत': 'IN',
'Bhārat': 'IN',
// North America
'Kanada': 'CA',
'Canada': 'CA',
'Mexiko': 'MX',
'Mexico': 'MX',
'Estados Unidos Mexicanos': 'MX',
'Vereinigte Staaten': 'US',
'United States': 'US',
'USA': 'US',
};
String getCountryIsoCode(String country) {
return countryToIsoCode[country] ?? country;
}
bool compareCountries(String country1, String country2) {
if (getCountryIsoCode(country1) == getCountryIsoCode(country2)) {
return true;
} else {
return false;
}
}