diff --git a/README.md b/README.md
index 4a0b0bb..6b2b849 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,15 @@
-![app_screens](Screenshots/Overmorrow_white_circle_mini.png)
-
# Overmorrow weather
-![app_gallery](Screenshots/new_preview.png)
+![app_gallery](Screenshots/new_feature_graphic_yellow.jpg)
+
+## Minimalist colorful weather app
+
+![app_gallery](Screenshots/app_gallery4_tranparent.png)
-### Beautiful minimalist weather app.
-![app_screens](Screenshots/app_gallery3.png)
| [![Download on Google Play](/Screenshots/play_badge4.png 'Download')](https://play.google.com/store/apps/details?id=com.marotidev.Overmorrow) | [![Download on IzzyOnDroid](/Screenshots/IzzyOnDroid_c.png 'Download')](https://apt.izzysoft.de/fdroid/index/apk/com.marotidev.Overmorrow/) |
|---|---|
-
## Weather providers 🌨️
- [open-meteo](https://open-meteo.com)
- [weatherapi.com](https://www.weatherapi.com)
@@ -59,6 +58,8 @@ So instead here is my take on the weather app ui (but i did kep it free and ad f
- ✅ Settings/Info/Donate pages
- ✅ Tablet mode
- ✅ more than one weather provider
+- ✅ add network images
+- ✅ material you
#### hope to add in the near-future:
diff --git a/Screenshots/Overmorrow_white_circle_mini.png b/Screenshots/Overmorrow_white_circle_mini.png
deleted file mode 100644
index 0ce8b46..0000000
Binary files a/Screenshots/Overmorrow_white_circle_mini.png and /dev/null differ
diff --git a/Screenshots/app_gallery4_tranparent.png b/Screenshots/app_gallery4_tranparent.png
new file mode 100644
index 0000000..4744e39
Binary files /dev/null and b/Screenshots/app_gallery4_tranparent.png differ
diff --git a/Screenshots/new_feature_graphic_yellow.jpg b/Screenshots/new_feature_graphic_yellow.jpg
new file mode 100644
index 0000000..f143a51
Binary files /dev/null and b/Screenshots/new_feature_graphic_yellow.jpg differ
diff --git a/Screenshots/new_preview.png b/Screenshots/new_preview.png
deleted file mode 100644
index 72a8a44..0000000
Binary files a/Screenshots/new_preview.png and /dev/null differ
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 431f645..f2015cd 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -63,8 +63,8 @@ android {
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
- versionCode 41
- versionName "2.4.1"
+ versionCode 42
+ versionName "2.4.2"
}
buildTypes {
diff --git a/lib/decoders/decode_OM.dart b/lib/decoders/decode_OM.dart
index af33ed1..453642d 100644
--- a/lib/decoders/decode_OM.dart
+++ b/lib/decoders/decode_OM.dart
@@ -583,7 +583,9 @@ class OMHour {
sunstatus, item["hourly"]["time"][index])),
time: settings["Time mode"] == '12 hour'? oMamPmTime(item["hourly"]["time"][index]) : oM24hour(item["hourly"]["time"][index]),
- precip: unit_coversion(item["hourly"]["precipitation"][index], settings["Precipitation"]),
+ precip: double.parse(
+ unit_coversion(item["hourly"]["precipitation"][index], settings["Precipitation"]).toStringAsFixed(1)),
+
precip_prob: item["hourly"]["precipitation_probability"][index],
wind: double.parse(
unit_coversion(item["hourly"]["wind_speed_10m"][index], settings["Wind"]).toStringAsFixed(1)),
@@ -614,7 +616,7 @@ class OMSunstatus {
? OMConvertTime(item["daily"]["sunrise"][0])
: OMamPmTime(item["daily"]["sunrise"][0]),
sunset: settings["Time mode"] == "24 hour"
- ? OMConvertTime(item["daily"]["sunrise"][0])
+ ? OMConvertTime(item["daily"]["sunset"][0])
: OMamPmTime(item["daily"]["sunset"][0]),
absoluteSunriseSunset: "${OMConvertTime(item["daily"]["sunrise"][0])}/"
"${OMConvertTime(item["daily"]["sunset"][0])}",
diff --git a/lib/decoders/decode_mn.dart b/lib/decoders/decode_mn.dart
index 3c7e713..9e6466d 100644
--- a/lib/decoders/decode_mn.dart
+++ b/lib/decoders/decode_mn.dart
@@ -16,17 +16,20 @@ along with this program. If not, see .
*/
+import 'dart:convert';
import 'dart:math';
-import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:overmorrow/Icons/overmorrow_weather_icons_icons.dart';
+import 'package:overmorrow/decoders/decode_OM.dart';
+import 'package:worldtime/worldtime.dart';
-import 'package:overmorrow/decoders/decode_wapi.dart';
-
+import '../caching.dart';
import '../settings_page.dart';
import '../ui_helper.dart';
import '../weather_refact.dart';
+import 'decode_wapi.dart';
+import 'extra_info.dart';
String metNTextCorrection(String text, {language = 'English'}) {
String p = metNWeatherToText[text] ?? 'Clear Sky';
@@ -34,6 +37,55 @@ String metNTextCorrection(String text, {language = 'English'}) {
return t;
}
+int metNCalculateHourDif(DateTime timeThere) {
+ DateTime now = DateTime.now().toUtc();
+
+ return now.hour - timeThere.hour;
+}
+
+int metNcalculateFeelsLike(double t, double r, double v) {
+ //unfortunately met norway has no feels like temperatures, so i have to calculate it myself based on:
+ //temperature, relative humidity, and wind speed
+ // https://meteor.geol.iastate.edu/~ckarsten/bufkit/apparent_temperature.html
+
+ if (t >= 24) {
+ t = (t * 1.8) + 32;
+
+ double heat_index = -42.379 + (2.04901523 * t) + (10.14333127 * r)
+ - (0.22475541 * t * r) - (0.00683783 * t * t)
+ - (0.05481717 * r * r) + (0.00122874 * t * t * r)
+ + (0.00085282 * t * r * r) - (0.00000199 * t * t * r * r);
+
+ return ((heat_index - 32) / 1.8).round();
+ }
+
+ else if (t <= 13) {
+ t = (t * 1.8) + 32;
+
+ double wind_chill = 35.74 + (0.6215 * t) - (35.75 * pow(v, 0.16)) + (0.4275 * t * pow(v, 0.16));
+
+ return ((wind_chill - 32) / 1.8).round();
+ }
+
+ else {
+ return t.round();
+ }
+
+}
+
+String metNGetName(index, settings, item, start) {
+ if (index < 3) {
+ const names = ['Today', 'Tomorrow', 'Overmorrow'];
+ return translation(names[index], settings["Language"]);
+ }
+ String x = item["properties"]["timeseries"][start]["time"].split("T")[0];
+ List z = x.split("-");
+ DateTime time = DateTime(int.parse(z[0]), int.parse(z[1]), int.parse(z[2]));
+ const weeks = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
+ String weekname = translation(weeks[time.weekday - 1], settings["Language"]);
+ return "$weekname, ${time.month}/${time.day}";
+}
+
String metNBackdropCorrection(String text) {
return textBackground[text] ?? 'clear_sky3.jpg';
}
@@ -54,10 +106,10 @@ IconData metNIconCorrection(String text) {
return textMaterialIcon[text] ?? OvermorrowWeatherIcons.sun2;
}
-String metNTimeCorrect(String date) {
+String metNTimeCorrect(String date, int hourDif) {
final realtime = date.split('T')[1];
final realhour = realtime.split(':')[0];
- final num = int.parse(realhour);
+ final num = (int.parse(realhour) - hourDif) % 24;
if (num == 0) {
return '12am';
}
@@ -66,7 +118,7 @@ String metNTimeCorrect(String date) {
return '${minusHour}am';
}
else if (num < 12) {
- return realhour + 'am';
+ return '${realhour}am';
}
else if (num == 12) {
return '12pm';
@@ -74,58 +126,207 @@ String metNTimeCorrect(String date) {
return '${num - 12}pm';
}
+String metN24HourTime(String date, int hourDif) {
+ final realtime = date.split('T')[1];
+ final realhour = realtime.split(':')[0];
+ final num = (int.parse(realhour) - hourDif) % 24;
+ final hour = num.toString().padLeft(2, "0");
+ final minute = realtime.split(':')[1].padLeft(2, "0");
+ return "$hour:$minute";
+}
+
+Future MetNGetLocalTime(lat, lng) async {
+ return await Worldtime().timeByLocation(
+ latitude: lat,
+ longitude: lng,
+ );
+}
+
+Future> MetNMakeRequest(double lat, double lng, String real_loc) async {
+
+ final MnParams = {
+ "lat" : lat.toString(),
+ "lon" : lng.toString(),
+ "altitude" : "100",
+ };
+ final headers = {
+ "User-Agent": "Overmorrow weather (com.marotidev.overmorrow)"
+ };
+ final MnUrl = Uri.https("api.met.no", 'weatherapi/locationforecast/2.0/complete', MnParams);
+
+ var MnFile = await cacheManager2.getSingleFile(MnUrl.toString(), key: "$real_loc, met.no", headers: headers).timeout(const Duration(seconds: 6));
+ var MnResponse = await MnFile.readAsString();
+ final MnData = jsonDecode(MnResponse);
+
+ DateTime fetch_datetime = await MnFile.lastModified();
+ return [MnData, fetch_datetime];
+
+}
+
class MetNCurrent {
final String text;
- final String backdrop;
final int temp;
- final List contentColor;
final int humidity;
+ final int feels_like;
final int uv;
final double precip;
+
final int wind;
- final Color backcolor;
- final Color accentcolor;
+ final int wind_dir;
+
+ final Color surface;
+ final Color primary;
+ final Color primaryLight;
+ final Color primaryLighter;
+ final Color onSurface;
+ final Color outline;
+ final Color containerLow;
+ final Color container;
+ final Color containerHigh;
+ final Color colorPop;
+ final Color descColor;
+ final Color surfaceVariant;
+ final Color onPrimaryLight;
+ final Color primarySecond;
+
+ final Color backup_primary;
+ final Color backup_backcolor;
+
+ final Image image;
+
+ final String photographerName;
+ final String photographerUrl;
+ final String photoUrl;
+
+ final List imageDebugColors;
const MetNCurrent({
required this.precip,
- required this.accentcolor,
- required this.backcolor,
- required this.backdrop,
- required this.contentColor,
required this.humidity,
+ required this.feels_like,
required this.temp,
required this.text,
required this.uv,
required this.wind,
+ required this.backup_backcolor,
+ required this.backup_primary,
+ required this.wind_dir,
+
+ required this.surface,
+ required this.primary,
+ required this.primaryLight,
+ required this.primaryLighter,
+ required this.onSurface,
+ required this.outline,
+ required this.containerLow,
+ required this.container,
+ required this.containerHigh,
+ required this.colorPop,
+ required this.descColor,
+ required this.surfaceVariant,
+ required this.onPrimaryLight,
+ required this.primarySecond,
+
+ required this.image,
+ required this.photographerName,
+ required this.photographerUrl,
+ required this.photoUrl,
+ required this.imageDebugColors,
});
- static MetNCurrent fromJson(item, settings) => MetNCurrent(
- text: metNTextCorrection(item["timeseries"][0]["data"]["next_1_hours"]["summary"]["symbol_code"], language: settings["Language"]),
-
- precip: unit_coversion(item["timeseries"][0]["data"]["next_1_hours"]["details"]["precipitation_amount"], settings["Precipitation"]),
- temp: unit_coversion(item["timeseries"][0]["data"]["instant"]["details"]["air_temperature"], settings["Temperature"]).round(),
- humidity: item["timeseries"][0]["data"]["instant"]["details"]["relative_humidity"],
- wind: unit_coversion(item["timeseries"][0]["data"]["instant"]["details"]["wind_speed"] * 3.6, settings["Wind"]).round(),
- uv: item["timeseries"][0]["data"]["instant"]["details"]["ultraviolet_index_clear_sky"],
-
- backdrop: metNBackdropCorrection(
- metNTextCorrection(item["timeseries"][0]["data"]["next_1_hours"]["summary"]["symbol_code"]),
- ),
- backcolor: metNBackColorCorrection(
- metNTextCorrection(item["timeseries"][0]["data"]["next_1_hours"]["summary"]["symbol_code"]),
- ),
- accentcolor: metNAccentColorCorrection(
- metNTextCorrection(item["timeseries"][0]["data"]["next_1_hours"]["summary"]["symbol_code"]),
- ),
- contentColor: metNContentColorCorrection(
- metNTextCorrection(item["timeseries"][0]["data"]["next_1_hours"]["summary"]["symbol_code"]),
- ),
- );
+ static Future fromJson(item, settings, real_loc, lat, lng) async {
+
+ Image Uimage;
+
+ String photographerName = "";
+ String photorgaperUrl = "";
+ String photoLink = "";
+
+ if (settings["Image source"] == "network") {
+ final text = metNTextCorrection(
+ item["properties"]["timeseries"][0]["data"]["next_1_hours"]["summary"]["symbol_code"],
+ language: "English");
+ final ImageData = await getUnsplashImage(text, real_loc, lat, lng);
+ Uimage = ImageData[0];
+ photographerName = ImageData[1];
+ photorgaperUrl = ImageData[2];
+ photoLink = ImageData[3];
+ }
+ else {
+ String imagePath = metNBackdropCorrection(
+ metNTextCorrection(item["properties"]["timeseries"][0]["data"]["next_1_hours"]["summary"]["symbol_code"]),
+ );
+ Uimage = Image.asset("assets/backdrops/$imagePath", fit: BoxFit.cover, width: double.infinity, height: double.infinity,);
+ }
+
+ Color back = metNAccentColorCorrection(
+ metNTextCorrection(item["properties"]["timeseries"][0]["data"]["next_1_hours"]["summary"]["symbol_code"]),
+ );
+
+ Color primary = metNBackColorCorrection(
+ metNTextCorrection(item["properties"]["timeseries"][0]["data"]["next_1_hours"]["summary"]["symbol_code"]),
+ );
+
+ List x = await getMainColor(settings, primary, back, Uimage);
+ List colors = x[0];
+ List imageDebugColors = x[1];
+
+ var it = item["properties"]["timeseries"][0]["data"];
+
+ return MetNCurrent(
+ image: Uimage,
+ photographerName: photographerName,
+ photographerUrl: photorgaperUrl,
+ photoUrl: photoLink,
+
+ text: metNTextCorrection(
+ it["next_1_hours"]["summary"]["symbol_code"],
+ language: settings["Language"]),
+
+ precip: unit_coversion(
+ it["next_1_hours"]["details"]["precipitation_amount"],
+ settings["Precipitation"]),
+ temp: unit_coversion(
+ it["instant"]["details"]["air_temperature"],
+ settings["Temperature"]).round(),
+ humidity: it["instant"]["details"]["relative_humidity"].round(),
+ wind: unit_coversion(
+ it["instant"]["details"]["wind_speed"] * 3.6,
+ settings["Wind"]).round(),
+ uv: it["instant"]["details"]["ultraviolet_index_clear_sky"].round(),
+ feels_like: metNcalculateFeelsLike(it["instant"]["details"]["air_temperature"],
+ it["instant"]["details"]["relative_humidity"], it["instant"]["details"]["wind_speed"] * 3.6),
+ imageDebugColors: imageDebugColors,
+ wind_dir: it["instant"]["details"]["wind_from_direction"].round(),
+
+ surface: colors[0],
+ primary: colors[1],
+ primaryLight: colors[2],
+ primaryLighter: colors[3],
+ onSurface: colors[4],
+ outline: colors[5],
+ containerLow: colors[6],
+ container: colors[7],
+ containerHigh: colors[8],
+ surfaceVariant: colors[9],
+ onPrimaryLight: colors[10],
+ primarySecond: colors[11],
+
+ colorPop: colors[12],
+ descColor: colors[13],
+
+ backup_backcolor: back,
+ backup_primary: primary,
+ );
+ }
}
class MetNDay {
final String text;
+
final IconData icon;
+ final double iconSize;
+
final String name;
final String minmaxtemp;
final List hourly;
@@ -133,62 +334,42 @@ class MetNDay {
final int precip_prob;
final double total_precip;
+
final int windspeed;
- final int avg_temp;
+ final int wind_dir;
+
final double mm_precip;
+ final int uv;
const MetNDay({
required this.text,
+
required this.icon,
+ required this.iconSize,
+
required this.name,
required this.minmaxtemp,
required this.hourly,
required this.precip_prob,
- required this.avg_temp,
required this.total_precip,
required this.windspeed,
required this.hourly_for_precip,
required this.mm_precip,
+ required this.uv,
+ required this.wind_dir,
});
- static Build(item, settings, index) {
-
- //finds the beggining of the day in question
- int days_found = 0;
- int index = 0;
- while (days_found < index) {
- String date = item[index]["time"];
- final realtime = date.split('T')[1];
- final realhour = realtime.split(':')[0];
- final num = int.parse(realhour);
- if (num == 0) {
- days_found += 1;
- }
- index += 1;
- }
-
- int begin = index.toInt();
- int end = 0;
-
- while (end == 0) {
- String date = item[index]["time"];
- final realtime = date.split('T')[1];
- final realhour = realtime.split(':')[0];
- final num = int.parse(realhour);
- if (num == 0) {
- end = index.toInt();
- }
- index += 1;
- }
-
- //now we know the timestamps for the beginning and the end of the day
+ static MetNDay fromJson(item, settings, start, end, index, hourDif) {
List temperatures = [];
- List windspeeds = [];
+ List windspeeds = [];
+ List winddirs = [];
List precip_mm = [];
+ List precip = [];
+ List uvs = [];
- int precipProb = 0;
+ int precipProb = -10;
List oneSummary = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
const weather_names = ['Clear Night', 'Partly Cloudy', 'Clear Sky', 'Overcast',
@@ -197,14 +378,18 @@ class MetNDay {
List hours = [];
- for (int n = begin; n < end; n++) {
- MetNHour hour = MetNHour.fromJson(item[n], settings);
+ for (int n = start; n < end; n++) {
+ MetNHour hour = MetNHour.fromJson(item["properties"]["timeseries"][n], settings, hourDif);
temperatures.add(hour.temp);
windspeeds.add(hour.wind);
- precip_mm.add(hour.precip);
+ winddirs.add(hour.wind_dir);
+ uvs.add(hour.uv);
- int index = weather_names.indexOf(hour.text);
- int value = weatherConditionBiassTable[hour.text] ?? 0;
+ precip_mm.add(hour.raw_precip);
+ precip.add(hour.precip);
+
+ int index = weather_names.indexOf(hour.rawText);
+ int value = weatherConditionBiassTable[hour.rawText] ?? 0;
oneSummary[index] += value;
if (hour.precip_prob > precipProb) {
@@ -219,27 +404,40 @@ class MetNDay {
return MetNDay(
mm_precip: precip_mm.reduce((a, b) => a + b),
precip_prob: precipProb,
- avg_temp: (precip_mm.reduce((a, b) => a + b) / temperatures.length).round(),
- minmaxtemp: "${temperatures.reduce(max)}˚/${temperatures.reduce(min)}°",
+ minmaxtemp: "${temperatures.reduce(min)}°/${temperatures.reduce(max)}°",
hourly: hours,
hourly_for_precip: hours,
- total_precip: unit_coversion(precip_mm.reduce((a, b) => a + b), settings["Precipitation"]),
+ total_precip: double.parse(precip.reduce((a, b) => a + b).toStringAsFixed(1)),
windspeed: (windspeeds.reduce((a, b) => a + b) / windspeeds.length).round(),
- name: getName(index, settings),
- text: metNTextCorrection(weather_names[BIndex]),
+ name: metNGetName(index, settings, item, start),
+ text: translation(weather_names[BIndex], settings["Language"]),
icon: metNIconCorrection(weather_names[BIndex]),
+ iconSize: oMIconSizeCorrection(weather_names[BIndex]),
+ wind_dir: (windspeeds.reduce((a, b) => a + b) / windspeeds.length).round(),
+ uv: uvs.reduce(max)
);
}
}
class MetNHour {
final int temp;
+
final IconData icon;
+ final double iconSize;
+
final String time;
final String text;
final double precip;
- final int wind;
final int precip_prob;
+ final double wind;
+ final int wind_dir;
+ final int uv;
+
+ final double raw_temp;
+ final double raw_precip;
+ final double raw_wind;
+
+ final rawText;
const MetNHour(
{
@@ -249,18 +447,158 @@ class MetNHour {
required this.text,
required this.precip,
required this.wind,
+ required this.iconSize,
+ required this.raw_precip,
+ required this.raw_temp,
+ required this.raw_wind,
+ required this.wind_dir,
+ required this.uv,
required this.precip_prob,
+ required this.rawText,
});
- static MetNHour fromJson(item, settings) => MetNHour(
- text: metNTextCorrection(item["data"]["next_1_hours"]["summary"]["symbol_code"], language: settings["Language"]),
- temp: unit_coversion(item["data"]["instant"]["details"]["air_temperature"], settings["Temperature"]).round(),
- precip: item["data"]["next_1_hours"]["details"]["precipitation_amount"],
- precip_prob : item["data"]["next_1_hours"]["details"]["probability_of_precipitation"].round(),
- icon: metNIconCorrection(
- metNTextCorrection(item["timeseries"][0]["data"]["next_1_hours"]["summary"]["symbol_code"]),
- ),
- time: metNTimeCorrect(item["time"]),
- wind: unit_coversion(item["data"]["instant"]["details"]["wind_speed"] * 3.6, settings["Wind"]).round(),
+ static MetNHour fromJson(item, settings, hourDif) {
+ var nextHours = item["data"]["next_1_hours"] ?? item["data"]["next_6_hours"];
+ return MetNHour(
+ rawText: metNTextCorrection(
+ nextHours["summary"]["symbol_code"]),
+ text: metNTextCorrection(
+ nextHours["summary"]["symbol_code"],
+ language: settings["Language"]),
+ temp: unit_coversion(
+ item["data"]["instant"]["details"]["air_temperature"],
+ settings["Temperature"]).round(),
+ precip: unit_coversion(
+ nextHours["details"]["precipitation_amount"],
+ settings["Precipitation"]),
+ precip_prob: (nextHours["details"]["probability_of_precipitation"] ??
+ 0).round(),
+ icon: metNIconCorrection(
+ metNTextCorrection(
+ nextHours["summary"]["symbol_code"]),
+ ),
+ time: settings["Time mode"] == "24 hour" ?
+ metN24HourTime(item["time"], hourDif) : metNTimeCorrect(item["time"], hourDif),
+ wind: double.parse(unit_coversion(
+ item["data"]["instant"]["details"]["wind_speed"] * 3.6,
+ settings["Wind"]).toStringAsFixed(1)),
+ wind_dir: item["data"]["instant"]["details"]["wind_from_direction"]
+ .round(),
+ uv: (item["data"]["instant"]["details"]["ultraviolet_index_clear_sky"] ?? 0)
+ .round(),
+
+ raw_wind: item["data"]["instant"]["details"]["wind_speed"] * 3.6,
+ raw_precip: nextHours["details"]["precipitation_amount"],
+ raw_temp: item["data"]["instant"]["details"]["air_temperature"],
+ iconSize: oMIconSizeCorrection(metNTextCorrection(
+ nextHours["summary"]["symbol_code"]),)
+ );
+ }
+}
+
+
+class MetNSunstatus {
+ final String sunrise;
+ final String sunset;
+ final double sunstatus;
+ final String absoluteSunriseSunset;
+
+ const MetNSunstatus({
+ required this.sunrise,
+ required this.sunstatus,
+ required this.sunset,
+ required this.absoluteSunriseSunset,
+ });
+
+ static Future fromJson(item, settings, lat, lng, int dif, DateTime timeThere) async {
+ final MnParams = {
+ "lat" : lat.toString(),
+ "lon" : lng.toString(),
+ "date" : "${timeThere.year}-${timeThere.month.toString().padLeft(2, "0")}-${timeThere.day.toString().padLeft(2, "0")}",
+ };
+ final headers = {
+ "User-Agent": "Overmorrow weather (com.marotidev.overmorrow)"
+ };
+ final MnUrl = Uri.https("api.met.no", 'weatherapi/sunrise/3.0/sun', MnParams);
+
+ var MnFile = await cacheManager2.getSingleFile(MnUrl.toString(), key: "$lat, $lng, sunstatus met.no", headers: headers).timeout(const Duration(seconds: 6));
+ var MnResponse = await MnFile.readAsString();
+ final item = jsonDecode(MnResponse);
+
+ List sunriseString = item["properties"]["sunrise"]["time"].split("T")[1].split("+")[0].split(":");
+ DateTime sunrise = timeThere.copyWith(
+ hour: (int.parse(sunriseString[0]) - dif) % 24,
+ minute: int.parse(sunriseString[1]),
+ );
+
+ List sunsetString = item["properties"]["sunset"]["time"].split("T")[1].split("+")[0].split(":");
+ DateTime sunset = timeThere.copyWith(
+ hour: (int.parse(sunsetString[0]) - dif) % 24,
+ minute: int.parse(sunsetString[1]),
+ );
+
+ return MetNSunstatus(
+ sunrise: settings["Time mode"] == "24 hour"
+ ? "${sunrise.hour.toString().padLeft(2, "0")}:${sunrise.minute.toString().padLeft(2, "0")}"
+ : OMamPmTime("T${sunrise.hour}:${sunrise.minute}"),
+ sunset: settings["Time mode"] == "24 hour"
+ ? "${sunset.hour.toString().padLeft(2, "0")}:${sunset.minute.toString().padLeft(2, "0")}"
+ : OMamPmTime("T${sunset.hour}:${sunset.minute}"),
+ absoluteSunriseSunset: "${sunrise.hour}:${sunrise.minute}/${sunset.hour}:${sunset.minute}",
+ sunstatus: min(max(
+ timeThere.difference(sunrise).inMinutes / sunset.difference(sunrise).inMinutes, 0), 1),
+ );
+ }
+}
+
+Future MetNGetWeatherData(lat, lng, real_loc, settings, placeName) async {
+
+ DateTime localTime = await MetNGetLocalTime(lat, lng);
+ int hourDif = metNCalculateHourDif(localTime);
+
+ var Mn = await MetNMakeRequest(lat, lng, real_loc);
+ var MnBody = Mn[0];
+
+ DateTime fetch_datetime = Mn[1];
+
+ MetNSunstatus sunstatus = await MetNSunstatus.fromJson(MnBody, settings, lat, lng, hourDif, localTime);
+
+ List days = [];
+
+ int begin = 0;
+ int index = 0;
+
+ int previous_hour = 0;
+ for (int n = 0; n < MnBody["properties"]["timeseries"].length; n++) {
+ int hour = (int.parse(MnBody["properties"]["timeseries"][n]["time"].split("T")[1].split(":")[0]) - hourDif) % 24;
+ if (n > 0 && hour - previous_hour < 1) {
+ MetNDay day = MetNDay.fromJson(MnBody, settings, begin, n, index, hourDif);
+ days.add(day);
+ index += 1;
+ begin = n;
+ }
+ previous_hour = hour;
+ }
+
+ return WeatherData(
+ radar: await RainviewerRadar.getData(),
+ aqi: await OMAqi.fromJson(MnBody, lat, lng, settings),
+ sunstatus: sunstatus,
+ minutely_15_precip: const OM15MinutePrecip(t_minus: "", precip_sum: 0, precips: []), //because MetN has no 15 minute forecast
+
+ current: await MetNCurrent.fromJson(MnBody, settings, real_loc, lat, lng),
+ days: days,
+
+ lat: lat,
+ lng: lng,
+
+ place: placeName,
+ settings: settings,
+ provider: "met norway",
+ real_loc: real_loc,
+
+ fetch_datetime: fetch_datetime,
+ updatedTime: DateTime.now(),
+ localtime: "${localTime.hour}:${localTime.minute}"
);
}
\ No newline at end of file
diff --git a/lib/decoders/decode_wapi.dart b/lib/decoders/decode_wapi.dart
index cee1291..997d494 100644
--- a/lib/decoders/decode_wapi.dart
+++ b/lib/decoders/decode_wapi.dart
@@ -322,7 +322,7 @@ class WapiCurrent {
if (settings["Image source"] == "network") {
final text = textCorrection(
item["current"]["condition"]["code"], item["current"]["is_day"],
- language: settings["Language"]
+ language: "English"
);
final ImageData = await getUnsplashImage(text, real_loc, lat, lng);
Uimage = ImageData[0];
@@ -444,7 +444,7 @@ class WapiDay {
item["day"]["condition"]["code"], 1
),
iconSize: oMIconSizeCorrection(textCorrection(
- item["day"]["condition"]["code"], 1, language: settings["Language"]
+ item["day"]["condition"]["code"], 1, language: "English"
),),
name: getName(index, settings),
minmaxtemp: '${unit_coversion(item["day"]["maxtemp_c"], settings["Temperature"]).round()}°'
@@ -522,7 +522,7 @@ class WapiHour {
item["condition"]["code"], item["is_day"]
),
iconSize: oMIconSizeCorrection(textCorrection(
- item["condition"]["code"], item["is_day"], language: settings["Language"]
+ item["condition"]["code"], item["is_day"], language: "English",
),),
temp: unit_coversion(item["temp_c"], settings["Temperature"]).round(),
time: getTime(item["time"], settings["Time mode"] == '12 hour'),
@@ -615,7 +615,6 @@ Future WapiGetWeatherData(lat, lng, real_loc, settings, placeName)
var wapi_body = wapi[0];
DateTime fetch_datetime = wapi[1];
- //String real_time = wapi_body["location"]["localtime"];
int epoch = wapi_body["location"]["localtime_epoch"];
WapiSunstatus sunstatus = WapiSunstatus.fromJson(wapi_body, settings);
diff --git a/lib/decoders/extra_info.dart b/lib/decoders/extra_info.dart
index 7dfb41e..3005035 100644
--- a/lib/decoders/extra_info.dart
+++ b/lib/decoders/extra_info.dart
@@ -25,6 +25,7 @@ import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:overmorrow/decoders/decode_OM.dart';
+import 'package:overmorrow/decoders/decode_mn.dart';
import 'package:overmorrow/settings_page.dart';
import 'package:palette_generator/palette_generator.dart';
@@ -35,6 +36,18 @@ import '../ui_helper.dart';
import '../weather_refact.dart';
import 'decode_wapi.dart';
+class HexColor extends Color {
+ static int _getColorFromHex(String hexColor) {
+ hexColor = hexColor.toUpperCase().replaceAll("#", "");
+ if (hexColor.length == 6) {
+ hexColor = "FF$hexColor";
+ }
+ return int.parse(hexColor, radix: 16);
+ }
+
+ HexColor(final String hexColor) : super(_getColorFromHex(hexColor));
+}
+
Future> getUnsplashImage(String _text, String real_loc, double lat, double lng) async {
List keys1 = textFilter.keys.toList();
@@ -133,6 +146,10 @@ Future> getUnsplashImage(String _text, String real_loc, double lat
final String username = unsplash_body[index]["user"]["name"] ?? "";
final String photoLink = unsplash_body[index]["links"]["html"] ?? "";
+ //final Color color = HexColor(unsplash_body[index]["color"]);
+
+ print(unsplash_body[index]["color"]);
+
//print((username, userLink));
return [Image(image: CachedNetworkImageProvider(image_path), fit: BoxFit.cover,
@@ -300,36 +317,38 @@ Future> _generatorPalette(Image imageWidget) async {
final int imageHeight = imageInfo.image.height;
final int imageWidth = imageInfo.image.height;
- final int desiredSquare = 400; //approximation because the top half image cropped is almost a square
+ const int desiredSquare = 400; //approximation because the top half image cropped is almost a square
- final double crop_x = desiredSquare / imageWidth;
- final double crop_y = desiredSquare / imageHeight;
+ final double cropX = desiredSquare / imageWidth;
+ final double cropY = desiredSquare / imageHeight;
- final double crop_absolute = max(crop_y, crop_x);
+ final double cropAbsolute = max(cropY, cropX);
- final double center_x = imageWidth / 2;
- final double center_y = imageHeight / 2;
+ final double centerX = imageWidth / 2;
+ final double centerY = imageHeight / 2;
- final new_left = center_x - ((desiredSquare / 2) / crop_absolute);
- final new_top = center_y - ((desiredSquare / 2) / crop_absolute);
+ final newLeft = centerX - ((desiredSquare / 2) / cropAbsolute);
+ final newTop = centerY - ((desiredSquare / 2) / cropAbsolute);
- final double regionWidth = 50;
- final double regionHeight = 50;
+ const double regionWidth = 50;
+ const double regionHeight = 50;
final Rect region = Rect.fromLTWH(
- new_left + (50 / crop_absolute),
- new_top + (300 / crop_absolute),
- (regionWidth / crop_absolute),
- (regionHeight / crop_absolute),
+ newLeft + (50 / cropAbsolute),
+ newTop + (300 / cropAbsolute),
+ (regionWidth / cropAbsolute),
+ (regionHeight / cropAbsolute),
);
PaletteGenerator _paletteGenerator = await PaletteGenerator.fromImage(
imageInfo.image,
region: region,
- maximumColorCount: 4
+ maximumColorCount: 4,
+ filters: [],
);
PaletteGenerator _paletteGenerator2 = await PaletteGenerator.fromImage(
imageInfo.image,
- maximumColorCount: 5
+ maximumColorCount: 3,
+ filters: [],
);
imageProvider.resolve(const ImageConfiguration()).removeListener(listener);
@@ -355,7 +374,7 @@ Future _materialPalette(Image imageWidget, theme, color) async {
return ColorScheme.fromSeed(
seedColor: color,
brightness: theme == 'light' ? Brightness.light : Brightness.dark,
- dynamicSchemeVariant: DynamicSchemeVariant.tonalSpot
+ dynamicSchemeVariant: DynamicSchemeVariant.tonalSpot,
);
}
@@ -416,6 +435,9 @@ class WeatherData {
if (provider == 'weatherapi.com') {
return WapiGetWeatherData(lat, lng, real_loc, settings, placeName);
}
+ else if (provider == "met norway"){
+ return MetNGetWeatherData(lat, lng, real_loc, settings, placeName);
+ }
else {
return OMGetWeatherData(lat, lng, real_loc, settings, placeName);
}
@@ -445,8 +467,6 @@ class RainviewerRadar {
final String host = data["host"];
- //int timenow = DateTime.now().toUtc().microsecond;
-
List images = [];
List times = [];
@@ -460,7 +480,6 @@ class RainviewerRadar {
}
for (var x in future) {
- //int dif = x["time"] * 1000 - timenow;
DateTime time = DateTime.fromMillisecondsSinceEpoch(x["time"] * 1000);
images.add(host + x["path"]);
times.add("${time.hour}h ${time.minute}m");
diff --git a/lib/donation_page.dart b/lib/donation_page.dart
index 30b774e..894ee47 100644
--- a/lib/donation_page.dart
+++ b/lib/donation_page.dart
@@ -215,7 +215,7 @@ class _InfoPageState extends State {
),
),
Padding(
- padding: const EdgeInsets.only(top: 40, bottom: 10),
+ padding: const EdgeInsets.only(top: 50, bottom: 10),
child: comfortatext(
translation("weather data:", settings["Language"]), 16,
settings,
@@ -242,6 +242,29 @@ class _InfoPageState extends State {
child: comfortatext("weatherapi", 16, settings, color: primary,
decoration: TextDecoration.underline),
),
+ GestureDetector(
+ onTap: () {
+ HapticFeedback.selectionClick();
+ _launchUrl("https://api.met.no/");
+ },
+ child: comfortatext("met-norway", 16, settings, color: primary,
+ decoration: TextDecoration.underline),
+ ),
+ ],
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.only(top: 30, bottom: 10),
+ child: comfortatext(
+ "${translation("radar", settings["Language"])}:", 16,
+ settings,
+ color: onSurface),
+ ),
+ Padding(
+ padding: EdgeInsets.only(left: 20),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
GestureDetector(
onTap: () {
HapticFeedback.selectionClick();
@@ -250,11 +273,19 @@ class _InfoPageState extends State {
child: comfortatext("rainviewer", 16, settings, color: primary,
decoration: TextDecoration.underline),
),
+ GestureDetector(
+ onTap: () {
+ HapticFeedback.selectionClick();
+ _launchUrl("https://carto.com/");
+ },
+ child: comfortatext("carto", 16, settings, color: primary,
+ decoration: TextDecoration.underline),
+ ),
],
),
),
Padding(
- padding: EdgeInsets.only(top: 40),
+ padding: EdgeInsets.only(top: 50),
child: Wrap(
spacing: 10,
children: [
diff --git a/lib/languages.dart b/lib/languages.dart
index 4f25d51..20b4e69 100644
--- a/lib/languages.dart
+++ b/lib/languages.dart
@@ -1458,49 +1458,6 @@ Map> mainTranslate = {
'godz.',
'ώ',
],
-
- "Overmorrow 2.4.0 introduces Network images!": [
- 'Overmorrow 2.4.0 introduces Network images!',
- 'Az Overmorrow 2.4.0 hálózati képeket vezet be!',
- '¡Overmorrow 2.4.0 introduce imágenes de red!',
- 'Overmorrow 2.4.0 introduit des images réseau !',
- 'Overmorrow 2.4.0 führt Netzwerkbilder ein!',
- 'Overmorrow 2.4.0 introduce immagini di rete!',
- 'Overmorrow 2.4.0 introduz imagens de rede!',
- 'Overmorrow 2.4.0 представляет сетевые изображения!',
- 'Overmorrow 2.4.0 引入了网络图像!',
- 'Overmorrow 2.4.0 にネットワーク画像を導入!',
- 'Overmorrow 2.4.0 wprowadza obrazy z sieci!',
- 'Το Overmorrow 2.4.0 εισάγει εικόνες δικτύου!'
- ],
- "Would you like to enable network images?": [
- 'Would you like to enable network images?',
- 'Szeretnéd engedélyezni a hálózati képeket?',
- '¿Te gustaría habilitar imágenes de red?',
- 'Souhaitez-vous activer les images réseau ?',
- 'Möchten Sie Netzwerkbilder aktivieren?',
- 'Vuoi abilitare le immagini di rete?',
- 'Gostaria de ativar as imagens de rede?',
- 'Хотите включить сетевые изображения?',
- '您想启用网络图像吗?',
- 'ネットワーク画像を有効にしますか?',
- 'Czy chcesz włączyć obrazy z sieci?',
- 'Θέλετε να ενεργοποιήσετε τις εικόνες δικτύου;'
- ],
- "note: you can always change later by going into settings > appearance > image source": [
- 'note: you can always change later by going into settings > appearance > image source',
- 'megjegyzés: később bármikor módosíthatja a beállítások > megjelenés > kép forrása menüpontban',
- 'nota: siempre puedes cambiarlo más tarde en configuración > apariencia > fuente de imagen',
- 'remarque : vous pouvez toujours modifier plus tard en allant dans paramètres > apparence > source d\'image',
- 'Hinweis: Sie können dies später jederzeit unter Einstellungen > Erscheinungsbild > Bildquelle ändern',
- 'nota: puoi sempre modificarlo in seguito andando su impostazioni > aspetto > sorgente immagine',
- 'nota: você pode sempre mudar depois indo para configurações > aparência > fonte de imagem',
- 'примечание: вы всегда можете изменить это позже в настройках > внешний вид > источник изображения',
- '注意:您可以随时通过进入设置 > 外观 > 图片来源来更改',
- '注意:設定 > 外観 > 画像のソース で後からいつでも変更できます',
- 'uwaga: zawsze możesz to zmienić później, przechodząc do ustawień > wygląd > źródło obrazu',
- 'σημείωση: μπορείτε πάντα να αλλάξετε αργότερα πηγαίνοντας στις ρυθμίσεις > εμφάνιση > πηγή εικόνας'
- ],
"Disable": [
'Disable',
'Letiltás',
@@ -1529,6 +1486,48 @@ Map> mainTranslate = {
'Włącz',
'Ενεργοποίηση'
],
+ "Layout": [
+ 'Layout',
+ 'Elrendezés',
+ 'Diseño',
+ 'Disposition',
+ 'Layout',
+ 'Layout',
+ 'Layout',
+ 'Макет',
+ '布局',
+ 'レイアウト',
+ 'Układ',
+ 'Διάταξη'
+ ],
+ "widget order, customization": [
+ 'widget order, customization',
+ 'widget sorrend, személyreszabás',
+ 'orden de widgets, personalización',
+ 'ordre des widgets, personnalisation',
+ 'Widget-Reihenfolge, Anpassung',
+ 'ordine dei widget, personalizzazione',
+ 'ordem de widgets, personalização',
+ 'порядок виджетов, настройка',
+ '小部件顺序,自定义',
+ 'ウィジェットの順序、カスタマイズ',
+ 'kolejność widżetów, dostosowanie',
+ 'σειρά widget, προσαρμογή'
+ ],
+ "30m": [
+ '30m',
+ '30p',
+ '30m',
+ '30m',
+ '30m',
+ '30m',
+ '30m',
+ '30м',
+ '30分',
+ '30分',
+ '30m',
+ '30λ',
+ ],
'Search translation': [ //used for getting the codes used for translation of city names
//If none are available then en (english) is the default
diff --git a/lib/main_screens.dart b/lib/main_screens.dart
index 004a03a..245b0c1 100644
--- a/lib/main_screens.dart
+++ b/lib/main_screens.dart
@@ -26,7 +26,6 @@ import 'package:overmorrow/radar.dart';
import 'package:overmorrow/settings_page.dart';
import 'package:material_floating_search_bar_2/material_floating_search_bar_2.dart';
import 'package:stretchy_header/stretchy_header.dart';
-import 'main.dart';
import 'main_ui.dart';
import 'new_displays.dart';
import 'ui_helper.dart';
@@ -53,13 +52,17 @@ class _NewMainState extends State {
@override
void initState() {
super.initState();
+ /*
+ i'm keeping this in case i need another pop-up sometime
if (data.settings['networkImageDialogShown'] == "false") {
WidgetsBinding.instance.addPostFrameCallback((_) {
_showFeatureDialog(context, data.settings);
});
}
+ */
}
+ /*
void _showFeatureDialog(BuildContext context, settings) {
showDialog(
context: context,
@@ -116,14 +119,30 @@ class _NewMainState extends State {
},
);
}
+ */
@override
Widget build(BuildContext context) {
+
final FlutterView view = WidgetsBinding.instance.platformDispatcher.views.first;
final Size size = view.physicalSize / view.devicePixelRatio;
final FloatingSearchBarController controller = FloatingSearchBarController();
+ final Map widgetsMap = {
+ 'sunstatus': NewSunriseSunset(data: data, key: Key(data.place), size: size,),
+ 'rain indicator': NewRain15MinuteIndicator(data),
+ 'air quality': NewAirQuality(data),
+ 'radar': RadarSmall(data: data, key: Key("${data.place}, ${data.current.surface}")),
+ 'forecast': buildNewDays(data),
+ 'daily': buildNewGlanceDay(data: data),
+ };
+
+ final List order = data.settings["Layout order"].split(",");
+ print(order);
+
+ final List orderedWidgets = order.map((name) => widgetsMap[name]!).toList();
+
String colorMode = data.settings["Color mode"];
if (colorMode == "auto") {
var brightness = SchedulerBinding.instance.platformDispatcher.platformBrightness;
@@ -213,6 +232,7 @@ class _NewMainState extends State {
),
],
),
+
/*
Padding(
padding: const EdgeInsets.only(left: 30),
@@ -241,12 +261,11 @@ class _NewMainState extends State {
),
*/
- NewSunriseSunset(data: data, key: Key(data.place), size: size,),
- NewRain15MinuteIndicator(data),
- NewAirQuality(data),
- RadarSmall(data: data, key: Key("${data.place}, ${data.current.surface}")),
- buildNewDays(data),
- buildNewGlanceDay(data: data),
+ Column(
+ children: orderedWidgets.map((widget) {
+ return widget;
+ }).toList(),
+ ),
Padding(
padding: const EdgeInsets.only(top: 10, bottom: 30),
diff --git a/lib/main_ui.dart b/lib/main_ui.dart
index 9ae3bdb..45d9bfe 100644
--- a/lib/main_ui.dart
+++ b/lib/main_ui.dart
@@ -88,7 +88,7 @@ Widget Circles(double width, var data, double bottom, color, {align = Alignment.
child: SizedBox(
width: width,
child: Container(
- padding: const EdgeInsets.only(top: 25, left: 4, right: 4),
+ padding: const EdgeInsets.only(top: 25, left: 4, right: 4, bottom: 13),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
@@ -142,7 +142,7 @@ Widget Circles(double width, var data, double bottom, color, {align = Alignment.
Widget providerSelector(settings, updateLocation, textcolor, highlight, primary,
provider, latlng, real_loc) {
return Padding(
- padding: const EdgeInsets.only(left: 23, right: 23, top: 15, bottom: 30),
+ padding: const EdgeInsets.only(left: 23, right: 23, bottom: 30, top: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -157,7 +157,7 @@ Widget providerSelector(settings, updateLocation, textcolor, highlight, primary,
),
),
Padding(
- padding: const EdgeInsets.only(top: 10),
+ padding: const EdgeInsets.only(top: 12),
child: Container(
decoration: BoxDecoration(
color: highlight,
@@ -178,7 +178,7 @@ Widget providerSelector(settings, updateLocation, textcolor, highlight, primary,
),
//value: selected_temp_unit.isNotEmpty ? selected_temp_unit : null, // guard it with null if empty
value: provider.toString(),
- items: ['weatherapi.com', 'open-meteo'].map((item) {
+ items: ['weatherapi.com', 'open-meteo', 'met norway'].map((item) {
return DropdownMenuItem(
value: item,
child: Text(item),
diff --git a/lib/new_displays.dart b/lib/new_displays.dart
index c0ab1b8..e2fd451 100644
--- a/lib/new_displays.dart
+++ b/lib/new_displays.dart
@@ -138,7 +138,7 @@ class _NewSunriseSunsetState extends State with SingleTickerPr
String write = widget.data.settings["Time mode"] == "24 hour"
? OMConvertTime(
- "j T${localTime.hour}:${localTime.minute}") //the j is just added so when splitting
+ "j T${localTime.hour.toString().padLeft(2, "0")}:${localTime.minute.toString().padLeft(2, "0")}") //the j is just added so when splitting
: OMamPmTime(
"j T${localTime.hour}:${localTime.minute}"); //it can grab the second item
@@ -157,7 +157,7 @@ class _NewSunriseSunsetState extends State with SingleTickerPr
final textWidth = textPainter.width;
return Padding(
- padding: const EdgeInsets.only(left: 25, right: 25, top: 13),
+ padding: const EdgeInsets.only(left: 25, right: 25, bottom: 23),
child: Column(
children: [
Padding(
@@ -243,7 +243,7 @@ class _NewSunriseSunsetState extends State with SingleTickerPr
Widget NewAirQuality(var data) {
return Padding(
- padding: const EdgeInsets.only(left: 20, right: 20, bottom: 19, top: 23),
+ padding: const EdgeInsets.only(left: 20, right: 20, bottom: 59),
child: Column(
children: [
Align(
@@ -316,7 +316,7 @@ Widget NewRain15MinuteIndicator(var data) {
return Visibility(
visible: data.minutely_15_precip.t_minus != "",
child: Padding(
- padding: const EdgeInsets.only(left: 21, right: 21, top: 23, bottom: 15),
+ padding: const EdgeInsets.only(left: 21, right: 21, bottom: 38),
child: Container(
decoration: BoxDecoration(
color: data.current.containerLow,
@@ -357,7 +357,7 @@ Widget NewRain15MinuteIndicator(var data) {
],
),
Padding(
- padding: const EdgeInsets.only(top: 14, bottom: 10),
+ padding: const EdgeInsets.only(top: 14, bottom: 8),
child: SizedBox(
height: 30,
child: ListView.builder(
@@ -382,7 +382,6 @@ Widget NewRain15MinuteIndicator(var data) {
),
),
SizedBox(
- height: 10,
width: 11.0 * data.minutely_15_precip.precips.length + 11,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
diff --git a/lib/new_forecast.dart b/lib/new_forecast.dart
index 237cccb..3cf5002 100644
--- a/lib/new_forecast.dart
+++ b/lib/new_forecast.dart
@@ -99,25 +99,26 @@ class _NewDayState extends State with AutomaticKeepAliveClientMixin {
),
),
Padding(
- padding: const EdgeInsets.only(top: 15, left: 23, right: 25),
+ padding: const EdgeInsets.only(top: 18, left: 23, right: 25),
child: Row(
children: [
SizedBox(
width: 35,
child: Icon(day.icon, size: 38.0 * day.iconSize, color: data.current.primary,)),
- Padding(
- padding: const EdgeInsets.only(left: 12.0, top: 3),
- child: comfortatext(day.text, 20, data.settings, color: data.current.onSurface,
- weight: FontWeight.w400),
+ Expanded(
+ child: Padding(
+ padding: const EdgeInsets.only(left: 12.0, top: 3),
+ child: comfortatext(day.text, 20, data.settings, color: data.current.onSurface,
+ weight: FontWeight.w400),
+ ),
),
- const Spacer(),
Padding(
padding: const EdgeInsets.only(top: 4),
child: Row(
children: [
comfortatext(day.minmaxtemp.split("/")[0], 20, data.settings, color: data.current.primary),
Padding(
- padding: const EdgeInsets.only(left: 5, right: 4),
+ padding: const EdgeInsets.only(left: 5, right: 7),
child: comfortatext("/", 19, data.settings, color: data.current.onSurface),
),
comfortatext(day.minmaxtemp.split("/")[1], 20, data.settings, color: data.current.primary),
@@ -267,7 +268,7 @@ class _NewDayState extends State with AutomaticKeepAliveClientMixin {
),
),
SizedBox(
- height: state? 280 : 250,
+ height: state? 280 : 260,
child: PageView(
physics: const NeverScrollableScrollPhysics(),
controller: _pageController,
@@ -286,7 +287,7 @@ class _NewDayState extends State with AutomaticKeepAliveClientMixin {
Widget buildNewDays(data) {
return ListView.builder(
- padding: const EdgeInsets.only(top: 50, left: 20, right: 20),
+ padding: const EdgeInsets.only(left: 20, right: 20, bottom: 10),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: 3,
@@ -707,7 +708,7 @@ class _buildNewGlanceDayState extends State with AutomaticKee
super.build(context);
if (data.days.length > 3) {
return Padding(
- padding: const EdgeInsets.only(left: 24, right: 24, bottom: 10, top: 10),
+ padding: const EdgeInsets.only(left: 24, right: 24, bottom: 25),
child: Column(
children: [
Padding(
diff --git a/lib/radar.dart b/lib/radar.dart
index be49719..53d0856 100644
--- a/lib/radar.dart
+++ b/lib/radar.dart
@@ -28,6 +28,8 @@ import 'package:overmorrow/settings_page.dart';
import 'package:overmorrow/ui_helper.dart';
import 'package:latlong2/latlong.dart';
+import 'decoders/decode_OM.dart';
+
class RadarSmall extends StatefulWidget {
final data;
@@ -64,7 +66,13 @@ class _RadarSmallState extends State {
for (int i = 0; i < data.radar.times.length; i++) {
List split = data.radar.times[i].split("h");
String minute = split[1].replaceAll(RegExp(r"\D"), "");
- times.add("${int.parse(split[0]) + offset}:${minute == "0" ? "00" : minute}");
+ int hour = (int.parse(split[0]) + offset) % 24;
+ if (data.settings["Time mode"] == "12 hour") {
+ times.add(OMamPmTime("jT$hour:${minute == "0" ? "00" : minute}"));
+ }
+ else {
+ times.add("${hour.toString().padLeft(2, "0")}:${minute == "0" ? "00" : minute}");
+ }
}
timer = Timer.periodic(const Duration(milliseconds: 1000), (Timer t) {
@@ -112,7 +120,7 @@ class _RadarSmallState extends State {
return Column(
children: [
Padding(
- padding: const EdgeInsets.only(left: 25, top: 40),
+ padding: const EdgeInsets.only(left: 25),
child: Align(
alignment: Alignment.centerLeft,
child: comfortatext(
@@ -123,7 +131,7 @@ class _RadarSmallState extends State {
),
Padding(
padding: const EdgeInsets.only(
- left: 25, right: 25, top: 12, bottom: 10),
+ left: 25, right: 25, top: 12, bottom: 10,),
child: AspectRatio(
aspectRatio: 1.57,
child: Container(
@@ -216,7 +224,7 @@ class _RadarSmallState extends State {
),
),
Padding(
- padding: const EdgeInsets.only(left: 38, right: 25, bottom: 0, top: 10),
+ padding: const EdgeInsets.only(left: 38, right: 25, bottom: 50, top: 10),
child: Row(
children: [
AnimatedSwitcher(
@@ -300,26 +308,26 @@ class _RadarSmallState extends State {
padding: const EdgeInsets.only(left: 16, right: 16, top: 9),
child: Row(
children: [
- comfortatext('-2hr', 13, data.settings, color: data.current.onSurface),
+ comfortatext('-2${translation('hr', data.settings['Language'])}', 13, data.settings, color: data.current.onSurface),
Expanded(
flex: 6,
child: Align(
alignment: Alignment.centerRight,
- child: comfortatext('-1hr', 13, data.settings, color: data.current.onSurface)
+ child: comfortatext('-1${translation('hr', data.settings['Language'])}', 13, data.settings, color: data.current.onSurface)
),
),
Expanded(
flex: 6,
child: Align(
alignment: Alignment.centerRight,
- child: comfortatext('now', 13, data.settings, color: data.current.onSurface)
+ child: comfortatext(translation('now', data.settings["Language"]), 13, data.settings, color: data.current.onSurface)
),
),
Expanded(
flex: 3,
child: Align(
alignment: Alignment.centerRight,
- child: comfortatext('30m', 13, data.settings, color: data.current.onSurface)
+ child: comfortatext(translation('30m', data.settings["Language"]), 13, data.settings, color: data.current.onSurface)
),
),
],
@@ -372,7 +380,13 @@ class _RadarBigState extends State {
for (int i = 0; i < data.radar.times.length; i++) {
List split = data.radar.times[i].split("h");
String minute = split[1].replaceAll(RegExp(r"\D"), "");
- times.add("${int.parse(split[0]) + offset}:${minute == "0" ? "00" : minute}");
+ int hour = (int.parse(split[0]) + offset) % 24;
+ if (data.settings["Time mode"] == "12 hour") {
+ times.add(OMamPmTime("jT$hour:${minute == "0" ? "00" : minute}"));
+ }
+ else {
+ times.add("${hour.toString().padLeft(2, "0")}:${minute == "0" ? "00" : minute}");
+ }
}
@@ -549,26 +563,26 @@ class _RadarBigState extends State {
padding: const EdgeInsets.only(left: 16, right: 16, top: 9),
child: Row(
children: [
- comfortatext('-2hr', 13, data.settings, color: data.current.onSurface),
+ comfortatext('-2${translation('hr', data.settings['Language'])}', 13, data.settings, color: data.current.onSurface),
Expanded(
flex: 6,
child: Align(
alignment: Alignment.centerRight,
- child: comfortatext('-1hr', 13, data.settings, color: data.current.onSurface)
+ child: comfortatext('-1${translation('hr', data.settings['Language'])}', 13, data.settings, color: data.current.onSurface)
),
),
Expanded(
flex: 6,
child: Align(
alignment: Alignment.centerRight,
- child: comfortatext('now', 13, data.settings, color: data.current.onSurface)
+ child: comfortatext(translation('now', data.settings["Language"]), 13, data.settings, color: data.current.onSurface)
),
),
Expanded(
flex: 3,
child: Align(
alignment: Alignment.centerRight,
- child: comfortatext('30m', 13, data.settings, color: data.current.onSurface)
+ child: comfortatext(translation('30m', data.settings["Language"]), 13, data.settings, color: data.current.onSurface)
),
),
],
diff --git a/lib/search_screens.dart b/lib/search_screens.dart
index 8976def..4cfa759 100644
--- a/lib/search_screens.dart
+++ b/lib/search_screens.dart
@@ -491,8 +491,8 @@ class dumbySearch extends StatelessWidget {
return Scaffold(
drawer: MyDrawer(backupprimary: primary, settings: settings, backupback: back, image: Image.asset("assets/backdrops/grayscale_snow2.jpg",
- fit: BoxFit.cover, width: double.infinity, height: double.infinity, color: colors[6],), surface: colors[0],
- onSurface: colors[4], primary: colors[1], hihglight: colors[6],
+ fit: BoxFit.cover, width: double.infinity, height: double.infinity), surface: colors[0],
+ onSurface: colors[4], primary: colors[1], hihglight: colors[6]
),
backgroundColor: colors[0],
body: StretchyHeader.singleChild(
diff --git a/lib/settings_page.dart b/lib/settings_page.dart
index 48401ab..e1f1afd 100644
--- a/lib/settings_page.dart
+++ b/lib/settings_page.dart
@@ -47,6 +47,8 @@ Map> settingSwitches = {
'Search provider' : ['weatherapi', 'open-meteo'],
'networkImageDialogShown' : ["false", "true"],
+
+ 'Layout order' : ["sunstatus,rain indicator,air quality,radar,forecast,daily"],
};
String translation(String text, String language) {
@@ -363,7 +365,12 @@ Future