switch default location from locations page

This commit is contained in:
Pranshul committed 2025-08-25 22:32:15 +05:30
1 parent d5b33d7cb2
commit cdad8865e3
23 files changed
+220 -94

No files matched your search

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+22 -2
View File
@@ -227,8 +227,18 @@ class MyApp extends StatelessWidget {
),
useMaterial3: true,
).copyWith(
textTheme: ThemeData.light().textTheme.apply(
textTheme: ThemeData.light()
.textTheme
.apply(
fontFamily: useSystemFont ? null : 'DefaultFont',
)
.copyWith(
bodyLarge: !useSystemFont
? TextStyle(fontSize: 15.5, fontFamily: 'DefaultFont')
: null,
bodyMedium: !useSystemFont
? TextStyle(fontSize: 14, fontFamily: 'DefaultFont')
: null,
),
highlightColor: Colors.transparent,
pageTransitionsTheme: const PageTransitionsTheme(
@@ -249,8 +259,18 @@ class MyApp extends StatelessWidget {
),
useMaterial3: true,
).copyWith(
textTheme: ThemeData.dark().textTheme.apply(
textTheme: ThemeData.dark()
.textTheme
.apply(
fontFamily: useSystemFont ? null : 'DefaultFont',
)
.copyWith(
bodyLarge: !useSystemFont
? TextStyle(fontSize: 15.5, fontFamily: 'DefaultFont')
: null,
bodyMedium: !useSystemFont
? TextStyle(fontSize: 14, fontFamily: 'DefaultFont')
: null,
),
highlightColor: Colors.transparent,
pageTransitionsTheme: const PageTransitionsTheme(
+4 -1
View File
@@ -597,7 +597,10 @@ class HourlyCardForecast extends StatelessWidget {
width: 5,
),
Text("hourly_forecast".tr(),
style: TextStyle(color: colorTheme.secondary, fontSize: 16)),
style: TextStyle(
color: colorTheme.secondary,
fontSize: 16,
fontWeight: FontWeight.w600)),
]),
Divider(
height: 6,
+1 -1
View File
@@ -1690,7 +1690,7 @@ class _ExtendWidgetState extends State<ExtendWidget> {
children: [
Container(
clipBehavior: Clip.hardEdge,
height: 300,
height: 305,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(18),
+3 -5
View File
@@ -261,13 +261,9 @@ class _WeatherHomeState extends State<WeatherHome> {
final now = DateTime.now();
if (lastUpdateTime != null &&
now.difference(lastUpdateTime).inMinutes < 450) {
setState(() {
_isAppFullyLoaded = true;
});
print(_isAppFullyLoaded);
_isAppFullyLoaded = true;
} else {
checkAndUpdateHomeLocation();
print(_isAppFullyLoaded);
}
}
return json.decode(cached);
@@ -285,6 +281,7 @@ class _WeatherHomeState extends State<WeatherHome> {
_isLoadingFroggy = false;
if (_istriggeredFromLocations) {
_istriggeredFromLocations = false;
_isAppFullyLoaded = true;
}
});
}
@@ -296,6 +293,7 @@ class _WeatherHomeState extends State<WeatherHome> {
_isLoadingFroggy = false;
if (_istriggeredFromLocations) {
_istriggeredFromLocations = false;
_isAppFullyLoaded = true;
}
Provider.of<ThemeController>(context, listen: false)
.setSeedColor(weatherConditionColors[newindex]);
+106 -16
View File
@@ -13,6 +13,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import '../utils/condition_label_map.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
import 'package:animations/animations.dart';
import '../widgets/dialog.dart';
class LocationsScreen extends StatefulWidget {
const LocationsScreen({super.key});
@@ -211,6 +212,7 @@ class _LocationsScreenState extends State<LocationsScreen> {
}
Widget buildDismissibleListView({Key? key}) {
final colorTheme = Theme.of(context).colorScheme;
return savedLocations.isEmpty
? const Center(child: Text("No saved locations."))
: ListView.builder(
@@ -251,6 +253,7 @@ class _LocationsScreenState extends State<LocationsScreen> {
"default_location".tr(),
style: TextStyle(
color: Theme.of(context).colorScheme.primary,
fontWeight: FontWeight.w600,
fontSize: 16),
)
],
@@ -423,27 +426,62 @@ class _LocationsScreenState extends State<LocationsScreen> {
),
),
Padding(
padding: EdgeInsets.only(left: 14, bottom: 10, top: 12),
padding: EdgeInsets.only(
left: 14, bottom: 5, top: 0, right: 14),
child: Row(
spacing: 5,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
isOnlyHomeLocation
? Text("")
: Icon(
Symbols.star,
color:
Theme.of(context).colorScheme.primary,
),
isOnlyHomeLocation
? Text("")
: Text(
"saved_locations".tr(),
style: TextStyle(
: Row(
spacing: 5,
children: [
Icon(
Symbols.star,
color: Theme.of(context)
.colorScheme
.primary,
fontSize: 16),
)
),
isOnlyHomeLocation
? Text("")
: Text(
"saved_locations".tr(),
style: TextStyle(
color: Theme.of(context)
.colorScheme
.primary,
fontWeight: FontWeight.w600,
fontSize: 16),
),
],
),
IconButton(
onPressed: () {
showMatDialog(
context: context,
title: "Info",
content: SizedBox(
height: 70 + 30,
child: Column(
children: [
Text(
"• Swipe from right to left to delete a location",
style: TextStyle(fontSize: 15),
),
Divider(
height: 16,
),
Text(
"• Hold a location to set it as default",
style:
TextStyle(fontSize: 15)),
],
)));
},
icon: Icon(
Symbols.info,
weight: 600,
))
],
)),
isOnlyHomeLocation
@@ -499,10 +537,44 @@ class _LocationsScreenState extends State<LocationsScreen> {
final isLastItem = index == savedLocations.length;
Future<Map<String, dynamic>> _getCurrentHomeInfo() async {
final prefs = await SharedPreferences.getInstance();
final homeLocationJson = prefs.getString('homeLocation');
if (homeLocationJson != null) {
final data = jsonDecode(homeLocationJson);
return {
'cacheKey': data['cacheKey'] ?? '',
'isGPS': data['isGPS'] ?? false,
'city': data['city'] ?? '',
'country': data['country'] ?? '',
};
}
return {'cacheKey': '', 'isGPS': false};
}
Future<void> setHomeLocation(
BuildContext context, SavedLocation loc) async {
final prefs = await SharedPreferences.getInstance();
final cacheKey = "${loc.city}_${loc.country}"
.toLowerCase()
.replaceAll(' ', '_');
await prefs.setString(
'homeLocation',
jsonEncode({
'city': loc.city,
'country': loc.country,
'cacheKey': cacheKey,
'lat': loc.latitude,
'lon': loc.longitude,
'isGPS': false,
}));
}
return FadeInListItem(
child: Dismissible(
key: ValueKey(
'${loc.city}-${loc.country}-${loc.latitude}-${loc.longitude}'),
'${loc.city}-${loc.country}-${loc.latitude}-${loc.longitude}-${index}'),
direction: DismissDirection.endToStart,
confirmDismiss: (direction) async {
final actualIndex = index - 1;
@@ -572,6 +644,21 @@ class _LocationsScreenState extends State<LocationsScreen> {
color:
Theme.of(context).colorScheme.surfaceContainerLow,
child: InkWell(
onLongPress: () async {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
showMatDialog(
context: context,
title: "${loc.city}, ${loc.country}",
confirmText: "Set as default",
cancelText: "Cancel",
onConfirm: () {
if (!context.mounted) return;
setHomeLocation(context, loc);
setState(() {});
},
);
},
onTap: () async {
final cacheKey = "${loc.city}_${loc.country}"
.toLowerCase()
@@ -764,7 +851,10 @@ class _LocationsScreenState extends State<LocationsScreen> {
child: ListTile(
minTileHeight: 70,
contentPadding: EdgeInsets.only(right: 16, left: 16),
leading: Icon(Symbols.location_on),
leading: Icon(
Symbols.location_on,
size: 26,
),
tileColor: Colors.transparent,
title: Text(
loc.city,
+2 -2
View File
@@ -200,14 +200,14 @@ class _SearchLocationsScreenState extends State<SearchLocationsScreen> {
TextButton(
child: Text(
"cancel".tr(),
style: TextStyle(fontSize: 16),
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
onPressed: () => Navigator.pop(context, false),
),
TextButton(
child: Text(
"save".tr(),
style: TextStyle(fontSize: 16),
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
onPressed: () => Navigator.pop(context, true),
),
+1 -1
View File
@@ -259,7 +259,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
value: SettingTileValue(currentAppfont),
dialogTitle: "App font",
initialOption: currentAppfont.toString(),
options: ["System", "Open Sans"],
options: ["System", "Nato Sans"],
onSubmitted: (value) {
context
.read<UnitSettingsNotifier>()
+53 -56
View File
@@ -35,12 +35,11 @@ class WeatherConditionAnimationMapper {
? 'assets/foreground-animations/cloudy_background.json'
: 'assets/foreground-animations/mostly_clear_night.json';
topMain = MediaQuery.of(context).padding.top + 40;
diffHeight = isDay == 1 ? 400 : 450;
diffHeight = isDay == 1 ? 400 : 450;
break;
case 3:
animationUrl =
'assets/foreground-animations/cloudy_background.json';
animationUrl = 'assets/foreground-animations/cloudy_background.json';
secondaryAnimationUrl =
'assets/foreground-animations/cloudy_background.json';
topMain = MediaQuery.of(context).padding.top + 50;
@@ -58,7 +57,7 @@ class WeatherConditionAnimationMapper {
case 56:
case 57:
animationUrl = 'assets/foreground-animations/rain_foreground.json';
topMain = 15;
topMain = 15;
break;
case 61:
@@ -67,13 +66,13 @@ class WeatherConditionAnimationMapper {
animationUrl = isDay == 1
? 'assets/foreground-animations/rain_foreground.json'
: 'assets/foreground-animations/rain_foreground.json';
topMain = 15;
topMain = 15;
break;
case 66:
case 67:
animationUrl = 'assets/foreground-animations/rain_foreground.json';
topMain = 15;
topMain = 15;
break;
case 71:
@@ -92,7 +91,7 @@ class WeatherConditionAnimationMapper {
case 81:
case 82:
animationUrl = 'assets/foreground-animations/rain_foreground.json';
topMain = 15;
topMain = 15;
break;
case 85:
@@ -104,10 +103,9 @@ class WeatherConditionAnimationMapper {
case 95:
case 96:
case 99:
animationUrl =
'assets/foreground-animations/rain_foreground.json';
secondaryAnimationUrl =
'assets/foreground-animations/thunder_background.json';
animationUrl = 'assets/foreground-animations/rain_foreground.json';
secondaryAnimationUrl =
'assets/foreground-animations/thunder_background.json';
topMain = 10;
break;
@@ -116,48 +114,48 @@ class WeatherConditionAnimationMapper {
}
if (animationUrl == null) {
return const SizedBox.shrink();
return const SizedBox.shrink();
}
if (secondaryAnimationUrl != null) {
return Positioned(
top: isSunAnim ? -MediaQuery.of(context).padding.top + 10 - (topMain ?? 0) : -MediaQuery.of(context).padding.top - (topMain ?? 0),
left: isSunAnim ? -MediaQuery.of(context).size.width * 0.12 : 0,
right: 0,
height: 300,
child: Stack(
clipBehavior: Clip.none,
children: [
Positioned.fill(
child: RepaintBoundary(
child: Lottie.asset(
animationUrl,
fit: BoxFit.cover,
repeat: true,
addRepaintBoundary: true,
if (secondaryAnimationUrl != null) {
return Positioned(
top: isSunAnim
? -MediaQuery.of(context).padding.top + 10 - (topMain ?? 0)
: -MediaQuery.of(context).padding.top - (topMain ?? 0),
left: isSunAnim ? -MediaQuery.of(context).size.width * 0.12 : 0,
right: 0,
height: 300,
child: Stack(
clipBehavior: Clip.none,
children: [
Positioned.fill(
child: RepaintBoundary(
child: Lottie.asset(
animationUrl,
fit: BoxFit.cover,
repeat: true,
addRepaintBoundary: true,
),
),
),
),
Positioned(
top: -MediaQuery.of(context).padding.top,
left: 0,
right: 0,
height: diffHeight ?? 500,
child: RepaintBoundary(
child: Lottie.asset(
secondaryAnimationUrl,
fit: BoxFit.cover,
repeat: true,
addRepaintBoundary: true,
),
),
),
],
),
Positioned(
top: -MediaQuery.of(context).padding.top,
left: 0,
right: 0,
height: diffHeight ?? 500,
child:RepaintBoundary(
child: Lottie.asset(
secondaryAnimationUrl,
fit: BoxFit.cover,
repeat: true,
addRepaintBoundary: true,
),
),
),
],
),
);
}
);
}
return Positioned(
top: -MediaQuery.of(context).padding.top - (topMain ?? 0),
@@ -165,13 +163,12 @@ if (secondaryAnimationUrl != null) {
right: 0,
height: 300,
child: RepaintBoundary(
child:Lottie.asset(
animationUrl,
fit: BoxFit.cover,
repeat: true,
),
child: Lottie.asset(
animationUrl,
fit: BoxFit.cover,
repeat: true,
),
),
);
}
}
}
+9 -3
View File
@@ -4,6 +4,7 @@ Future<void> showMatDialog({
required BuildContext context,
String title = 'Notice',
Widget? content,
IconData? icon,
String confirmText = 'OK',
VoidCallback? onConfirm,
String? cancelText,
@@ -12,20 +13,25 @@ Future<void> showMatDialog({
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
return AlertDialog.adaptive(
title: Text(title),
icon: icon == null ? null : Icon(icon),
content: content,
actions: <Widget>[
if (cancelText != null)
TextButton(
child: Text(cancelText),
child: Text(
cancelText,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
onPressed: () {
Navigator.of(context).pop();
if (onCancel != null) onCancel();
},
),
TextButton(
child: Text(confirmText),
child: Text(confirmText,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
onPressed: () {
Navigator.of(context).pop();
if (onConfirm != null) onConfirm();
+1 -1
View File
@@ -54,7 +54,7 @@ class HourlyCard extends StatelessWidget {
return Container(
decoration: BoxDecoration(
color: Color(selectedContainerBgIndex),
borderRadius: BorderRadius.circular(20),
borderRadius: BorderRadius.circular(24),
),
padding: EdgeInsets.only(top: 15, bottom: 0),
margin: EdgeInsets.fromLTRB(12, 0, 12, 0),
+4 -4
View File
@@ -98,13 +98,13 @@ flutter:
fonts:
- family: DefaultFont
fonts:
- asset: assets/fonts/OpenSans-Medium.ttf
- asset: assets/fonts/nato-Medium.ttf
weight: 400
- asset: assets/fonts/OpenSans-Medium.ttf
- asset: assets/fonts/nato-Medium.ttf
weight: 500
- asset: assets/fonts/OpenSans-SemiBold.ttf
- asset: assets/fonts/nato-SemiBold.ttf
weight: 600
- asset: assets/fonts/OpenSans-Bold.ttf
- asset: assets/fonts/nato-Bold.ttf
weight: 700
# To add assets to your application, add an assets section, like this:
# assets:
@@ -528,3 +528,14 @@ create_cxx_tasks
[gap of 36ms]
create_cxx_tasks completed in 345ms
# C/C++ build system timings
create_cxx_tasks
create-initial-cxx-model
create-module-model 38ms
create-variant-model 16ms
create-ARMEABI_V7A-model 41ms
[gap of 103ms]
create-initial-cxx-model completed in 204ms
[gap of 24ms]
create_cxx_tasks completed in 237ms
@@ -97,7 +97,7 @@ abstract class SettingTile extends StatelessWidget {
final textWidget = description as Text;
return Text(
textWidget.data ?? '',
style: textWidget.style ?? const TextStyle(fontWeight: FontWeight.w400, fontSize: 14),
style: textWidget.style ?? const TextStyle(),
maxLines: textWidget.maxLines,
overflow: textWidget.overflow,
textAlign: textWidget.textAlign,
@@ -18,7 +18,8 @@ class SettingTileValue extends StatelessWidget {
return Text(
value,
style: theme.textTheme.bodyMedium?.copyWith(color: enabled ? theme.colorScheme.tertiary : theme.disabledColor),
style: theme.textTheme.bodyMedium
?.copyWith(color: enabled ? theme.colorScheme.tertiary : theme.disabledColor, fontWeight: FontWeight.w500),
);
}
}