This commit is contained in:
Yoshi 2023-07-10 21:33:43 +03:00
parent c9f848254f
commit 562849bc9e
30 changed files with 1174 additions and 1278 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -201,25 +201,18 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
splashColor: Colors.transparent, splashColor: Colors.transparent,
highlightColor: Colors.transparent, highlightColor: Colors.transparent,
), ),
child: Container( child: TabBar(
height: 60, controller: tabController,
decoration: BoxDecoration( dividerColor: Colors.transparent,
color: context.theme.bottomNavigationBarTheme.backgroundColor, indicator: const UnderlineTabIndicator(borderSide: BorderSide.none),
), labelColor: Colors.blueAccent,
child: TabBar( unselectedLabelColor: Colors.grey,
controller: tabController, onTap: (int index) => changeTabIndex(index),
dividerColor: Colors.transparent, tabs: const [
indicator: Tab(icon: Icon(Iconsax.cloud_sunny)),
const UnderlineTabIndicator(borderSide: BorderSide.none), Tab(icon: Icon(Iconsax.global)),
labelColor: Colors.blueAccent, Tab(icon: Icon(Iconsax.setting_2)),
unselectedLabelColor: Colors.grey, ],
onTap: (int index) => changeTabIndex(index),
tabs: const [
Tab(icon: Icon(Iconsax.cloud_sunny)),
Tab(icon: Icon(Iconsax.global)),
Tab(icon: Icon(Iconsax.setting_2)),
],
),
), ),
), ),
floatingActionButton: tabIndex == 1 floatingActionButton: tabIndex == 1
@ -233,7 +226,6 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
return const CreateWeatherCard(); return const CreateWeatherCard();
}, },
), ),
backgroundColor: context.theme.colorScheme.tertiaryContainer,
child: const Icon(Iconsax.add), child: const Icon(Iconsax.add),
) )
: null, : null,

View file

