diff --git a/.gitignore b/.gitignore
index f76f15e..4314849 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,7 +15,6 @@ migrate_working_dir/
*.ipr
*.iws
.idea/
-.cxx/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
@@ -42,4 +41,4 @@ app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
-/android/app/release
+/android/app/release
\ No newline at end of file
diff --git a/.metadata b/.metadata
index 2d1be89..262ceed 100644
--- a/.metadata
+++ b/.metadata
@@ -1,11 +1,11 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
-# This file should be version controlled and should not be manually edited.
+# This file should be version controlled.
version:
- revision: "2663184aa79047d0a33a14a3b607954f8fdd8730"
- channel: "stable"
+ revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ channel: stable
project_type: app
@@ -13,26 +13,26 @@ project_type: app
migration:
platforms:
- platform: root
- create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
- base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
+ create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: android
- create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
- base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
+ create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: ios
- create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
- base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
+ create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: linux
- create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
- base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
+ create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: macos
- create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
- base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
+ create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: web
- create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
- base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
+ create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
- platform: windows
- create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
- base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730
+ create_revision: 135454af32477f815a7525073027a3ff9eff1bfd
+ base_revision: 135454af32477f815a7525073027a3ff9eff1bfd
# User provided section
diff --git a/README.md b/README.md
index 14e161c..faf32d4 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,15 @@
-

-
🌦️ Rain
+

