From 06c76cfd12b1f3d6dcc44afd465ebcdca9e2fc85 Mon Sep 17 00:00:00 2001 From: Pranshul Date: Wed, 6 Aug 2025 12:29:39 +0530 Subject: [PATCH] adding first working widget --- android/app/build.gradle.kts | 3 +- android/app/src/main/AndroidManifest.xml | 28 +++ .../weather_master_app/WeatherIconMapper.kt | 96 +++++++++ .../WeatherWidgetProvider.kt | 40 ++++ .../main/res/drawable/rounded_widget_bg.xml | 4 + .../src/main/res/layout/weather_widget.xml | 68 ++++++ .../src/main/res/values-night-v31/colors.xml | 35 +++ .../app/src/main/res/values-night/colors.xml | 29 +++ .../app/src/main/res/values-v31/colors.xml | 37 ++++ android/app/src/main/res/values/colors.xml | 35 +++ android/app/src/main/res/values/styles.xml | 30 +++ .../src/main/res/xml/weather_widget_info.xml | 8 + lib/main.dart | 23 ++ lib/screens/home.dart | 29 +-- lib/services/fetch_data.dart | 20 -- lib/widget_background.dart | 76 +++++++ lib/widgets/alert_block.dart | 203 ------------------ pubspec.lock | 16 +- pubspec.yaml | 4 +- .../.gradle/8.9/fileHashes/fileHashes.bin | Bin 28497 -> 28497 bytes .../.gradle/8.9/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../8.9/fileHashes/resourceHashesCache.bin | Bin 20435 -> 20503 bytes .../cxx/create_cxx_tasks_236_timing.txt | 8 + .../cxx/create_cxx_tasks_39_timing.txt | 11 + 24 files changed, 557 insertions(+), 246 deletions(-) create mode 100644 android/app/src/main/kotlin/com/pranshulgg/weather_master_app/WeatherIconMapper.kt create mode 100644 android/app/src/main/kotlin/com/pranshulgg/weather_master_app/WeatherWidgetProvider.kt create mode 100644 android/app/src/main/res/drawable/rounded_widget_bg.xml create mode 100644 android/app/src/main/res/layout/weather_widget.xml create mode 100644 android/app/src/main/res/values-night-v31/colors.xml create mode 100644 android/app/src/main/res/values-night/colors.xml create mode 100644 android/app/src/main/res/values-v31/colors.xml create mode 100644 android/app/src/main/res/values/colors.xml create mode 100644 android/app/src/main/res/xml/weather_widget_info.xml create mode 100644 lib/widget_background.dart delete mode 100644 lib/widgets/alert_block.dart create mode 100644 settings_tiles_custom/example/build/app/intermediates/cxx/create_cxx_tasks_236_timing.txt diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index c07788517..dd18bb154 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -72,5 +72,6 @@ flutter { dependencies { coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4") implementation("androidx.work:work-runtime-ktx:2.9.0") - + implementation("androidx.glance:glance-appwidget:1.0.0-alpha05") + implementation("com.google.android.material:material:1.12.0") } \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 615611a23..03ec09431 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -40,6 +40,34 @@ android:name="flutterEmbedding" android:value="2" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/values-night-v31/colors.xml b/android/app/src/main/res/values-night-v31/colors.xml new file mode 100644 index 000000000..070744bb6 --- /dev/null +++ b/android/app/src/main/res/values-night-v31/colors.xml @@ -0,0 +1,35 @@ + + + + @android:color/system_accent1_100 + @android:color/system_accent1_900 + @android:color/system_accent1_700 + @android:color/system_accent1_100 + + + @android:color/system_accent2_300 + @android:color/system_accent2_900 + @android:color/system_accent2_700 + @android:color/system_accent2_100 + + + @android:color/system_accent3_300 + @android:color/system_accent3_900 + @android:color/system_accent3_700 + @android:color/system_accent3_100 + + + @android:color/system_neutral1_900 + @android:color/system_neutral1_100 + @android:color/system_neutral1_700 + @android:color/system_neutral1_100 + + + @android:color/system_accent2_800 + @color/black + @color/material_dynamic_neutral40 + + + @android:color/system_neutral2_700 + @android:color/system_neutral2_100 + diff --git a/android/app/src/main/res/values-night/colors.xml b/android/app/src/main/res/values-night/colors.xml new file mode 100644 index 000000000..3bd7ed6fa --- /dev/null +++ b/android/app/src/main/res/values-night/colors.xml @@ -0,0 +1,29 @@ + + #aac7ff + #0a305f + #284777 + #d6e3ff + + #bec6dc + #283141 + #3e4759 + #dae2f9 + + #ddbce0 + #3f2844 + #573e5c + #fad8fd + + #111318 + #e2e2e9 + #111318 + #e2e2e9 + + #1d2024 + + #111318 + #c4c6d0 + + #ffb4ab + #690005 + \ No newline at end of file diff --git a/android/app/src/main/res/values-v31/colors.xml b/android/app/src/main/res/values-v31/colors.xml new file mode 100644 index 000000000..6f9937f79 --- /dev/null +++ b/android/app/src/main/res/values-v31/colors.xml @@ -0,0 +1,37 @@ + + + + @android:color/system_accent1_600 + @android:color/system_accent1_0 + @android:color/system_accent1_100 + @android:color/system_accent1_900 + + + @android:color/system_accent2_600 + @android:color/system_accent2_0 + @android:color/system_accent2_100 + @android:color/system_accent2_900 + + + @android:color/system_accent3_600 + @android:color/system_accent3_0 + @android:color/system_accent3_100 + @android:color/system_accent3_900 + + + @android:color/system_neutral1_100 + @android:color/system_neutral1_900 + @android:color/system_neutral1_500 + @android:color/system_neutral1_100 + + + @android:color/system_accent2_50 + @color/white + @color/material_dynamic_neutral90 + + + @android:color/system_neutral2_500 + @android:color/system_neutral1_500 + + + diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml new file mode 100644 index 000000000..6e696a57a --- /dev/null +++ b/android/app/src/main/res/values/colors.xml @@ -0,0 +1,35 @@ + + + #FF000000 + #FFFFFFFF + + + + #415f91 + #ffffff + #d6e3ff + #001b3e + + #565f71 + #ffffff + #dae2f9 + #131c2b + + #705575 + #ffffff + #fad8fd + #28132e + + #f9f9ff + #191c20 + #f9f9ff + #191c20 + + #ededf4 + + #d9d9e0 + #44474e + + #ba1a1a + #ffffff + \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index cb1ef8805..a3991de8e 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -11,8 +11,38 @@ Flutter UI initializes, as well as behind your Flutter UI while its running. + This Theme is only used starting with V2 of Flutter's Android embedding. --> + + + + + diff --git a/android/app/src/main/res/xml/weather_widget_info.xml b/android/app/src/main/res/xml/weather_widget_info.xml new file mode 100644 index 000000000..af1491495 --- /dev/null +++ b/android/app/src/main/res/xml/weather_widget_info.xml @@ -0,0 +1,8 @@ + + diff --git a/lib/main.dart b/lib/main.dart index 71371ccf8..b379ed411 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -22,6 +22,8 @@ import '../services/data_backup_service.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'dart:ui' as ui; import 'package:workmanager/workmanager.dart'; +import 'widget_background.dart'; +import 'package:home_widget/home_widget.dart'; final CorePalette paletteStartScreen = CorePalette.of(const Color.fromARGB(255, 255, 196, 0).toARGB32()); @@ -69,6 +71,7 @@ final flutterSupportedLocales = easySupportedLocales .toList(); + void main() async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); @@ -88,6 +91,26 @@ void main() async { final dir = await getApplicationDocumentsDirectory(); Hive.init(dir.path); + // widget------ + + Workmanager().initialize( + callbackDispatcherBG, + ); + + Workmanager().registerPeriodicTask( + "weatherAutoUpdateTask", + "weatherUpdate", + frequency: Duration(minutes: 15), + constraints: Constraints( + networkType: NetworkType.connected, + ), + ); + + + + // widget ------ + + final themeController = ThemeController(); await themeController.initialize(); await themeController.checkDynamicColorSupport(); diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 2b38438fa..627a5d68c 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -60,7 +60,11 @@ import '../widgets/pollen_card.dart'; import '../widgets/rain_block.dart'; import '../widgets/top_summary_block.dart'; import '../widgets/top_weather_card.dart'; -import '../widgets/alert_block.dart'; + + +// home widget +import '../widget_background.dart'; +import 'package:workmanager/workmanager.dart'; class WeatherHome extends StatefulWidget { @@ -270,7 +274,7 @@ Future saveLayoutConfig() async { } else if (isHomeLocation && lastUpdated != null) { final lastUpdateTime = DateTime.tryParse(lastUpdated); final now = DateTime.now(); - if (lastUpdateTime != null && now.difference(lastUpdateTime).inMinutes < 450) { + if (lastUpdateTime != null && now.difference(lastUpdateTime).inMinutes < 4500) { _isAppFullyLoaded = true; } else{ checkAndUpdateHomeLocation(); @@ -811,6 +815,9 @@ Widget _buildWeatherContent() { } + + + final raw = snapshot.data!; final weather = raw['data']; final current = weather['current']; @@ -881,7 +888,7 @@ void maybeUpdateWeatherAnimation(Map current) { final useFullMaterialScheme = PreferencesHelper.getBool("OnlyMaterialScheme") ?? false; - +// updateHomeWidget(); String formattedTime = lastUpdated != null @@ -969,6 +976,10 @@ for (int i = 0; i < allTimeStrings.length; i++) { } } +// updateHomeWidget(); + + + final List next2hPrecip = []; for (int i = 0; i < timeNext12h.length; i++) { @@ -1009,10 +1020,6 @@ if (rainStart != null) { final bool shouldShowRainBlock = bestStart != null && bestEnd != null; -final List alerts = (weather['alerts']?['alert'] as List?) ?? []; // Get alerts list or empty list if null -final bool showAlerts = alerts.isNotEmpty; // True if there are any alerts - - Widget buildLayoutBlock(LayoutBlockType type) { switch (type) { @@ -1145,6 +1152,7 @@ else GestureDetector( onTap: () async { +await Workmanager().cancelAll(); final result = await Navigator.of(context).push>( @@ -1318,12 +1326,7 @@ else ), WeatherFrogIconWidget(iconUrl: _iconUrlFroggy), const SizedBox(height: 12), - - if(showAlerts && showAlertsPref) - alertCard( weather['alerts']!, context), - - shouldShowRainBlock ? SizedBox(height: 8.5,) : showInsightsRandomly ? SizedBox(height: 8.5,) : SizedBox.shrink(), - + Column( children: () { diff --git a/lib/services/fetch_data.dart b/lib/services/fetch_data.dart index ff83acf77..61aee8698 100644 --- a/lib/services/fetch_data.dart +++ b/lib/services/fetch_data.dart @@ -46,26 +46,12 @@ class WeatherService { }); - - - bool showAlerts = PreferencesHelper.getBool("showAlerts") ?? true; - // Prepare list of HTTP requests (always include weather and air quality) final requests = >[ http.get(uri), http.get(airQualityUri), ]; - // Conditionally add alerts request only if user wants them - if (showAlerts && !isBackground) { - final alertUri = Uri.parse('https://api.weatherapi.com/v1/alerts.json').replace(queryParameters: { - 'key': dotenv.env['API_KEY_WEATHERAPI']!.toString(), - 'q': '$lat,$lon', - }); - requests.add(http.get(alertUri)); - } - - // Execute all HTTP requests in parallel final responses = await Future.wait(requests); @@ -73,10 +59,6 @@ class WeatherService { final weatherData = json.decode(responses[0].body) as Map; final airQualityData = json.decode(responses[1].body) as Map; - // Conditionally decode alert data if it was fetched - final alertData = showAlerts && responses.length > 2 - ? json.decode(responses[2].body) as Map - : {}; // Check if we need fallback data for missing fields Map finalWeatherData = weatherData; @@ -117,7 +99,6 @@ class WeatherService { final combinedDataForView = { ...finalWeatherData, 'air_quality': airQualityData, - 'alerts': alertData['alerts'] ?? [], }; final nowForView = DateTime.now().toIso8601String(); @@ -155,7 +136,6 @@ class WeatherService { final combinedData = { ...finalWeatherData, 'air_quality': airQualityData, - 'alerts': alertData['alerts'] ?? [], }; final wrappedData = { diff --git a/lib/widget_background.dart b/lib/widget_background.dart new file mode 100644 index 000000000..e85564ced --- /dev/null +++ b/lib/widget_background.dart @@ -0,0 +1,76 @@ +import 'services/fetch_data.dart'; +import 'utils/preferences_helper.dart'; +import 'package:flutter/material.dart'; +import 'package:home_widget/home_widget.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:hive/hive.dart'; +import 'package:workmanager/workmanager.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +@pragma('vm:entry-point') +Future updateHomeWidget() async { + try { + print('[WidgetUpdate] Starting updateHomeWidget'); + + await HomeWidget.setAppGroupId('com.pranshulgg.weather_master_app'); + print('[WidgetUpdate] Set AppGroupId'); + + + final weatherService = WeatherService(); + final homeLocation = PreferencesHelper.getJson('homeLocation'); + + final result = await weatherService.fetchWeather( + homeLocation?['lat']!, + homeLocation?['lon']!, + locationName: homeLocation?['cacheKey'], + context: null, + isBackground: true + ); + + final current = result!['data']['current']; + final temp = current['temperature_2m'].toInt(); + final code = current['weather_code']; + final daily = result!['data']['daily']; + final maxTemp = daily['temperature_2m_max'][0]; + final minTemp = daily['temperature_2m_min'][0]; + final isDay = current['is_day']; + + + // final temp = 200; + // final code = 80; + // final maxTemp = 33; + // final minTemp = 40; + // final isDay = 0; + + await HomeWidget.saveWidgetData('temperatureCurrentPill', temp.round().toString()); + await HomeWidget.saveWidgetData('weather_codeCurrentPill', code.toString()); + await HomeWidget.saveWidgetData('todayMax', maxTemp.round().toString()); + await HomeWidget.saveWidgetData('todayMin', minTemp.round().toString()); + + await HomeWidget.saveWidgetData('isDayWidget', isDay.toString()); + + await HomeWidget.updateWidget(name: 'WeatherWidgetProvider', iOSName: null); + print('[WidgetUpdate] Called updateWidget'); + } catch (e, stack) { + print('[WidgetUpdate][ERROR] $e'); + print(stack); + } +} + +@pragma('vm:entry-point') +void callbackDispatcherBG() { + Workmanager().executeTask((task, inputData) async { + WidgetsFlutterBinding.ensureInitialized(); + + final dir = await getApplicationDocumentsDirectory(); + Hive.init(dir.path); + + + await PreferencesHelper.init(); + await updateHomeWidget(); + + + return Future.value(true); + }); +} + diff --git a/lib/widgets/alert_block.dart b/lib/widgets/alert_block.dart deleted file mode 100644 index 81c08c7a1..000000000 --- a/lib/widgets/alert_block.dart +++ /dev/null @@ -1,203 +0,0 @@ -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -Widget alertCard(Map data, BuildContext context) { - List alerts = data['alert'] ?? []; - - if (alerts.isEmpty) { - return const Text("No alerts available."); - } - - final alert = alerts.first; - - return GestureDetector( - - - child: Container( - padding: const EdgeInsets.all(12), - margin: const EdgeInsets.fromLTRB(12, 0, 12, 0), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.errorContainer, - borderRadius: BorderRadius.circular(18), - ), - constraints: BoxConstraints( - minHeight: 65 - ), - child: IntrinsicHeight( - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - width: 46, - height: 46, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.error, - borderRadius: BorderRadius.circular(50), - - ), - child: Center( - child: Icon( - Icons.warning_amber, - color: Theme.of(context).colorScheme.onError, - ), - ), - ), - const SizedBox(width: 10), - Expanded( - child: Text( - alert['headline'] ?? 'No headline', - style: TextStyle( - fontSize: 14.5, - color: Theme.of(context).colorScheme.onErrorContainer, - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ), - Icon( - Icons.chevron_right_rounded, - color: Theme.of(context).colorScheme.onSurface, - ), - ], - ), - ), - ), - onTap: () { - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => AlertsPage(data: data,)), - ); - }, - ); -} - -class AlertsPage extends StatelessWidget { - final Map data; - - const AlertsPage({super.key, required this.data}); - - @override - Widget build(BuildContext context) { - List alerts = data['alert'] ?? []; - - return Scaffold( - body: CustomScrollView( - slivers: [ - SliverAppBar.large( - titleSpacing: 0, - automaticallyImplyLeading: false, - flexibleSpace: FlexibleSpaceBar( - title: Text("weather_alerts".tr()), - expandedTitleScale: 1.3, - titlePadding: EdgeInsets.all(16), - ), - backgroundColor: Theme.of(context).colorScheme.surface, - expandedHeight: 100, - scrolledUnderElevation: 1, - actions: [ - IconButton(onPressed: () {Navigator.pop(context);}, icon: Icon(Icons.close, weight: 600,)), - SizedBox(width: 5) - ], - ), - - SliverToBoxAdapter( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Opacity( - opacity: 0.7, - child: Padding(padding: EdgeInsets.only(bottom: 10, left: 16, right: 16), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: EdgeInsets.only(top: 2), - child: Icon(Icons.info_outline, color: Theme.of(context).colorScheme.onSurfaceVariant, size: 17,), - ), - SizedBox(width: 5,), - Expanded( - child: Text( - "Due to the API being in beta, alerts from other regions may occasionally appear", - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ), - ], - ), - ), - ), - if (alerts.isNotEmpty) - ...alerts.map((alert) { - return Container( - margin: const EdgeInsets.symmetric(vertical: 6.0, horizontal: 12), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerLow, - borderRadius: BorderRadius.circular(18), - ), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - alert['headline'] ?? 'No headline', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.error, - ), - ), - Divider(), - const SizedBox(height: 8), - Text( - alert['desc']?.replaceAll('\n', '\n') ?? '', - style: const TextStyle(fontSize: 14), - ), - const SizedBox(height: 8), - Text( - alert['instruction']?.replaceAll('\n', '\n') ?? '', - style: const TextStyle( - fontSize: 14, - fontStyle: FontStyle.italic, - ), - ), - const SizedBox(height: 8), - Divider(), - Text( - 'Effective: ${formatDate(alert['effective'])}', - style: TextStyle(fontSize: 15, color: Theme.of(context).colorScheme.primary), - ), - Text( - 'Expires: ${formatDate(alert['expires'])}', - style: TextStyle(fontSize: 15, color: Theme.of(context).colorScheme.primary), - ), - ], - ), - ), - ); - }).toList(), - - SizedBox(height: MediaQuery.of(context).padding.bottom + 10,) - ], - ), - ), - ] - ) - ); - - - - - } -} - -DateFormat dateFormat = DateFormat('EEEE, MMM d • h:mm a'); - -String formatDate(String dateStr) { - try { - DateTime dt = DateTime.parse(dateStr).toLocal(); - return dateFormat.format(dt); - } catch (_) { - return dateStr; - } -} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 069a9ddd9..c4964ca40 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,14 +1,6 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - android_intent_plus: - dependency: "direct main" - description: - name: android_intent_plus - sha256: dfc1fd3a577205ae8f11e990fb4ece8c90cceabbee56fcf48e463ecf0bd6aae3 - url: "https://pub.dev" - source: hosted - version: "5.3.0" animations: dependency: "direct main" description: @@ -438,6 +430,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + home_widget: + dependency: "direct main" + description: + name: home_widget + sha256: ad9634ef5894f3bac73f04d59e2e5151a39798f49985399fd928dadc828d974a + url: "https://pub.dev" + source: hosted + version: "0.8.0" http: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 79a20e3e6..53fa18c9f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,7 +64,9 @@ dependencies: file_picker: ^10.2.0 flutter_dotenv: ^5.2.1 workmanager: ^0.9.0 - android_intent_plus: ^5.3.0 + home_widget: ^0.8.0 + + settings_tiles: path: ./settings_tiles_custom diff --git a/settings_tiles_custom/example/android/.gradle/8.9/fileHashes/fileHashes.bin b/settings_tiles_custom/example/android/.gradle/8.9/fileHashes/fileHashes.bin index 2fb8ab62d1184ae023d7e57b6e5590fc78e95b1d..83df6455c5209957a99345fc66c4921a190b063f 100644 GIT binary patch delta 1929 zcmYk5Urd#C9L71DH49EPvZgVy47llWW`0WZRp z7Jin*7nmsK!#c2}gzzQSD(n$BjflW0j4LF+#_-qh3!Fi{Ko{BtPGdwf{|TH#ekpgI zM2$cMhXjseSXbr*zCz9>hC2}yIDuAOiEZM{CuE`r`ViZ0;h{3ijM*cL$#3Ism4z3} zco4m)C}UeU4hZz3U*H?W6`XQrzD23PSvch$bd)FV(C_X>R94SmO5ix$o4Mf}HV8zq zU!h0fJZ>vkuQU7u3Ir}96ftzh_jtW$VXpbwo2*9H2qcnibFutuOC4FWNA z2n=FW;1XN`hJV7d3bg^A=8tl4OWwo!Ef&5D@Zc`vs>FtHU*HOI-(bTKss)B|P~cZw z7PyL8fnV@cCBy9q2pq*n0s|NjxQ!Wtvl>}dChRvDXHa!?X_(o{}pWd>u}TlvIUR&Ew?kKzLg$HQ2BCud9yyVcx^Jv09~ z=OPleV291E*!Q%08TYh=xhIuveIioudzkZj8Ohkjh=@W8`#!?k7)jAOo7qXV%{ivk z@U`dI{St*EPkl?oqug^!VzU_Jjo5QqDfZg!Y?)!p9uaYh2!-Qj%lJZ(T+2Pv@YeE* z;#%oOi>yquVMKCM`q5|R&xt*Xv^v@&>>lC9wN+1J=|K*S%2?BqG8vu^%|AEt2X`F5l5*Yok?`gUSRX*)JXXgezw zOzb?Z6Z>>xA3J+?@#U9eSpG#Tv{USY2HH=sYOjdLDY``DYF!@dQX83fu)L8|WNV$+ zono&Gk-z{t1x})0!-7B%&eFnFadR+Xn1zDIZ`dmfUGQU?*YygZ6jupxVNV z6+DOtsw$W^iX#FM3<->5Szrt~mGoRdxrUrdH;z`u@6eSzhLDVoVo~5UvUhR9MHCDC zghLvF0+YBcFahgznt#R)fhamO^a)I1PGA!0RWx703mV=OxQt^0moOu66~=Cw2eDNk zh8BVAI4UrMDS>OSd1;=(a{|+7@bWaT%E6_*hwZy940w5PH*iU8v-np-!5d8Y1+@Zm z=n=SyF%5s~(#AbBpMqDzhXOI26gU!u^JcL^a&tiM68_{ZY6XrVH z7hf(O1QN=PK2%J=e6%FT69`W*YEuopeR!otjT-$rO3D|cd^s^HqN5BQ zrNE7kYSrgujLY$*bT-PM(z@EhvG1W>7Z?SKYL6=v`*cMv9R)- z3()Jgu+Fb;#ki}Z(>SNg&*;ZY8x-*fSN!ZZotCV6#)>GSFqYu2XY-GATn4=hQoheP zXMov@6faSjt7vOa6kmz$9?tPbjNf&nc(?6k$~;pJinvM9OJP3A$e0K@33~(Q%)-;a zUEb1>4s^-L4JJ&8@0xxzrhYVX?ty)biJ@~JW3KBMS@NNjN8oH^d6=2LMm5Py;jX$9 zMVP`kgIVogd4qO(t9X6JI8%;@2%~qu$~MKaa>J?g=QMG5@&C~#Es#4{ zQ^&1g`IwZmF(l<|EDLy8-rC059+bCnwhQmK6*}5osZ)H|Hsty;F{MrM@5xo?7@6FX zU)+PM diff --git a/settings_tiles_custom/example/android/.gradle/8.9/fileHashes/fileHashes.lock b/settings_tiles_custom/example/android/.gradle/8.9/fileHashes/fileHashes.lock index 22a01c128971e32427b90465e604d679cce7e62f..b65bc4c55398f1712ac99c8f4a3dc58b7e86ac4a 100644 GIT binary patch literal 17 VcmZRMz56`-dT#I<1~8EQ002Hu1>gVx literal 17 VcmZRMz56`-dT#I<1~8Cm0suYV1#tiX diff --git a/settings_tiles_custom/example/android/.gradle/8.9/fileHashes/resourceHashesCache.bin b/settings_tiles_custom/example/android/.gradle/8.9/fileHashes/resourceHashesCache.bin index 8e6e878538108f27f66a415b4775df244412c274..ecb563e85ce9d3aeed5a643e52e7d39f44a02db0 100644 GIT binary patch delta 77 zcmcaSpK