@ -62,79 +62,67 @@ class _SettingsPageState extends State<SettingsPage> {
builder: (BuildContext context) { builder: (BuildContext context) {
return StatefulBuilder( return StatefulBuilder(
builder: (BuildContext context, setState) { builder: (BuildContext context, setState) {
return Container( return Column(
decoration: BoxDecoration( crossAxisAlignment: CrossAxisAlignment.center,
color: context.theme.colorScheme.secondaryContainer, mainAxisSize: MainAxisSize.min,
borderRadius: const BorderRadius.only( children: [
topLeft: Radius.circular(20), Padding(
topRight: Radius.circular(20), padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 15),
child: Text(
'appearance'.tr,
style: context.textTheme.titleLarge,
),
), ),
), SettingLinks(
child: Column( icon: Icon(
crossAxisAlignment: CrossAxisAlignment.center, Iconsax.moon,
mainAxisSize: MainAxisSize.min, color: context.theme.iconTheme.color,
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 15),
child: Text(
'appearance'.tr,
style: context.textTheme.titleLarge,
),
), ),
SettingLinks( text: 'theme'.tr,
icon: Icon( switcher: true,
Iconsax.moon, value: Get.isDarkMode,
color: context.theme.iconTheme.color, onChange: (_) {
), if (Get.isDarkMode) {
text: 'theme'.tr, themeController
switcher: true, .changeThemeMode(ThemeMode.light);
value: Get.isDarkMode, themeController.saveTheme(false);
onChange: (_) { } else {
if (Get.isDarkMode) { themeController.changeThemeMode(ThemeMode.dark);
themeController themeController.saveTheme(true);
.changeThemeMode(ThemeMode.light); }
themeController.saveTheme(false); },
} else { ),
themeController SettingLinks(
.changeThemeMode(ThemeMode.dark); icon: Icon(
themeController.saveTheme(true); Iconsax.mobile,
} color: context.theme.iconTheme.color,
},
), ),
SettingLinks( text: 'amoledTheme'.tr,
icon: Icon( switcher: true,
Iconsax.mobile, value: settings.amoledTheme,
color: context.theme.iconTheme.color, onChange: (value) {
), themeController.saveOledTheme(value);
text: 'amoledTheme'.tr, MyApp.updateAppState(context,
switcher: true, newAmoledTheme: value);
value: settings.amoledTheme, },
onChange: (value) { ),
themeController.saveOledTheme(value); SettingLinks(
MyApp.updateAppState(context, icon: Icon(
newAmoledTheme: value); Iconsax.colorfilter,
}, color: context.theme.iconTheme.color,
), ),
// SettingLinks( text: 'materialColor'.tr,
// icon: Icon( switcher: true,
// Iconsax.colorfilter, value: settings.materialColor,
// color: context.theme.iconTheme.color, onChange: (value) {
// ), themeController.saveMaterialTheme(value);
// text: 'materialColor'.tr, MyApp.updateAppState(context,
// switcher: true, newMaterialColor: value);
// value: settings.materialColor, },
// onChange: (value) { ),
// isar.writeTxn(() async { const SizedBox(height: 10),
// settings.materialColor = value; ],
// isar.settings.put(settings);
// });
// setState(() {});
// },
// ),
const SizedBox(height: 10),
],
),
); );
}, },
); );
@ -155,149 +143,138 @@ class _SettingsPageState extends State<SettingsPage> {
builder: (BuildContext context) { builder: (BuildContext context) {
return StatefulBuilder( return StatefulBuilder(
builder: (BuildContext context, setState) { builder: (BuildContext context, setState) {
return Container( return Column(
decoration: BoxDecoration( crossAxisAlignment: CrossAxisAlignment.center,
color: context.theme.colorScheme.secondaryContainer, mainAxisSize: MainAxisSize.min,
borderRadius: const BorderRadius.only( children: [
topLeft: Radius.circular(20), Padding(
topRight: Radius.circular(20), padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 15),
child: Text(
'functions'.tr,
style: context.textTheme.titleLarge,
),
), ),
), SettingLinks(
child: Column( icon: Icon(
crossAxisAlignment: CrossAxisAlignment.center, Iconsax.map_1,
mainAxisSize: MainAxisSize.min, color: context.theme.iconTheme.color,
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 15),
child: Text(
'functions'.tr,
style: context.textTheme.titleLarge,
),
), ),
SettingLinks( text: 'location'.tr,
icon: Icon( switcher: true,
Iconsax.map_1, value: settings.location,
color: context.theme.iconTheme.color, onChange: (value) {
), isar.writeTxn(() async {
text: 'location'.tr, settings.location = value;
switcher: true, isar.settings.put(settings);
value: settings.location, });
onChange: (value) { setState(() {});
},
),
SettingLinks(
icon: Icon(
Iconsax.notification_1,
color: context.theme.iconTheme.color,
),
text: 'notifications'.tr,
switcher: true,
value: settings.notifications,
onChange: (value) async {
final result = Platform.isIOS
? await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions()
: await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.requestPermission();
if (result != null) {
isar.writeTxn(() async { isar.writeTxn(() async {
settings.location = value; settings.notifications = value;
isar.settings.put(settings); isar.settings.put(settings);
}); });
setState(() {}); if (value) {
},
),
SettingLinks(
icon: Icon(
Iconsax.notification_1,
color: context.theme.iconTheme.color,
),
text: 'notifications'.tr,
switcher: true,
value: settings.notifications,
onChange: (value) async {
final result = Platform.isIOS
? await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions()
: await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.requestPermission();
if (result != null) {
isar.writeTxn(() async {
settings.notifications = value;
isar.settings.put(settings);
});
if (value) {
locationController.notlification(
locationController.mainWeather);
} else {
flutterLocalNotificationsPlugin.cancelAll();
}
setState(() {});
}
},
),
SettingLinks(
icon: Icon(
Iconsax.notification_status,
color: context.theme.iconTheme.color,
),
text: 'timeRange'.tr,
dropdown: true,
dropdownName: '$timeRange',
dropdownList: const <String>[
'1',
'2',
'3',
'4',
'5',
],
dropdownCange: (String? newValue) {
isar.writeTxn(() async {
settings.timeRange = int.parse(newValue!);
isar.settings.put(settings);
});
MyApp.updateAppState(context,
newTimeRange: int.parse(newValue!));
if (settings.notifications) {
flutterLocalNotificationsPlugin.cancelAll();
locationController.notlification( locationController.notlification(
locationController.mainWeather); locationController.mainWeather);
} else {
flutterLocalNotificationsPlugin.cancelAll();
} }
}, setState(() {});
}
},
),
SettingLinks(
icon: Icon(
Iconsax.notification_status,
color: context.theme.iconTheme.color,
), ),
SettingLinks( text: 'timeRange'.tr,
icon: Icon( dropdown: true,
Iconsax.timer_start, dropdownName: '$timeRange',
color: context.theme.iconTheme.color, dropdownList: const <String>[
), '1',
text: 'timeStart'.tr, '2',
info: true, '3',
infoSettings: true, '4',
textInfo: TimeOfDay.now().format(context), '5',
onPressed: () async { ],
final TimeOfDay? timeStart = dropdownCange: (String? newValue) {
await showTimePicker( isar.writeTxn(() async {
context: context, settings.timeRange = int.parse(newValue!);
initialTime: TimeOfDay.now(), isar.settings.put(settings);
); });
isar.writeTxn(() async { MyApp.updateAppState(context,
settings.timeStart = newTimeRange: int.parse(newValue!));
timeStart?.format(context); if (settings.notifications) {
isar.settings.put(settings); flutterLocalNotificationsPlugin.cancelAll();
}); locationController.notlification(
}, locationController.mainWeather);
}
},
),
SettingLinks(
icon: Icon(
Iconsax.timer_start,
color: context.theme.iconTheme.color,
), ),
SettingLinks( text: 'timeStart'.tr,
icon: Icon( info: true,
Iconsax.timer_pause, infoSettings: true,
color: context.theme.iconTheme.color, textInfo: TimeOfDay.now().format(context),
), onPressed: () async {
text: 'timeEnd'.tr, final TimeOfDay? timeStart = await showTimePicker(
info: true, context: context,
infoSettings: true, initialTime: TimeOfDay.now(),
textInfo: TimeOfDay.now().format(context), );
onPressed: () async { isar.writeTxn(() async {
final TimeOfDay? timeEnd = await showTimePicker( settings.timeStart = timeStart?.format(context);
context: context, isar.settings.put(settings);
initialTime: TimeOfDay.now(), });
); },
isar.writeTxn(() async { ),
settings.timeEnd = timeEnd?.format(context); SettingLinks(
isar.settings.put(settings); icon: Icon(
}); Iconsax.timer_pause,
}, color: context.theme.iconTheme.color,
), ),
const SizedBox(height: 10), text: 'timeEnd'.tr,
], info: true,
), infoSettings: true,
textInfo: TimeOfDay.now().format(context),
onPressed: () async {
final TimeOfDay? timeEnd = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
isar.writeTxn(() async {
settings.timeEnd = timeEnd?.format(context);
isar.settings.put(settings);
});
},
),
const SizedBox(height: 10),
],
); );
}, },
); );
@ -318,92 +295,79 @@ class _SettingsPageState extends State<SettingsPage> {
builder: (BuildContext context) { builder: (BuildContext context) {
return StatefulBuilder( return StatefulBuilder(
builder: (BuildContext context, setState) { builder: (BuildContext context, setState) {
return Container( return Column(
decoration: BoxDecoration( crossAxisAlignment: CrossAxisAlignment.center,
color: context.theme.colorScheme.secondaryContainer, mainAxisSize: MainAxisSize.min,
borderRadius: const BorderRadius.only( children: [
topLeft: Radius.circular(20), Padding(
topRight: Radius.circular(20), padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 15),
child: Text(
'data'.tr,
style: context.textTheme.titleLarge,
),
), ),
), SettingLinks(
child: Column( icon: Icon(
crossAxisAlignment: CrossAxisAlignment.center, Iconsax.sun_1,
mainAxisSize: MainAxisSize.min, color: context.theme.iconTheme.color,
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 15),
child: Text(
'data'.tr,
style: context.textTheme.titleLarge,
),
), ),
SettingLinks( text: 'degrees'.tr,
icon: Icon( dropdown: true,
Iconsax.sun_1, dropdownName: settings.degrees.tr,
color: context.theme.iconTheme.color, dropdownList: <String>[
), 'celsius'.tr,
text: 'degrees'.tr, 'fahrenheit'.tr
dropdown: true, ],
dropdownName: settings.degrees.tr, dropdownCange: (String? newValue) {
dropdownList: <String>[ isar.writeTxn(() async {
'celsius'.tr, settings.degrees = newValue == 'celsius'.tr
'fahrenheit'.tr ? 'celsius'
], : 'fahrenheit';
dropdownCange: (String? newValue) { isar.settings.put(settings);
isar.writeTxn(() async { });
settings.degrees = newValue == 'celsius'.tr setState(() {});
? 'celsius' },
: 'fahrenheit'; ),
isar.settings.put(settings); SettingLinks(
}); icon: Icon(
setState(() {}); Iconsax.rulerpen,
}, color: context.theme.iconTheme.color,
), ),
SettingLinks( text: 'measurements'.tr,
icon: Icon( dropdown: true,
Iconsax.rulerpen, dropdownName: settings.measurements.tr,
color: context.theme.iconTheme.color, dropdownList: <String>['metric'.tr, 'imperial'.tr],
), dropdownCange: (String? newValue) {
text: 'measurements'.tr, isar.writeTxn(() async {
dropdown: true, settings.measurements = newValue == 'metric'.tr
dropdownName: settings.measurements.tr, ? 'metric'
dropdownList: <String>[ : 'imperial';
'metric'.tr, isar.settings.put(settings);
'imperial'.tr });
], setState(() {});
dropdownCange: (String? newValue) { },
isar.writeTxn(() async { ),
settings.measurements = SettingLinks(
newValue == 'metric'.tr icon: Icon(
? 'metric' Iconsax.clock,
: 'imperial'; color: context.theme.iconTheme.color,
isar.settings.put(settings);
});
setState(() {});
},
), ),
SettingLinks( text: 'timeformat'.tr,
icon: Icon( dropdown: true,
Iconsax.clock, dropdownName: settings.timeformat.tr,
color: context.theme.iconTheme.color, dropdownList: <String>['12'.tr, '24'.tr],
), dropdownCange: (String? newValue) {
text: 'timeformat'.tr, isar.writeTxn(() async {
dropdown: true, settings.timeformat =
dropdownName: settings.timeformat.tr, newValue == '12'.tr ? '12' : '24';
dropdownList: <String>['12'.tr, '24'.tr], isar.settings.put(settings);
dropdownCange: (String? newValue) { });
isar.writeTxn(() async { setState(() {});
settings.timeformat = },
newValue == '12'.tr ? '12' : '24'; ),
isar.settings.put(settings); const SizedBox(height: 10),
}); ],
setState(() {});
},
),
const SizedBox(height: 10),
],
),
); );
}, },
); );
@ -429,59 +393,43 @@ class _SettingsPageState extends State<SettingsPage> {
builder: (BuildContext context) { builder: (BuildContext context) {
return StatefulBuilder( return StatefulBuilder(
builder: (BuildContext context, setState) { builder: (BuildContext context, setState) {
return Container( return ListView(
decoration: BoxDecoration( children: [
color: context.theme.colorScheme.secondaryContainer, Padding(
borderRadius: const BorderRadius.only( padding: const EdgeInsets.symmetric(
topLeft: Radius.circular(20), horizontal: 20, vertical: 15),
topRight: Radius.circular(20), child: Text(
'language'.tr,
style: context.textTheme.titleLarge,
textAlign: TextAlign.center,
),
), ),
), ListView.builder(
child: ListView( shrinkWrap: true,
children: [ physics: const BouncingScrollPhysics(),
Padding( itemCount: appLanguages.length,
padding: const EdgeInsets.symmetric( itemBuilder: (context, index) {
horizontal: 20, vertical: 15), return Card(
child: Text( margin: const EdgeInsets.symmetric(
'language'.tr, horizontal: 15, vertical: 5),
style: context.textTheme.titleLarge, child: TextButton(
textAlign: TextAlign.center, child: Text(
), appLanguages[index]['name'],
), style: context.textTheme.labelLarge,
ListView.builder(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
itemCount: appLanguages.length,
itemBuilder: (context, index) {
return Container(
height: 50,
margin: const EdgeInsets.symmetric(
horizontal: 15, vertical: 5),
decoration: BoxDecoration(
color: context
.theme.colorScheme.primaryContainer,
borderRadius: const BorderRadius.all(
Radius.circular(15)),
), ),
child: TextButton( onPressed: () {
onPressed: () { MyApp.updateAppState(context,
MyApp.updateAppState(context, newLocale: appLanguages[index]
newLocale: appLanguages[index] ['locale']);
['locale']); updateLanguage(
updateLanguage( appLanguages[index]['locale']);
appLanguages[index]['locale']); },
}, ),
child: Text( );
appLanguages[index]['name'], },
style: context.textTheme.labelLarge, ),
), const SizedBox(height: 10),
), ],
);
},
),
const SizedBox(height: 10),
],
),
); );
}, },
); );

View file

@ -53,69 +53,69 @@ class _WeatherPageState extends State<WeatherPage> {
), ),
Obx( Obx(
() => locationController.isLoading.isFalse () => locationController.isLoading.isFalse
? Container( ? Card(
height: 135,
margin: const EdgeInsets.symmetric(vertical: 15), margin: const EdgeInsets.symmetric(vertical: 15),
padding: const EdgeInsets.symmetric( child: SizedBox(
horizontal: 15, height: 135,
vertical: 5, child: Padding(
), padding: const EdgeInsets.symmetric(
decoration: BoxDecoration( horizontal: 15, vertical: 5),
color: context.theme.colorScheme.primaryContainer, child: ScrollablePositionedList.separated(
borderRadius: const BorderRadius.all( key: const PageStorageKey(0),
Radius.circular(20), physics: const AlwaysScrollableScrollPhysics(),
), separatorBuilder:
), (BuildContext context, int index) {
child: ScrollablePositionedList.separated( return VerticalDivider(
key: const PageStorageKey(0), width: 10,
physics: const AlwaysScrollableScrollPhysics(), color: context.theme.unselectedWidgetColor,
separatorBuilder: (BuildContext context, int index) { indent: 40,
return VerticalDivider( endIndent: 40,
width: 10, );
color: context.theme.unselectedWidgetColor, },
indent: 40, scrollDirection: Axis.horizontal,
endIndent: 40, itemScrollController:
); locationController.itemScrollController,
}, itemCount:
scrollDirection: Axis.horizontal, locationController.mainWeather.time!.length,
itemScrollController: itemBuilder: (ctx, i) => GestureDetector(
locationController.itemScrollController, onTap: () {
itemCount: locationController.hourOfDay.value = i;
locationController.mainWeather.time!.length, locationController.dayOfNow.value =
itemBuilder: (ctx, i) => GestureDetector( (i / 24).floor();
onTap: () { setState(() {});
locationController.hourOfDay.value = i; },
locationController.dayOfNow.value = child: Container(
(i / 24).floor(); margin:
setState(() {}); const EdgeInsets.symmetric(vertical: 5),
}, padding: const EdgeInsets.symmetric(
child: Container( horizontal: 20,
margin: const EdgeInsets.symmetric(vertical: 5), vertical: 5,
padding: const EdgeInsets.symmetric( ),
horizontal: 20, decoration: BoxDecoration(
vertical: 5, color:
), i == locationController.hourOfDay.value
decoration: BoxDecoration( ? Get.isDarkMode
color: i == locationController.hourOfDay.value ? Colors.indigo
? Get.isDarkMode : Colors.amberAccent
? Colors.indigo : Colors.transparent,
: Colors.amberAccent borderRadius: const BorderRadius.all(
: Colors.transparent, Radius.circular(20),
borderRadius: const BorderRadius.all( ),
Radius.circular(20), ),
child: WeatherHourly(
time:
locationController.mainWeather.time![i],
weather: locationController
.mainWeather.weathercode![i],
degree: locationController
.mainWeather.temperature2M![i],
timeDay: locationController
.mainWeather.sunrise![(i / 24).floor()],
timeNight: locationController
.mainWeather.sunset![(i / 24).floor()],
),
), ),
), ),
child: WeatherHourly(
time: locationController.mainWeather.time![i],
weather: locationController
.mainWeather.weathercode![i],
degree: locationController
.mainWeather.temperature2M![i],
timeDay: locationController
.mainWeather.sunrise![(i / 24).floor()],
timeNight: locationController
.mainWeather.sunset![(i / 24).floor()],
),
), ),
), ),
), ),

View file

@ -93,64 +93,60 @@ class _WeatherCardPageState extends State<WeatherCardPage> {
timeDay: widget.weatherCard.sunrise![dayNow], timeDay: widget.weatherCard.sunrise![dayNow],
timeNight: widget.weatherCard.sunset![dayNow], timeNight: widget.weatherCard.sunset![dayNow],
), ),
Container( Card(
height: 130,
margin: const EdgeInsets.symmetric(vertical: 15), margin: const EdgeInsets.symmetric(vertical: 15),
padding: const EdgeInsets.symmetric( child: SizedBox(
horizontal: 15, height: 130,
vertical: 5, child: Padding(
), padding: const EdgeInsets.symmetric(
decoration: BoxDecoration( horizontal: 15, vertical: 5),
color: context.theme.colorScheme.primaryContainer, child: ScrollablePositionedList.separated(
borderRadius: const BorderRadius.all( key: const PageStorageKey(1),
Radius.circular(20), physics: const AlwaysScrollableScrollPhysics(),
), separatorBuilder: (BuildContext context, int index) {
), return VerticalDivider(
child: ScrollablePositionedList.separated( width: 10,
key: const PageStorageKey(1), color: context.theme.unselectedWidgetColor,
physics: const AlwaysScrollableScrollPhysics(), indent: 40,
separatorBuilder: (BuildContext context, int index) { endIndent: 40,
return VerticalDivider( );
width: 10, },
color: context.theme.unselectedWidgetColor, scrollDirection: Axis.horizontal,
indent: 40, itemScrollController: itemScrollController,
endIndent: 40, itemCount: widget.weatherCard.time!.length,
); itemBuilder: (ctx, i) => GestureDetector(
}, onTap: () {
scrollDirection: Axis.horizontal, timeNow = i;
itemScrollController: itemScrollController, dayNow = (i / 24).floor();
itemCount: widget.weatherCard.time!.length, setState(() {});
itemBuilder: (ctx, i) => GestureDetector( },
onTap: () { child: Container(
timeNow = i; margin: const EdgeInsets.symmetric(vertical: 5),
dayNow = (i / 24).floor(); padding: const EdgeInsets.symmetric(
setState(() {}); horizontal: 20,
}, vertical: 5,
child: Container( ),
margin: const EdgeInsets.symmetric(vertical: 5), decoration: BoxDecoration(
padding: const EdgeInsets.symmetric( color: i == timeNow
horizontal: 20, ? Get.isDarkMode
vertical: 5, ? Colors.indigo
), : Colors.amberAccent
decoration: BoxDecoration( : Colors.transparent,
color: i == timeNow borderRadius: const BorderRadius.all(
? Get.isDarkMode Radius.circular(20),
? Colors.indigo ),
: Colors.amberAccent ),
: Colors.transparent, child: WeatherHourly(
borderRadius: const BorderRadius.all( time: widget.weatherCard.time![i],
Radius.circular(20), weather: widget.weatherCard.weathercode![i],
degree: widget.weatherCard.temperature2M![i],
timeDay:
widget.weatherCard.sunrise![(i / 24).floor()],
timeNight:
widget.weatherCard.sunset![(i / 24).floor()],
),
), ),
), ),
child: WeatherHourly(
time: widget.weatherCard.time![i],
weather: widget.weatherCard.weathercode![i],
degree: widget.weatherCard.temperature2M![i],
timeDay:
widget.weatherCard.sunrise![(i / 24).floor()],
timeNight:
widget.weatherCard.sunset![(i / 24).floor()],
),
), ),
), ),
), ),

View file

@ -39,88 +39,85 @@ class _CardDescWeatherState extends State<CardDescWeather> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Card(
width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 20), child: Padding(
decoration: BoxDecoration( padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 20),
borderRadius: BorderRadius.circular(20), child: Row(
color: context.theme.colorScheme.primaryContainer, children: [
), Expanded(
child: Row( child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
Expanded( children: [
child: Column( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Row( Text(
crossAxisAlignment: CrossAxisAlignment.center, statusImFa.getDegree(widget.degree[locationController
children: [ .getTime(widget.time, widget.timezone)]
Text( .round()
statusImFa.getDegree(widget.degree[locationController .toInt()),
.getTime(widget.time, widget.timezone)] style: context.textTheme.titleLarge?.copyWith(
.round() fontSize: 22,
.toInt()), fontWeight: FontWeight.w600,
style: context.textTheme.titleLarge?.copyWith( ),
fontSize: 22,
fontWeight: FontWeight.w600,
), ),
), const SizedBox(width: 7),
const SizedBox(width: 7), Text(
Text( status.getText(widget.weather[locationController
status.getText(widget.weather[locationController.getTime( .getTime(widget.time, widget.timezone)]),
widget.time, widget.timezone)]), style: context.textTheme.titleMedium?.copyWith(
style: context.textTheme.titleMedium?.copyWith( color: Colors.grey,
color: Colors.grey, fontWeight: FontWeight.w400,
fontWeight: FontWeight.w400, ),
), ),
), ],
],
),
const SizedBox(height: 10),
Text(
widget.district.isEmpty
? widget.city
: widget.city.isEmpty
? widget.district
: widget.city == widget.district
? widget.city
: '${widget.city}'
', ${widget.district}',
style: context.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w500,
), ),
), const SizedBox(height: 10),
const SizedBox(height: 5), Text(
StreamBuilder( widget.district.isEmpty
stream: Stream.periodic(const Duration(seconds: 1)), ? widget.city
builder: (context, snapshot) { : widget.city.isEmpty
return Text( ? widget.district
'${'time'.tr}: ${statusImFa.getTimeFormatTz(tz.TZDateTime.now(tz.getLocation(widget.timezone)))}', : widget.city == widget.district
style: context.textTheme.titleMedium?.copyWith( ? widget.city
color: Colors.grey, : '${widget.city}'
fontWeight: FontWeight.w400, ', ${widget.district}',
), style: context.textTheme.titleMedium?.copyWith(
); fontWeight: FontWeight.w500,
}, ),
), ),
], const SizedBox(height: 5),
StreamBuilder(
stream: Stream.periodic(const Duration(seconds: 1)),
builder: (context, snapshot) {
return Text(
'${'time'.tr}: ${statusImFa.getTimeFormatTz(tz.TZDateTime.now(tz.getLocation(widget.timezone)))}',
style: context.textTheme.titleMedium?.copyWith(
color: Colors.grey,
fontWeight: FontWeight.w400,
),
);
},
),
],
),
), ),
), const SizedBox(width: 5),
const SizedBox(width: 5), Image.asset(
Image.asset( status.getImageNow(
status.getImageNow( widget.weather[
widget.weather[ locationController.getTime(widget.time, widget.timezone)],
locationController.getTime(widget.time, widget.timezone)], widget.time[
widget.time[ locationController.getTime(widget.time, widget.timezone)],
locationController.getTime(widget.time, widget.timezone)], widget.timeDay[locationController.getDay(
widget.timeDay[locationController.getDay( widget.timeDaily, widget.timezone)],
widget.timeDaily, widget.timezone)], widget.timeNight[locationController.getDay(
widget.timeNight[locationController.getDay( widget.timeDaily, widget.timezone)]),
widget.timeDaily, widget.timezone)]), scale: 6.5,
scale: 6.5, ),
), ],
], ),
), ),
); );
} }