+
🌦️ Rain
-
-
-
-
-
-
+
+
+
+
+
+
Tired of unpredictable weather? Rain's got you covered! Get ready for any forecast. 🌦️
@@ -40,7 +40,7 @@ We fetch weather data from [Open-Meteo](https://open-meteo.com/en/docs) and use
### 📸 Screenshots
-
+
### 💰 Support Us
@@ -52,6 +52,7 @@ If you find Rain valuable and worthy for future innovation, consider supporting
### 📥 Get Rain Now
[](https://play.google.com/store/apps/details?id=com.yoshi.rain)
+[](https://apps.rustore.ru/app/com.yoshi.rain)
Or get the latest APK from the [Releases Section](https://github.com/DarkMooNight/Rain/releases/latest). You can also find the app on IzzyOnDroid via a F-Droid client [here](https://apt.izzysoft.de/fdroid/index/apk/com.yoshi.rain).
@@ -62,5 +63,5 @@ This project is licensed under the [MIT License](./LICENSE).
### 👨💻 Our Contributors
-
+
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 6a479c4..9847a76 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -4,6 +4,24 @@ plugins {
id "dev.flutter.flutter-gradle-plugin"
}
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
@@ -11,73 +29,64 @@ if (keystorePropertiesFile.exists()) {
}
android {
- namespace = 'com.yoshi.rain'
- compileSdk = 35
- ndkVersion = '29.0.13113456'
+ namespace 'com.yoshi.rain'
+ compileSdkVersion 34
+ ndkVersion flutter.ndkVersion
compileOptions {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
- coreLibraryDesugaringEnabled = true
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
- jvmTarget = JavaVersion.VERSION_17
+ jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
- dependenciesInfo {
- // Disables dependency metadata when building APKs.
- includeInApk = false
- // Disables dependency metadata when building Android App Bundles.
- includeInBundle = false
- }
-
defaultConfig {
- applicationId = 'com.yoshi.rain'
- minSdk = 23
- targetSdk = flutter.targetSdkVersion
- versionCode = flutter.versionCode
- versionName = flutter.versionName
+ applicationId "com.yoshi.rain"
+ minSdkVersion 23
+ targetSdkVersion flutter.targetSdkVersion
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
}
signingConfigs {
- release {
- keyAlias = keystoreProperties['keyAlias']
- keyPassword = keystoreProperties['keyPassword']
- storeFile = keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
- storePassword = keystoreProperties['storePassword']
+ release {
+ keyAlias keystoreProperties['keyAlias']
+ keyPassword keystoreProperties['keyPassword']
+ storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
+ storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
- signingConfig = signingConfigs.release
+ signingConfig signingConfigs.release
}
debug {
- signingConfig = signingConfigs.debug
- minifyEnabled = true
+ signingConfig signingConfigs.debug
+ minifyEnabled true
}
}
buildFeatures {
- viewBinding = true
+ viewBinding true
}
}
flutter {
- source = "../.."
+ source '../..'
}
dependencies {
implementation("androidx.core:core-remoteviews:1.1.0")
implementation("com.google.android.material:material:1.12.0")
- implementation('androidx.work:work-runtime-ktx:2.10.0')
- coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
+ implementation("androidx.work:work-runtime-ktx:2.9.0")
}
// Remove this for FLOSS version
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index d02b0cf..1934665 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -18,7 +18,6 @@
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
- android:enableOnBackInvokedCallback="true"
android:windowSoftInputMode="adjustResize">
-
+
\ No newline at end of file
diff --git a/android/gradle.properties b/android/gradle.properties
index a792b07..598d13f 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,4 +1,3 @@
org.gradle.jvmargs=-Xmx4G
android.useAndroidX=true
android.enableJetifier=true
-android.enableR8.fullMode = false
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index c6a2952..3c472b9 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
diff --git a/android/settings.gradle b/android/settings.gradle
index 18a751a..9f0fe47 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -5,9 +5,10 @@ pluginManagement {
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
- }()
+ }
+ settings.ext.flutterSdkPath = flutterSdkPath()
- includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
+ includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
repositories {
google()
@@ -18,8 +19,8 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
- id "com.android.application" version "8.9.0" apply false
- id "org.jetbrains.kotlin.android" version "2.1.10" apply false
+ id "com.android.application" version "7.4.2" apply false
+ id "org.jetbrains.kotlin.android" version "2.0.0" apply false
}
include ":app"
diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift
deleted file mode 100644
index 86a7c3b..0000000
--- a/ios/RunnerTests/RunnerTests.swift
+++ /dev/null
@@ -1,12 +0,0 @@
-import Flutter
-import UIKit
-import XCTest
-
-class RunnerTests: XCTestCase {
-
- func testExample() {
- // If you add code to the Runner application, consider adding tests here.
- // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
- }
-
-}
diff --git a/lib/app/api/api.dart b/lib/app/api/api.dart
old mode 100755
new mode 100644
index f2f6715..2a30802
--- a/lib/app/api/api.dart
+++ b/lib/app/api/api.dart
@@ -3,12 +3,12 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:rain/app/api/city_api.dart';
import 'package:rain/app/api/weather_api.dart';
-import 'package:rain/app/data/db.dart';
+import 'package:rain/app/data/weather.dart';
import 'package:rain/main.dart';
class WeatherAPI {
- final Dio dio =
- Dio()..options.baseUrl = 'https://api.open-meteo.com/v1/forecast?';
+ final Dio dio = Dio()
+ ..options.baseUrl = 'https://api.open-meteo.com/v1/forecast?';
final Dio dioLocation = Dio();
static const String _weatherParams =
@@ -41,25 +41,14 @@ class WeatherAPI {
}
}
- Future getWeatherCard(
- double lat,
- double lon,
- String city,
- String district,
- String timezone,
- ) async {
+ Future getWeatherCard(double lat, double lon, String city,
+ String district, String timezone) async {
final String urlWeather = _buildWeatherUrl(lat, lon);
try {
Response response = await dio.get(urlWeather);
WeatherDataApi weatherData = WeatherDataApi.fromJson(response.data);
return _mapWeatherDataToCard(
- weatherData,
- lat,
- lon,
- city,
- district,
- timezone,
- );
+ weatherData, lat, lon, city, district, timezone);
} on DioException catch (e) {
if (kDebugMode) {
print(e);
@@ -135,14 +124,8 @@ class WeatherAPI {
);
}
- WeatherCard _mapWeatherDataToCard(
- WeatherDataApi weatherData,
- double lat,
- double lon,
- String city,
- String district,
- String timezone,
- ) {
+ WeatherCard _mapWeatherDataToCard(WeatherDataApi weatherData, double lat,
+ double lon, String city, String district, String timezone) {
return WeatherCard(
time: weatherData.hourly.time,
temperature2M: weatherData.hourly.temperature2M,
diff --git a/lib/app/api/city_api.dart b/lib/app/api/city_api.dart
old mode 100755
new mode 100644
index 9712e75..55a3b6a
--- a/lib/app/api/city_api.dart
+++ b/lib/app/api/city_api.dart
@@ -1,14 +1,15 @@
class CityApi {
- CityApi({required this.results});
+ CityApi({
+ required this.results,
+ });
List results;
factory CityApi.fromJson(Map json) => CityApi(
- results:
- json['results'] == null
+ results: json['results'] == null
? List.empty()
: List.from(json['results'].map((x) => Result.fromJson(x))),
- );
+ );
}
class Result {
@@ -25,9 +26,9 @@ class Result {
double longitude;
factory Result.fromJson(Map json) => Result(
- admin1: json['admin1'] ?? '',
- name: json['name'],
- latitude: json['latitude'],
- longitude: json['longitude'],
- );
+ admin1: json['admin1'] ?? '',
+ name: json['name'],
+ latitude: json['latitude'],
+ longitude: json['longitude'],
+ );
}
diff --git a/lib/app/api/weather_api.dart b/lib/app/api/weather_api.dart
old mode 100755
new mode 100644
diff --git a/lib/app/api/weather_api.freezed.dart b/lib/app/api/weather_api.freezed.dart
old mode 100755
new mode 100644
diff --git a/lib/app/api/weather_api.g.dart b/lib/app/api/weather_api.g.dart
old mode 100755
new mode 100644
diff --git a/lib/app/controller/controller.dart b/lib/app/controller/controller.dart
old mode 100755
new mode 100644
index 32d3ceb..1e01069
--- a/lib/app/controller/controller.dart
+++ b/lib/app/controller/controller.dart
@@ -1,6 +1,7 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_timezone/flutter_timezone.dart';
import 'package:geocoding/geocoding.dart';
import 'package:geolocator/geolocator.dart';
@@ -10,11 +11,11 @@ import 'package:isar/isar.dart';
import 'package:lat_lng_to_timezone/lat_lng_to_timezone.dart' as tzmap;
import 'package:path_provider/path_provider.dart';
import 'package:rain/app/api/api.dart';
-import 'package:rain/app/data/db.dart';
-import 'package:rain/app/utils/notification.dart';
-import 'package:rain/app/utils/show_snack_bar.dart';
-import 'package:rain/app/ui/widgets/weather/status/status_data.dart';
-import 'package:rain/app/ui/widgets/weather/status/status_weather.dart';
+import 'package:rain/app/data/weather.dart';
+import 'package:rain/app/services/notification.dart';
+import 'package:rain/app/services/utils.dart';
+import 'package:rain/app/widgets/status/status_data.dart';
+import 'package:rain/app/widgets/status/status_weather.dart';
import 'package:rain/main.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import 'package:timezone/data/latest_all.dart' as tz;
@@ -52,14 +53,15 @@ class WeatherController extends GetxController {
@override
void onInit() {
- weatherCards.assignAll(
- isar.weatherCards.where().sortByIndex().findAllSync(),
- );
+ weatherCards
+ .assignAll(isar.weatherCards.where().sortByIndex().findAllSync());
super.onInit();
}
- Future _determinePosition() async {
- LocationPermission permission = await Geolocator.checkPermission();
+ Future determinePosition() async {
+ LocationPermission permission;
+
+ permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
@@ -69,8 +71,7 @@ class WeatherController extends GetxController {
if (permission == LocationPermission.deniedForever) {
return Future.error(
- 'Location permissions are permanently denied, we cannot request permissions.',
- );
+ 'Location permissions are permanently denied, we cannot request permissions.');
}
return await Geolocator.getCurrentPosition();
}
@@ -79,26 +80,25 @@ class WeatherController extends GetxController {
if (settings.location) {
await getCurrentLocation();
} else {
- final locationCity = isar.locationCaches.where().findFirstSync();
- if (locationCity != null) {
- await getLocation(
- locationCity.lat!,
- locationCity.lon!,
- locationCity.district!,
- locationCity.city!,
- );
+ if ((isar.locationCaches.where().findAllSync()).isNotEmpty) {
+ LocationCache locationCity =
+ (isar.locationCaches.where().findFirstSync())!;
+ await getLocation(locationCity.lat!, locationCity.lon!,
+ locationCity.district!, locationCity.city!);
}
}
}
Future getCurrentLocation() async {
+ bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
+
if (!(await isOnline.value)) {
showSnackBar(content: 'no_inter'.tr);
await readCache();
return;
}
- if (!await Geolocator.isLocationServiceEnabled()) {
+ if (!serviceEnabled) {
showSnackBar(
content: 'no_location'.tr,
onPressed: () => Geolocator.openLocationSettings(),
@@ -107,73 +107,70 @@ class WeatherController extends GetxController {
return;
}
- if (isar.mainWeatherCaches.where().findAllSync().isNotEmpty) {
+ if ((isar.mainWeatherCaches.where().findAllSync()).isNotEmpty) {
await readCache();
return;
}
- final position = await _determinePosition();
- final placemarks = await placemarkFromCoordinates(
- position.latitude,
- position.longitude,
- );
- final place = placemarks[0];
+ Position position = await determinePosition();
+ List placemarks =
+ await placemarkFromCoordinates(position.latitude, position.longitude);
+ Placemark place = placemarks[0];
_latitude.value = position.latitude;
_longitude.value = position.longitude;
- _district.value = place.administrativeArea ?? '';
- _city.value = place.locality ?? '';
+ _district.value = '${place.administrativeArea}';
+ _city.value = '${place.locality}';
- _mainWeather.value = await WeatherAPI().getWeatherData(
- _latitude.value,
- _longitude.value,
- );
+ _mainWeather.value =
+ await WeatherAPI().getWeatherData(_latitude.value, _longitude.value);
notificationCheck();
+
await writeCache();
await readCache();
}
- Future