Rain/lib/main.dart

339 lines
12 KiB
Dart
Raw Normal View History

2023-07-09 12:56:16 +05:30
import 'dart:io';
2023-06-17 20:57:57 +03:00
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dynamic_color/dynamic_color.dart';
2023-10-03 19:23:52 +03:00
import 'package:flutter/foundation.dart';
2023-06-17 20:57:57 +03:00
import 'package:flutter/material.dart';
2023-09-01 20:18:40 +03:00
import 'package:flutter/services.dart';
2023-06-17 20:57:57 +03:00
import 'package:flutter_displaymode/flutter_displaymode.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_timezone/flutter_timezone.dart';
import 'package:get/get.dart';
2023-10-01 22:38:43 +03:00
import 'package:home_widget/home_widget.dart';
2024-04-10 21:25:23 +03:00
import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart';
2023-06-17 20:57:57 +03:00
import 'package:isar/isar.dart';
import 'package:path_provider/path_provider.dart';
2023-10-03 19:23:52 +03:00
import 'package:rain/app/controller/controller.dart';
2024-09-06 22:07:50 +03:00
import 'package:rain/app/data/db.dart';
import 'package:rain/app/ui/geolocation.dart';
import 'package:rain/app/ui/home.dart';
import 'package:rain/app/ui/onboarding.dart';
2023-06-17 20:57:57 +03:00
import 'package:rain/theme/theme.dart';
2024-08-03 18:55:26 +03:00
import 'package:rain/theme/theme_controller.dart';
import 'package:rain/translation/translation.dart';
2024-09-06 22:07:50 +03:00
import 'package:rain/app/utils/device_info.dart';
2023-10-12 12:11:20 +05:30
import 'package:timezone/data/latest_all.dart' as tz;
import 'package:timezone/timezone.dart' as tz;
2023-10-03 19:23:52 +03:00
import 'package:workmanager/workmanager.dart';
2023-06-17 20:57:57 +03:00
late Isar isar;
late Settings settings;
2024-02-11 22:00:37 +03:00
late LocationCache locationCache;
2025-03-02 15:58:04 +03:00
final ValueNotifier<Future<bool>> isOnline = ValueNotifier(
InternetConnection().hasInternetAccess,
);
2023-06-17 20:57:57 +03:00
2025-03-15 23:40:48 +03:00
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
2023-10-12 16:30:28 +03:00
FlutterLocalNotificationsPlugin();
2023-06-17 20:57:57 +03:00
2023-06-30 21:33:58 +03:00
bool amoledTheme = false;
bool materialColor = false;
2024-01-28 20:16:12 +03:00
bool roundDegree = false;
2024-07-10 21:59:36 +03:00
bool largeElement = false;
2023-07-02 21:53:03 +03:00
Locale locale = const Locale('en', 'US');
2023-07-09 23:41:51 +03:00
int timeRange = 1;
2023-07-26 22:20:30 +03:00
String timeStart = '09:00';
String timeEnd = '21:00';
2023-10-12 17:30:22 +03:00
String widgetBackgroundColor = '';
2023-10-12 20:48:23 +03:00
String widgetTextColor = '';
2023-06-29 21:25:00 +03:00
2023-10-01 22:38:43 +03:00
const String appGroupId = 'DARK NIGHT';
const String androidWidgetName = 'OreoWidget';
2025-03-15 23:40:48 +03:00
const List<Map<String, dynamic>> appLanguages = [
{'name': 'বাংলা', 'locale': Locale('bn', 'IN')},
{'name': 'Čeština', 'locale': Locale('cs', 'CZ')},
{'name': 'Dansk', 'locale': Locale('da', 'DK')},
{'name': 'Deutsch', 'locale': Locale('de', 'DE')},
{'name': 'English', 'locale': Locale('en', 'US')},
{'name': 'Español', 'locale': Locale('es', 'ES')},
{'name': 'Français', 'locale': Locale('fr', 'FR')},
// {'name': 'Gaeilge', 'locale': Locale('ga', 'IE')},
{'name': 'हिन्दी', 'locale': Locale('hi', 'IN')},
{'name': 'Magyar', 'locale': Locale('hu', 'HU')},
{'name': 'Italiano', 'locale': Locale('it', 'IT')},
{'name': '한국어', 'locale': Locale('ko', 'KR')},
{'name': 'فارسی', 'locale': Locale('fa', 'IR')},
{'name': 'ქართული', 'locale': Locale('ka', 'GE')},
{'name': 'Nederlands', 'locale': Locale('nl', 'NL')},
{'name': 'Polski', 'locale': Locale('pl', 'PL')},
{'name': 'Português (Brasil)', 'locale': Locale('pt', 'BR')},
{'name': 'Română', 'locale': Locale('ro', 'RO')},
{'name': 'Русский', 'locale': Locale('ru', 'RU')},
{'name': 'Slovenčina', 'locale': Locale('sk', 'SK')},
{'name': 'Türkçe', 'locale': Locale('tr', 'TR')},
{'name': 'اردو', 'locale': Locale('ur', 'PK')},
{'name': '中文(简体)', 'locale': Locale('zh', 'CN')},
{'name': '中文(繁體)', 'locale': Locale('zh', 'TW')},
];
2023-10-03 19:23:52 +03:00
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((task, inputData) {
return WeatherController().updateWidget();
});
}
2023-06-17 20:57:57 +03:00
void main() async {
WidgetsFlutterBinding.ensureInitialized();
2025-03-15 23:40:48 +03:00
await _initializeApp();
runApp(const MyApp());
}
Future<void> _initializeApp() async {
_setupConnectivityListener();
await _initializeTimeZone();
await _initializeIsar();
await _initializeNotifications();
2023-07-09 12:56:16 +05:30
if (Platform.isAndroid) {
2025-03-15 23:40:48 +03:00
await _setOptimalDisplayMode();
2023-10-09 11:25:06 +03:00
Workmanager().initialize(callbackDispatcher, isInDebugMode: kDebugMode);
2025-03-15 23:40:48 +03:00
HomeWidget.setAppGroupId(appGroupId);
2023-07-09 12:56:16 +05:30
}
2025-03-15 23:40:48 +03:00
DeviceFeature().init();
2023-06-17 20:57:57 +03:00
}
2025-03-15 23:40:48 +03:00
void _setupConnectivityListener() {
Connectivity().onConnectivityChanged.listen((result) {
isOnline.value =
result.contains(ConnectivityResult.none)
? Future.value(false)
: InternetConnection().hasInternetAccess;
});
}
Future<void> _initializeTimeZone() async {
final timeZoneName = await FlutterTimezone.getLocalTimezone();
tz.initializeTimeZones();
tz.setLocalLocation(tz.getLocation(timeZoneName));
2023-06-17 20:57:57 +03:00
}
2025-03-15 23:40:48 +03:00
Future<void> _initializeIsar() async {
2023-06-17 20:57:57 +03:00
isar = await Isar.open([
SettingsSchema,
MainWeatherCacheSchema,
LocationCacheSchema,
WeatherCardSchema,
], directory: (await getApplicationSupportDirectory()).path);
2023-09-18 16:26:08 +03:00
settings = isar.settings.where().findFirstSync() ?? Settings();
2024-02-11 22:00:37 +03:00
locationCache =
isar.locationCaches.where().findFirstSync() ?? LocationCache();
2023-09-28 22:23:36 +03:00
2023-07-04 21:22:29 +03:00
if (settings.language == null) {
settings.language = '${Get.deviceLocale}';
2023-09-18 16:26:08 +03:00
isar.writeTxnSync(() => isar.settings.putSync(settings));
2023-07-04 21:22:29 +03:00
}
2023-09-28 22:23:36 +03:00
if (settings.theme == null) {
settings.theme = 'system';
isar.writeTxnSync(() => isar.settings.putSync(settings));
}
2023-06-17 20:57:57 +03:00
}
2025-03-15 23:40:48 +03:00
Future<void> _initializeNotifications() async {
const initializationSettings = InitializationSettings(
android: AndroidInitializationSettings('@mipmap/ic_launcher'),
iOS: DarwinInitializationSettings(),
linux: LinuxInitializationSettings(defaultActionName: 'Rain'),
);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
Future<void> _setOptimalDisplayMode() async {
final supported = await FlutterDisplayMode.supported;
final active = await FlutterDisplayMode.active;
final sameResolution =
supported
.where((m) => m.width == active.width && m.height == active.height)
.toList()
..sort((a, b) => b.refreshRate.compareTo(a.refreshRate));
final mostOptimalMode =
sameResolution.isNotEmpty ? sameResolution.first : active;
await FlutterDisplayMode.setPreferredMode(mostOptimalMode);
}
2023-06-29 21:25:00 +03:00
class MyApp extends StatefulWidget {
2023-10-22 09:34:08 +03:00
const MyApp({super.key});
2023-06-29 21:25:00 +03:00
static Future<void> updateAppState(
BuildContext context, {
2023-06-30 21:33:58 +03:00
bool? newAmoledTheme,
bool? newMaterialColor,
2024-01-28 20:16:12 +03:00
bool? newRoundDegree,
2024-07-10 21:59:36 +03:00
bool? newLargeElement,
2023-07-02 21:53:03 +03:00
Locale? newLocale,
2023-07-09 23:41:51 +03:00
int? newTimeRange,
2023-07-26 22:20:30 +03:00
String? newTimeStart,
String? newTimeEnd,
2023-10-12 17:30:22 +03:00
String? newWidgetBackgroundColor,
2023-10-12 20:48:23 +03:00
String? newWidgetTextColor,
2023-06-29 21:25:00 +03:00
}) async {
final state = context.findAncestorStateOfType<_MyAppState>()!;
2025-03-15 23:40:48 +03:00
if (newAmoledTheme != null) state.changeAmoledTheme(newAmoledTheme);
if (newMaterialColor != null) state.changeMarerialTheme(newMaterialColor);
if (newRoundDegree != null) state.changeRoundDegree(newRoundDegree);
if (newLargeElement != null) state.changeLargeElement(newLargeElement);
if (newLocale != null) state.changeLocale(newLocale);
if (newTimeRange != null) state.changeTimeRange(newTimeRange);
if (newTimeStart != null) state.changeTimeStart(newTimeStart);
if (newTimeEnd != null) state.changeTimeEnd(newTimeEnd);
2023-10-12 17:30:22 +03:00
if (newWidgetBackgroundColor != null) {
state.changeWidgetBackgroundColor(newWidgetBackgroundColor);
}
2023-10-12 20:48:23 +03:00
if (newWidgetTextColor != null) {
state.changeWidgetTextColor(newWidgetTextColor);
}
2023-06-29 21:25:00 +03:00
}
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
2023-06-17 20:57:57 +03:00
final themeController = Get.put(ThemeController());
2025-03-15 23:40:48 +03:00
void changeAmoledTheme(bool newAmoledTheme) =>
setState(() => amoledTheme = newAmoledTheme);
void changeMarerialTheme(bool newMaterialColor) =>
setState(() => materialColor = newMaterialColor);
void changeRoundDegree(bool newRoundDegree) =>
setState(() => roundDegree = newRoundDegree);
void changeLargeElement(bool newLargeElement) =>
setState(() => largeElement = newLargeElement);
void changeTimeRange(int newTimeRange) =>
setState(() => timeRange = newTimeRange);
void changeTimeStart(String newTimeStart) =>
setState(() => timeStart = newTimeStart);
void changeTimeEnd(String newTimeEnd) => setState(() => timeEnd = newTimeEnd);
void changeLocale(Locale newLocale) => setState(() => locale = newLocale);
void changeWidgetBackgroundColor(String newWidgetBackgroundColor) =>
setState(() => widgetBackgroundColor = newWidgetBackgroundColor);
void changeWidgetTextColor(String newWidgetTextColor) =>
setState(() => widgetTextColor = newWidgetTextColor);
2023-10-12 20:48:23 +03:00
2023-06-29 21:25:00 +03:00
@override
void initState() {
2025-03-15 23:40:48 +03:00
super.initState();
2023-06-30 21:33:58 +03:00
amoledTheme = settings.amoledTheme;
materialColor = settings.materialColor;
2024-01-28 20:16:12 +03:00
roundDegree = settings.roundDegree;
2024-07-10 21:59:36 +03:00
largeElement = settings.largeElement;
2023-10-12 16:30:28 +03:00
locale = Locale(
2025-03-02 15:58:04 +03:00
settings.language!.substring(0, 2),
settings.language!.substring(3),
);
2023-07-09 23:41:51 +03:00
timeRange = settings.timeRange ?? 1;
2023-07-26 22:20:30 +03:00
timeStart = settings.timeStart ?? '09:00';
timeEnd = settings.timeEnd ?? '21:00';
2023-10-12 17:30:22 +03:00
widgetBackgroundColor = settings.widgetBackgroundColor ?? '';
2023-10-12 20:48:23 +03:00
widgetTextColor = settings.widgetTextColor ?? '';
2023-06-29 21:25:00 +03:00
}
2023-06-17 20:57:57 +03:00
@override
Widget build(BuildContext context) {
2024-07-09 23:03:40 +03:00
final edgeToEdgeAvailable = DeviceFeature().isEdgeToEdgeAvailable();
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
2024-07-07 14:49:45 +03:00
return GestureDetector(
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: DynamicColorBuilder(
builder: (lightColorScheme, darkColorScheme) {
2024-07-09 23:03:40 +03:00
final lightMaterialTheme = lightTheme(
2025-03-02 15:58:04 +03:00
lightColorScheme?.surface,
lightColorScheme,
edgeToEdgeAvailable,
);
2024-07-09 23:03:40 +03:00
final darkMaterialTheme = darkTheme(
2025-03-02 15:58:04 +03:00
darkColorScheme?.surface,
darkColorScheme,
edgeToEdgeAvailable,
);
final darkMaterialThemeOled = darkTheme(
oledColor,
darkColorScheme,
edgeToEdgeAvailable,
);
2023-07-19 18:59:53 +03:00
2024-07-07 14:49:45 +03:00
return GetMaterialApp(
themeMode: themeController.theme,
2025-03-02 15:58:04 +03:00
theme:
materialColor
? lightColorScheme != null
? lightMaterialTheme
: lightTheme(
lightColor,
colorSchemeLight,
edgeToEdgeAvailable,
)
2024-07-09 23:03:40 +03:00
: lightTheme(
2025-03-02 15:58:04 +03:00
lightColor,
colorSchemeLight,
edgeToEdgeAvailable,
),
darkTheme:
amoledTheme
? materialColor
? darkColorScheme != null
? darkMaterialThemeOled
: darkTheme(
oledColor,
colorSchemeDark,
edgeToEdgeAvailable,
)
2024-07-09 23:03:40 +03:00
: darkTheme(
2025-03-02 15:58:04 +03:00
oledColor,
colorSchemeDark,
edgeToEdgeAvailable,
)
: materialColor
2024-07-07 14:49:45 +03:00
? darkColorScheme != null
? darkMaterialTheme
2024-07-09 23:03:40 +03:00
: darkTheme(
2025-03-02 15:58:04 +03:00
darkColor,
colorSchemeDark,
edgeToEdgeAvailable,
)
2024-07-09 23:03:40 +03:00
: darkTheme(
2025-03-02 15:58:04 +03:00
darkColor,
colorSchemeDark,
edgeToEdgeAvailable,
),
2024-07-07 14:49:45 +03:00
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
translations: Translation(),
locale: locale,
fallbackLocale: const Locale('en', 'US'),
supportedLocales:
appLanguages.map((e) => e['locale'] as Locale).toList(),
debugShowCheckedModeBanner: false,
2025-03-02 15:58:04 +03:00
home:
settings.onboard
2025-03-15 23:40:48 +03:00
? (locationCache.city == null ||
locationCache.district == null ||
locationCache.lat == null ||
locationCache.lon == null)
2025-03-02 15:58:04 +03:00
? const SelectGeolocation(isStart: true)
: const HomePage()
: const OnBording(),
2024-07-07 14:49:45 +03:00
title: 'Rain',
);
},
),
2023-06-17 20:57:57 +03:00
);
}
}