View file

@ -44,218 +44,205 @@ class _CreateWeatherCardState extends State<CreateWeatherCard> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Form(
decoration: BoxDecoration( key: formKey,
color: context.theme.colorScheme.secondaryContainer, child: SingleChildScrollView(
borderRadius: const BorderRadius.only( child: Stack(
topLeft: Radius.circular(20), children: [
topRight: Radius.circular(20), Padding(
), padding: EdgeInsets.only(
), bottom: MediaQuery.of(context).viewInsets.bottom,
child: Form(
key: formKey,
child: SingleChildScrollView(
child: Stack(
children: [
Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding:
const EdgeInsets.only(top: 10, left: 5, right: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
onPressed: () {
Get.back();
},
icon: Icon(
Iconsax.close_square,
color: context.theme.iconTheme.color,
size: 20,
),
),
Text(
'create'.tr,
style: context.textTheme.titleLarge,
textAlign: TextAlign.center,
),
IconButton(
onPressed: () async {
if (formKey.currentState!.validate()) {
textTrim(_controllerLat);
textTrim(_controllerLon);
textTrim(_controllerCity);
textTrim(_controllerDistrict);
setState(() => isLoading = true);
await locationController.addCardWeather(
double.parse(_controllerLat.text),
double.parse(_controllerLon.text),
_controllerCity.text,
_controllerDistrict.text,
);
setState(() => isLoading = false);
Get.back();
}
},
icon: Icon(
Iconsax.tick_square,
color: context.theme.iconTheme.color,
size: 20,
),
),
],
),
),
Padding(
padding:
const EdgeInsets.only(left: 10, right: 10, top: 10),
child: RawAutocomplete<Result>(
focusNode: _focusNode,
textEditingController: _controller,
fieldViewBuilder: (BuildContext context,
TextEditingController fieldTextEditingController,
FocusNode fieldFocusNode,
VoidCallback onFieldSubmitted) {
return TextField(
controller: _controller,
focusNode: _focusNode,
decoration: InputDecoration(
prefixIcon: const Icon(Iconsax.global_search),
filled: true,
fillColor:
context.theme.colorScheme.primaryContainer,
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(15),
),
labelText: 'search'.tr,
),
);
},
optionsBuilder: (TextEditingValue textEditingValue) {
if (textEditingValue.text.isEmpty) {
return const Iterable<Result>.empty();
}
return WeatherAPI()
.getSuggestions(textEditingValue.text, locale);
},
onSelected: (Result selection) =>
fillController(selection),
displayStringForOption: (Result option) =>
'${option.name}, ${option.admin1}',
optionsViewBuilder: (BuildContext context,
AutocompleteOnSelected<Result> onSelected,
Iterable<Result> options) {
return Align(
alignment: Alignment.topCenter,
child: Material(
color: context.theme.colorScheme.primaryContainer,
borderRadius: BorderRadius.circular(20),
elevation: 4.0,
child: ListView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final Result option =
options.elementAt(index);
return InkWell(
onTap: () => onSelected(option),
child: ListTile(
title: Text(
'${option.name}, ${option.admin1}',
style: context.textTheme.bodyLarge,
),
),
);
},
),
),
);
},
),
),
MyTextForm(
controller: _controllerLat,
labelText: 'lat'.tr,
type: TextInputType.number,
icon: const Icon(Iconsax.location),
padding:
const EdgeInsets.only(left: 10, right: 10, top: 10),
validator: (value) {
if (value == null || value.isEmpty) {
return 'validateValue'.tr;
}
double? numericValue = double.tryParse(value);
if (numericValue == null) {
return 'validateNumber'.tr;
}
if (numericValue < -90 || numericValue > 90) {
return 'validate90'.tr;
}
return null;
},
),
MyTextForm(
controller: _controllerLon,
labelText: 'lon'.tr,
type: TextInputType.number,
icon: const Icon(Iconsax.location),
padding:
const EdgeInsets.only(left: 10, right: 10, top: 10),
validator: (value) {
if (value == null || value.isEmpty) {
return 'validateValue'.tr;
}
double? numericValue = double.tryParse(value);
if (numericValue == null) {
return 'validateNumber'.tr;
}
if (numericValue < -180 || numericValue > 180) {
return 'validate180'.tr;
}
return null;
},
),
MyTextForm(
controller: _controllerCity,
labelText: 'city'.tr,
type: TextInputType.name,
icon: const Icon(Icons.location_city_rounded),
padding:
const EdgeInsets.only(left: 10, right: 10, top: 10),
validator: (value) {
if (value == null || value.isEmpty) {
return 'validateName'.tr;
}
return null;
},
),
MyTextForm(
controller: _controllerDistrict,
labelText: 'district'.tr,
type: TextInputType.streetAddress,
icon: const Icon(Iconsax.global),
padding:
const EdgeInsets.only(left: 10, right: 10, top: 10),
),
const SizedBox(height: 20),
],
),
), ),
if (isLoading) child: Column(
const Center( crossAxisAlignment: CrossAxisAlignment.center,
child: CircularProgressIndicator(), mainAxisSize: MainAxisSize.min,
), children: [
], Padding(
), padding: const EdgeInsets.only(top: 10, left: 5, right: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
onPressed: () {
Get.back();
},
icon: Icon(
Iconsax.close_square,
color: context.theme.iconTheme.color,
size: 20,
),
),
Text(
'create'.tr,
style: context.textTheme.titleLarge,
textAlign: TextAlign.center,
),
IconButton(
onPressed: () async {
if (formKey.currentState!.validate()) {
textTrim(_controllerLat);
textTrim(_controllerLon);
textTrim(_controllerCity);
textTrim(_controllerDistrict);
setState(() => isLoading = true);
await locationController.addCardWeather(
double.parse(_controllerLat.text),
double.parse(_controllerLon.text),
_controllerCity.text,
_controllerDistrict.text,
);
setState(() => isLoading = false);
Get.back();
}
},
icon: Icon(
Iconsax.tick_square,
color: context.theme.iconTheme.color,
size: 20,
),
),
],
),
),
Padding(
padding:
const EdgeInsets.only(left: 10, right: 10, top: 10),
child: RawAutocomplete<Result>(
focusNode: _focusNode,
textEditingController: _controller,
fieldViewBuilder: (BuildContext context,
TextEditingController fieldTextEditingController,
FocusNode fieldFocusNode,
VoidCallback onFieldSubmitted) {
return TextField(
controller: _controller,
focusNode: _focusNode,
decoration: InputDecoration(
prefixIcon: const Icon(Iconsax.global_search),
filled: true,
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(15),
),
labelText: 'search'.tr,
),
);
},
optionsBuilder: (TextEditingValue textEditingValue) {
if (textEditingValue.text.isEmpty) {
return const Iterable<Result>.empty();
}
return WeatherAPI()
.getSuggestions(textEditingValue.text, locale);
},
onSelected: (Result selection) =>
fillController(selection),
displayStringForOption: (Result option) =>
'${option.name}, ${option.admin1}',
optionsViewBuilder: (BuildContext context,
AutocompleteOnSelected<Result> onSelected,
Iterable<Result> options) {
return Align(
alignment: Alignment.topCenter,
child: Material(
color: context.theme.colorScheme.primaryContainer,
borderRadius: BorderRadius.circular(20),
elevation: 4.0,
child: ListView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final Result option = options.elementAt(index);
return InkWell(
onTap: () => onSelected(option),
child: ListTile(
title: Text(
'${option.name}, ${option.admin1}',
style: context.textTheme.bodyLarge,
),
),
);
},
),
),
);
},
),
),
MyTextForm(
controller: _controllerLat,
labelText: 'lat'.tr,
type: TextInputType.number,
icon: const Icon(Iconsax.location),
padding:
const EdgeInsets.only(left: 10, right: 10, top: 10),
validator: (value) {
if (value == null || value.isEmpty) {
return 'validateValue'.tr;
}
double? numericValue = double.tryParse(value);
if (numericValue == null) {
return 'validateNumber'.tr;
}
if (numericValue < -90 || numericValue > 90) {
return 'validate90'.tr;
}
return null;
},
),
MyTextForm(
controller: _controllerLon,
labelText: 'lon'.tr,
type: TextInputType.number,
icon: const Icon(Iconsax.location),
padding:
const EdgeInsets.only(left: 10, right: 10, top: 10),
validator: (value) {
if (value == null || value.isEmpty) {
return 'validateValue'.tr;
}
double? numericValue = double.tryParse(value);
if (numericValue == null) {
return 'validateNumber'.tr;
}
if (numericValue < -180 || numericValue > 180) {
return 'validate180'.tr;
}
return null;
},
),
MyTextForm(
controller: _controllerCity,
labelText: 'city'.tr,
type: TextInputType.name,
icon: const Icon(Icons.location_city_rounded),
padding:
const EdgeInsets.only(left: 10, right: 10, top: 10),
validator: (value) {
if (value == null || value.isEmpty) {
return 'validateName'.tr;
}
return null;
},
),
MyTextForm(
controller: _controllerDistrict,
labelText: 'district'.tr,
type: TextInputType.streetAddress,
icon: const Icon(Iconsax.global),
padding:
const EdgeInsets.only(left: 10, right: 10, top: 10),
),
const SizedBox(height: 20),
],
),
),
if (isLoading)
const Center(
child: CircularProgressIndicator(),
),
],
), ),
), ),
); );

