mirror of
https://github.com/PranshulGG/WeatherMaster.git
synced 2026-10-22 02:52:37 -05:00
switch default location from locations page
This commit is contained in:
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
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
|
||||
@@ -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>()
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+11
@@ -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),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user