View file

@ -154,93 +154,91 @@ class _DailyCardState extends State<DailyCard> {
timeSunset: widget.sunset[index], timeSunset: widget.sunset[index],
), ),
), ),
Container( Card(
margin: const EdgeInsets.only(bottom: 15), margin: const EdgeInsets.only(bottom: 15),
padding: const EdgeInsets.only(top: 20, bottom: 5), child: Padding(
decoration: BoxDecoration( padding: const EdgeInsets.only(top: 20, bottom: 5),
color: context.theme.colorScheme.primaryContainer, child: Column(
borderRadius: const BorderRadius.all( children: [
Radius.circular(20), Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/cold.png',
value: statusImFa.getDegree(widget
.apparentTemperatureMin[index]
.round()),
desc: 'apparentTemperatureMin'.tr,
),
DescWeather(
imageName: 'assets/images/hot.png',
value: statusImFa.getDegree(widget
.apparentTemperatureMax[index]
.round()),
desc: 'apparentTemperatureMax'.tr,
),
DescWeather(
imageName: 'assets/images/uv.png',
value: '${widget.uvIndexMax[index].round()}',
desc: 'uvIndex'.tr,
message: message.getUvIndex(
widget.uvIndexMax[index].round()),
),
],
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/windsock.png',
value:
'${widget.winddirection10MDominant[index]}°',
desc: 'direction'.tr,
message: message.getDirection(
widget.winddirection10MDominant[index]),
),
DescWeather(
imageName: 'assets/images/wind.png',
value: statusImFa.getSpeed(
widget.windspeed10MMax[index].round()),
desc: 'wind'.tr,
),
DescWeather(
imageName: 'assets/images/windgusts.png',
value: statusImFa.getSpeed(
widget.windgusts10MMax[index].round()),
desc: 'windgusts'.tr,
),
],
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/humidity.png',
value:
'${widget.precipitationProbabilityMax[index]}%',
desc: 'precipitationProbabilit'.tr,
),
DescWeather(
imageName: 'assets/images/water.png',
value: statusImFa
.getPrecipitation(widget.rainSum[index]),
desc: 'rain'.tr,
),
DescWeather(
imageName: 'assets/images/rainfall.png',
value: statusImFa.getPrecipitation(
widget.precipitationSum[index]),
desc: 'precipitation'.tr,
),
],
),
],
), ),
), ),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/cold.png',
value: statusImFa.getDegree(
widget.apparentTemperatureMin[index].round()),
desc: 'apparentTemperatureMin'.tr,
),
DescWeather(
imageName: 'assets/images/hot.png',
value: statusImFa.getDegree(
widget.apparentTemperatureMax[index].round()),
desc: 'apparentTemperatureMax'.tr,
),
DescWeather(
imageName: 'assets/images/uv.png',
value: '${widget.uvIndexMax[index].round()}',
desc: 'uvIndex'.tr,
message: message
.getUvIndex(widget.uvIndexMax[index].round()),
),
],
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/windsock.png',
value:
'${widget.winddirection10MDominant[index]}°',
desc: 'direction'.tr,
message: message.getDirection(
widget.winddirection10MDominant[index]),
),
DescWeather(
imageName: 'assets/images/wind.png',
value: statusImFa.getSpeed(
widget.windspeed10MMax[index].round()),
desc: 'wind'.tr,
),
DescWeather(
imageName: 'assets/images/windgusts.png',
value: statusImFa.getSpeed(
widget.windgusts10MMax[index].round()),
desc: 'windgusts'.tr,
),
],
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/humidity.png',
value:
'${widget.precipitationProbabilityMax[index]}%',
desc: 'precipitationProbabilit'.tr,
),
DescWeather(
imageName: 'assets/images/water.png',
value: statusImFa
.getPrecipitation(widget.rainSum[index]),
desc: 'rain'.tr,
),
DescWeather(
imageName: 'assets/images/rainfall.png',
value: statusImFa.getPrecipitation(
widget.precipitationSum[index]),
desc: 'precipitation'.tr,
),
],
),
],
),
), ),
], ],
), ),

View file

@ -37,105 +37,101 @@ class DescContainer extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final statusImFa = StatusImFa(); final statusImFa = StatusImFa();
final message = Message(); final message = Message();
return Container( return Card(
margin: const EdgeInsets.only(bottom: 15), margin: const EdgeInsets.only(bottom: 15),
padding: const EdgeInsets.only(top: 22, bottom: 5), child: Padding(
decoration: BoxDecoration( padding: const EdgeInsets.only(top: 22, bottom: 5),
color: context.theme.colorScheme.primaryContainer, child: Column(
borderRadius: const BorderRadius.all( children: [
Radius.circular(20), Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/humidity.png',
value: '$humidity%',
desc: 'humidity'.tr,
),
DescWeather(
imageName: 'assets/images/temperature.png',
value: '${feels.round()}°',
desc: 'feels'.tr,
),
DescWeather(
imageName: 'assets/images/fog.png',
value: statusImFa.getVisibility(visibility),
desc: 'visibility'.tr,
),
],
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/windsock.png',
value: '$direction°',
desc: 'direction'.tr,
message: message.getDirection(direction),
),
DescWeather(
imageName: 'assets/images/wind.png',
value: statusImFa.getSpeed(wind.round()),
desc: 'wind'.tr,
),
DescWeather(
imageName: 'assets/images/windgusts.png',
value: statusImFa.getSpeed(windgusts.round()),
desc: 'windgusts'.tr,
),
],
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/evaporation.png',
value: statusImFa.getPrecipitation(evaporation.abs()),
desc: 'evaporation'.tr,
),
DescWeather(
imageName: 'assets/images/rainfall.png',
value: statusImFa.getPrecipitation(precipitation),
desc: 'precipitation'.tr,
),
DescWeather(
imageName: 'assets/images/water.png',
value: statusImFa.getPrecipitation(rain),
desc: 'rain'.tr,
),
],
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/cloudy.png',
value: '$cloudcover%',
desc: 'cloudcover'.tr,
),
DescWeather(
imageName: 'assets/images/atmospheric.png',
value: '${pressure.round()} ${'hPa'.tr}',
desc: 'pressure'.tr,
message: message.getPressure(pressure.round()),
),
DescWeather(
imageName: 'assets/images/uv.png',
value: '${uvIndex.round()}',
desc: 'uvIndex'.tr,
message: message.getUvIndex(uvIndex.round()),
),
],
),
],
), ),
), ),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/humidity.png',
value: '$humidity%',
desc: 'humidity'.tr,
),
DescWeather(
imageName: 'assets/images/temperature.png',
value: '${feels.round()}°',
desc: 'feels'.tr,
),
DescWeather(
imageName: 'assets/images/fog.png',
value: statusImFa.getVisibility(visibility),
desc: 'visibility'.tr,
),
],
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/windsock.png',
value: '$direction°',
desc: 'direction'.tr,
message: message.getDirection(direction),
),
DescWeather(
imageName: 'assets/images/wind.png',
value: statusImFa.getSpeed(wind.round()),
desc: 'wind'.tr,
),
DescWeather(
imageName: 'assets/images/windgusts.png',
value: statusImFa.getSpeed(windgusts.round()),
desc: 'windgusts'.tr,
),
],
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/evaporation.png',
value: statusImFa.getPrecipitation(evaporation.abs()),
desc: 'evaporation'.tr,
),
DescWeather(
imageName: 'assets/images/rainfall.png',
value: statusImFa.getPrecipitation(precipitation),
desc: 'precipitation'.tr,
),
DescWeather(
imageName: 'assets/images/water.png',
value: statusImFa.getPrecipitation(rain),
desc: 'rain'.tr,
),
],
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DescWeather(
imageName: 'assets/images/cloudy.png',
value: '$cloudcover%',
desc: 'cloudcover'.tr,
),
DescWeather(
imageName: 'assets/images/atmospheric.png',
value: '${pressure.round()} ${'hPa'.tr}',
desc: 'pressure'.tr,
message: message.getPressure(pressure.round()),
),
DescWeather(
imageName: 'assets/images/uv.png',
value: '${uvIndex.round()}',
desc: 'uvIndex'.tr,
message: message.getUvIndex(uvIndex.round()),
),
],
),
],
),
); );
} }
} }

View file

@ -23,52 +23,50 @@ class ListCardDaily extends StatelessWidget {
final status = Status(); final status = Status();
final statusImFa = StatusImFa(); final statusImFa = StatusImFa();
return Container( return Card(
width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 20), child: Padding(
decoration: BoxDecoration( padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 20),
borderRadius: BorderRadius.circular(20), child: Row(
color: context.theme.colorScheme.primaryContainer, children: [
), Expanded(
child: Row( child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
Expanded( children: [
child: Column( Text(
crossAxisAlignment: CrossAxisAlignment.start, '${statusImFa.getDegree(temperature2MMin.round())} / ${statusImFa.getDegree(temperature2MMax.round())}',
children: [ style: context.textTheme.titleLarge?.copyWith(
Text( fontSize: 22,
'${statusImFa.getDegree(temperature2MMin.round())} / ${statusImFa.getDegree(temperature2MMax.round())}', fontWeight: FontWeight.w600,
style: context.textTheme.titleLarge?.copyWith( ),
fontSize: 22,
fontWeight: FontWeight.w600,
), ),
), const SizedBox(height: 5),
const SizedBox(height: 5), Text(
Text( DateFormat.MMMMEEEEd(locale?.languageCode)
DateFormat.MMMMEEEEd(locale?.languageCode).format(timeDaily), .format(timeDaily),
style: context.textTheme.titleMedium?.copyWith( style: context.textTheme.titleMedium?.copyWith(
color: Colors.grey, color: Colors.grey,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
),
), ),
), const SizedBox(height: 5),
const SizedBox(height: 5), Text(
Text( status.getText(weathercodeDaily),
status.getText(weathercodeDaily), style: context.textTheme.titleMedium?.copyWith(
style: context.textTheme.titleMedium?.copyWith( color: Colors.grey,
color: Colors.grey, fontWeight: FontWeight.w400,
fontWeight: FontWeight.w400, ),
), ),
), ],
], ),
), ),
), const SizedBox(width: 5),
const SizedBox(width: 5), Image.asset(
Image.asset( status.getImageNowDaily(weathercodeDaily, timeDaily),
status.getImageNowDaily(weathercodeDaily, timeDaily), scale: 6.5,
scale: 6.5, ),
), ],
], ),
), ),
); );
} }

View file

@ -35,88 +35,69 @@ class SettingLinks extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Card(
height: 60,
margin: const EdgeInsets.symmetric(horizontal: 15, vertical: 5), margin: const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
decoration: BoxDecoration( child: ListTile(
color: context.theme.colorScheme.primaryContainer, onTap: onPressed,
borderRadius: const BorderRadius.all(Radius.circular(15)), leading: icon,
), title: Text(
child: TextButton( text,
onPressed: onPressed, style: context.textTheme.titleMedium,
child: Row( overflow: TextOverflow.visible,
children: [ ),
Expanded( trailing: switcher
child: Row( ? Transform.scale(
children: [ scale: 0.8,
const SizedBox(width: 5), child: Switch(
icon, value: value!,
const SizedBox(width: 15), onChanged: onChange,
Expanded( ),
child: Text( )
text, : dropdown
style: context.textTheme.titleMedium, ? DropdownButton<String>(
overflow: TextOverflow.visible, underline: Container(),
), value: dropdownName,
), items: dropdownList!
], .map<DropdownMenuItem<String>>((String value) {
), return DropdownMenuItem<String>(
), value: value,
switcher child: Text(value),
? Transform.scale( );
scale: 0.8, }).toList(),
child: Switch( onChanged: dropdownCange,
value: value!,
onChanged: onChange,
),
) )
: dropdown : info
? DropdownButton<String>( ? infoSettings
underline: Container(), ? Wrap(
value: dropdownName, children: [
items: dropdownList! Padding(
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: dropdownCange,
)
: info
? infoSettings
? Row(
children: [
Padding(
padding: const EdgeInsets.only(right: 5),
child: Text(
textInfo!,
style: context.textTheme.bodyMedium,
overflow: TextOverflow.visible,
),
),
Icon(
Iconsax.arrow_right_3,
color: context.theme.iconTheme.color,
size: 18,
),
],
)
: Padding(
padding: const EdgeInsets.only(right: 5), padding: const EdgeInsets.only(right: 5),
child: Text( child: Text(
textInfo!, textInfo!,
style: context.textTheme.titleMedium, style: context.textTheme.bodyMedium,
overflow: TextOverflow.visible, overflow: TextOverflow.visible,
), ),
) ),
: Icon( Icon(
Iconsax.arrow_right_3, Iconsax.arrow_right_3,
color: context.theme.iconTheme.color, color: context.theme.iconTheme.color,
size: 18, size: 18,
), ),
], ],
), )
: Padding(
padding: const EdgeInsets.only(right: 5),
child: Text(
textInfo!,
style: context.textTheme.titleMedium,
overflow: TextOverflow.visible,
),
)
: Icon(
Iconsax.arrow_right_3,
color: context.theme.iconTheme.color,
size: 18,
),
), ),
); );
} }

View file

@ -16,12 +16,11 @@ class MyShimmer extends StatelessWidget {
return Shimmer.fromColors( return Shimmer.fromColors(
baseColor: context.theme.colorScheme.primaryContainer, baseColor: context.theme.colorScheme.primaryContainer,
highlightColor: context.theme.unselectedWidgetColor, highlightColor: context.theme.unselectedWidgetColor,
child: Container( child: Card(
height: hight,
margin: edgeInsetsMargin, margin: edgeInsetsMargin,
decoration: BoxDecoration( child: SizedBox(
color: context.theme.colorScheme.primaryContainer, height: hight,
borderRadius: const BorderRadius.all(Radius.circular(20))), ),
), ),
); );
} }

View file

@ -22,81 +22,77 @@ class _SunsetSunriseState extends State<SunsetSunrise> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Card(
margin: const EdgeInsets.only(bottom: 15), margin: const EdgeInsets.only(bottom: 15),
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), child: Padding(
decoration: BoxDecoration( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
color: context.theme.colorScheme.primaryContainer, child: Row(
borderRadius: const BorderRadius.all( children: [
Radius.circular(20), Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'sunrise'.tr,
style: context.textTheme.titleSmall,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
),
const SizedBox(height: 2),
Text(
statusImFa.getTimeFormat(widget.timeSunrise),
style: context.textTheme.titleLarge,
),
],
),
),
Expanded(
child: Image.asset(
'assets/images/sunrise.png',
scale: 10,
),
),
],
),
),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'sunset'.tr,
style: context.textTheme.titleSmall,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
),
const SizedBox(height: 2),
Text(
statusImFa.getTimeFormat(widget.timeSunset),
style: context.textTheme.titleLarge,
),
],
),
),
Expanded(
child: Image.asset(
'assets/images/sunset.png',
scale: 10,
),
),
],
),
),
],
), ),
), ),
child: Row(
children: [
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'sunrise'.tr,
style: context.textTheme.titleSmall,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
),
const SizedBox(height: 2),
Text(
statusImFa.getTimeFormat(widget.timeSunrise),
style: context.textTheme.titleLarge,
),
],
),
),
Expanded(
child: Image.asset(
'assets/images/sunrise.png',
scale: 10,
),
),
],
),
),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'sunset'.tr,
style: context.textTheme.titleSmall,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
),
const SizedBox(height: 2),
Text(
statusImFa.getTimeFormat(widget.timeSunset),
style: context.textTheme.titleLarge,
),
],
),
),
Expanded(
child: Image.asset(
'assets/images/sunset.png',
scale: 10,
),
),
],
),
),
],
),
); );
} }
} }

View file

@ -35,7 +35,6 @@ class MyTextForm extends StatelessWidget {
prefixIcon: icon, prefixIcon: icon,
suffixIcon: iconButton, suffixIcon: iconButton,
filled: true, filled: true,
fillColor: context.theme.colorScheme.primaryContainer,
border: OutlineInputBorder( border: OutlineInputBorder(
borderSide: BorderSide.none, borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(15), borderRadius: BorderRadius.circular(15),

View file

@ -28,164 +28,168 @@ class _WeatherDailyState extends State<WeatherDaily> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Card(
height: 455,
margin: const EdgeInsets.only(bottom: 15), margin: const EdgeInsets.only(bottom: 15),
padding: const EdgeInsets.symmetric( child: SizedBox(
horizontal: 15, height: 455,
vertical: 5, child: Padding(
), padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
decoration: BoxDecoration( child: Column(
color: context.theme.colorScheme.primaryContainer, children: [
borderRadius: const BorderRadius.all( Expanded(
Radius.circular(20), child: ListView.builder(
), physics: const NeverScrollableScrollPhysics(),
), itemCount: 7,
child: Column( itemBuilder: (ctx, index) {
children: [ return InkWell(
Expanded( onTap: () => Get.to(
child: ListView.builder( () => DailyCard(
physics: const NeverScrollableScrollPhysics(), timeDaily: widget.mainWeatherCache?.timeDaily ??
itemCount: 7, widget.weatherCard!.timeDaily!,
itemBuilder: (ctx, index) { weathercodeDaily:
return InkWell( widget.mainWeatherCache?.weathercodeDaily ??
onTap: () => Get.to( widget.weatherCard!.weathercodeDaily!,
() => DailyCard( temperature2MMax:
timeDaily: widget.mainWeatherCache?.timeDaily ?? widget.mainWeatherCache?.temperature2MMax ??
widget.weatherCard!.timeDaily!, widget.weatherCard!.temperature2MMax!,
weathercodeDaily: temperature2MMin:
widget.mainWeatherCache?.weathercodeDaily ?? widget.mainWeatherCache?.temperature2MMin ??
widget.weatherCard!.weathercodeDaily!, widget.weatherCard!.temperature2MMin!,
temperature2MMax: apparentTemperatureMax: widget.mainWeatherCache
widget.mainWeatherCache?.temperature2MMax ?? ?.apparentTemperatureMax ??
widget.weatherCard!.temperature2MMax!, widget.weatherCard!.apparentTemperatureMax!,
temperature2MMin: apparentTemperatureMin: widget.mainWeatherCache
widget.mainWeatherCache?.temperature2MMin ?? ?.apparentTemperatureMin ??
widget.weatherCard!.temperature2MMin!, widget.weatherCard!.apparentTemperatureMin!,
apparentTemperatureMax: widget sunrise: widget.mainWeatherCache?.sunrise ??
.mainWeatherCache?.apparentTemperatureMax ?? widget.weatherCard!.sunrise!,
widget.weatherCard!.apparentTemperatureMax!, sunset: widget.mainWeatherCache?.sunset ??
apparentTemperatureMin: widget widget.weatherCard!.sunset!,
.mainWeatherCache?.apparentTemperatureMin ?? precipitationSum:
widget.weatherCard!.apparentTemperatureMin!, widget.mainWeatherCache?.precipitationSum ??
sunrise: widget.mainWeatherCache?.sunrise ?? widget.weatherCard!.precipitationSum!,
widget.weatherCard!.sunrise!, precipitationProbabilityMax: widget
sunset: widget.mainWeatherCache?.sunset ?? .mainWeatherCache
widget.weatherCard!.sunset!, ?.precipitationProbabilityMax ??
precipitationSum: widget.weatherCard!
widget.mainWeatherCache?.precipitationSum ?? .precipitationProbabilityMax!,
widget.weatherCard!.precipitationSum!, windspeed10MMax:
precipitationProbabilityMax: widget.mainWeatherCache widget.mainWeatherCache?.windspeed10MMax ??
?.precipitationProbabilityMax ?? widget.weatherCard!.windspeed10MMax!,
widget windgusts10MMax:
.weatherCard!.precipitationProbabilityMax!, widget.mainWeatherCache?.windgusts10MMax ??
windspeed10MMax: widget.weatherCard!.windgusts10MMax!,
widget.mainWeatherCache?.windspeed10MMax ?? uvIndexMax:
widget.weatherCard!.windspeed10MMax!, widget.mainWeatherCache?.uvIndexMax ??
windgusts10MMax: widget.weatherCard!.uvIndexMax!,
widget.mainWeatherCache?.windgusts10MMax ?? rainSum: widget.mainWeatherCache?.rainSum ??
widget.weatherCard!.windgusts10MMax!, widget.weatherCard!.rainSum!,
uvIndexMax: widget.mainWeatherCache?.uvIndexMax ?? winddirection10MDominant: widget
widget.weatherCard!.uvIndexMax!, .mainWeatherCache
rainSum: widget.mainWeatherCache?.rainSum ?? ?.winddirection10MDominant ??
widget.weatherCard!.rainSum!,
winddirection10MDominant: widget.mainWeatherCache
?.winddirection10MDominant ??
widget.weatherCard!.winddirection10MDominant!,
index: index,
),
transition: Transition.downToUp),
child: Container(
margin: const EdgeInsets.symmetric(vertical: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
DateFormat.EEEE(locale?.languageCode).format(
widget.mainWeatherCache?.timeDaily?[index] ??
widget.weatherCard!.timeDaily![index]),
style: context.textTheme.labelLarge,
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
status.getImage7Day(widget.mainWeatherCache
?.weathercodeDaily?[index] ??
widget widget
.weatherCard!.weathercodeDaily![index]), .weatherCard!.winddirection10MDominant!,
scale: 3, index: index,
), ),
const SizedBox(width: 5), transition: Transition.downToUp),
Expanded( child: Container(
child: Text( margin: const EdgeInsets.symmetric(vertical: 12),
status.getText(widget.mainWeatherCache child: Row(
?.weathercodeDaily?[index] ?? mainAxisAlignment: MainAxisAlignment.spaceBetween,
widget.weatherCard! children: [
.weathercodeDaily![index]), Expanded(
style: context.textTheme.labelLarge, child: Text(
overflow: TextOverflow.ellipsis, DateFormat.EEEE(locale?.languageCode).format(
), widget.mainWeatherCache
), ?.timeDaily?[index] ??
], widget.weatherCard!.timeDaily![index]),
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
statusImFa.getDegree(widget.mainWeatherCache
?.temperature2MMin?[index]
.round() ??
widget.weatherCard!.temperature2MMin![index]
.round()),
style: context.textTheme.labelLarge, style: context.textTheme.labelLarge,
), ),
Text( ),
' / ', Expanded(
style: context.textTheme.bodyMedium?.copyWith( child: Row(
color: Colors.grey, mainAxisAlignment: MainAxisAlignment.center,
), children: [
Image.asset(
status.getImage7Day(widget.mainWeatherCache
?.weathercodeDaily?[index] ??
widget.weatherCard!
.weathercodeDaily![index]),
scale: 3,
),
const SizedBox(width: 5),
Expanded(
child: Text(
status.getText(widget.mainWeatherCache
?.weathercodeDaily?[index] ??
widget.weatherCard!
.weathercodeDaily![index]),
style: context.textTheme.labelLarge,
overflow: TextOverflow.ellipsis,
),
),
],
), ),
Text( ),
statusImFa.getDegree(widget.mainWeatherCache Expanded(
?.temperature2MMax?[index] child: Row(
.round() ?? mainAxisAlignment: MainAxisAlignment.end,
widget.weatherCard!.temperature2MMax![index] children: [
.round()), Text(
style: context.textTheme.bodyMedium?.copyWith( statusImFa.getDegree(widget.mainWeatherCache
color: Colors.grey, ?.temperature2MMin?[index]
), .round() ??
widget.weatherCard!
.temperature2MMin![index]
.round()),
style: context.textTheme.labelLarge,
),
Text(
' / ',
style:
context.textTheme.bodyMedium?.copyWith(
color: Colors.grey,
),
),
Text(
statusImFa.getDegree(widget.mainWeatherCache
?.temperature2MMax?[index]
.round() ??
widget.weatherCard!
.temperature2MMax![index]
.round()),
style:
context.textTheme.bodyMedium?.copyWith(
color: Colors.grey,
),
),
],
), ),
], ),
), ],
), ),
], ),
), );
), },
);
},
),
),
const Divider(),
InkWell(
onTap: widget.onTap,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(
'weatherMore'.tr,
style: context.textTheme.titleLarge?.copyWith(
fontSize: 16,
), ),
overflow: TextOverflow.ellipsis,
), ),
), const Divider(),
InkWell(
onTap: widget.onTap,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(
'weatherMore'.tr,
style: context.textTheme.titleLarge?.copyWith(
fontSize: 16,
),
overflow: TextOverflow.ellipsis,
),
),
),
],
), ),
], ),
), ),
); );
} }

View file

@ -15,6 +15,11 @@ class ThemeController extends GetxController {
isar.writeTxn(() async => isar.settings.put(settings)); isar.writeTxn(() async => isar.settings.put(settings));
} }
void saveMaterialTheme(bool isMaterial) async {
settings.materialColor = isMaterial;
isar.writeTxn(() async => isar.settings.put(settings));
}
void saveTheme(bool isDarkMode) async { void saveTheme(bool isDarkMode) async {
settings.theme = isDarkMode; settings.theme = isDarkMode;
isar.writeTxn(() async => isar.settings.put(settings)); isar.writeTxn(() async => isar.settings.put(settings));