diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cdd8ee3..6b95854 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: branches: [master] env: - FLUTTER_VERSION: '3.16.x' + FLUTTER_VERSION: '3.19.x' jobs: analyze: diff --git a/.gitignore b/.gitignore index 2f36ff0..fd23e4c 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,4 @@ app.*.map.json /android/app/release .vscode/settings.json +assets/apikey.json diff --git a/analysis_options.yaml b/analysis_options.yaml index 00d1c86..90633ee 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,30 +1,13 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. include: package:flutter_lints/flutter.yaml linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at - # https://dart-lang.github.io/linter/lints/index.html. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. rules: - avoid_print: false # Uncomment to disable the `avoid_print` rule - prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + avoid_print: true + cancel_subscriptions: true + prefer_single_quotes: true + prefer_const_constructors: true + prefer_const_declarations: true require_trailing_commas: true - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options + use_super_parameters: true + close_sinks: true + prefer_relative_imports: true \ No newline at end of file diff --git a/assets/apikey.json b/assets/apikey.json index 55a2d62..e370bb6 100644 --- a/assets/apikey.json +++ b/assets/apikey.json @@ -1,3 +1,3 @@ { - "apiKey": "YOUR_OPEN_WEATHER_API_KEY_HERE" + "apiKey": "" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 9c4101a..d8d1b26 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,25 +1,36 @@ import 'dart:convert'; -import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:provider/provider.dart'; -import 'package:pulse/app/weather_model.dart'; -import 'package:pulse/app/weather_page.dart'; +import 'package:geocoding_resolver/geocoding_resolver.dart'; +import 'package:open_weather_client/open_weather.dart'; +import 'package:watch_it/watch_it.dart'; import 'package:yaru/yaru.dart'; -import 'package:yaru_widgets/yaru_widgets.dart'; + +import 'src/app/app.dart'; +import 'src/weather/weather_model.dart'; Future main() async { await YaruWindowTitleBar.ensureInitialized(); - - WidgetsFlutterBinding.ensureInitialized(); - final apiKey = await loadApiKey(); - - if (apiKey != null) { + if (apiKey != null && apiKey.isNotEmpty) { + di.registerSingleton(OpenWeather(apiKey: apiKey)); + di.registerSingleton(GeoCoder()); + final weatherModel = + WeatherModel(openWeather: di(), geoCoder: di()); + await weatherModel.init(); + di.registerSingleton(weatherModel); + + runApp(const App()); + } else { runApp( - MyApp.create( - apiKey, + MaterialApp( + theme: yaruLight, + home: const Scaffold( + body: Center( + child: Text('NO VALI API KEY FOUND'), + ), + ), ), ); } @@ -30,41 +41,3 @@ Future loadApiKey() async { final json = jsonDecode(source); return json['apiKey'] as String; } - -class MyApp extends StatefulWidget { - const MyApp({super.key, required this.apiKey}); - - final String apiKey; - - static Widget create(String apiKey) { - return ChangeNotifierProvider( - create: (context) => WeatherModel(apiKey)..init(), - child: MyApp(apiKey: apiKey), - ); - } - - @override - State createState() => _MyAppState(); -} - -class _MyAppState extends State { - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Weather', - debugShowCheckedModeBanner: false, - theme: yaruLight, - darkTheme: yaruDark, - home: const WeatherPage(), - scrollBehavior: const MaterialScrollBehavior().copyWith( - dragDevices: { - PointerDeviceKind.mouse, - PointerDeviceKind.touch, - PointerDeviceKind.stylus, - PointerDeviceKind.unknown, - PointerDeviceKind.trackpad, - }, - ), - ); - } -} diff --git a/lib/src/app/app.dart b/lib/src/app/app.dart new file mode 100644 index 0000000..c91bb1f --- /dev/null +++ b/lib/src/app/app.dart @@ -0,0 +1,30 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:yaru/yaru.dart'; + +import '../../weather.dart'; + +class App extends StatelessWidget { + const App({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Weather', + debugShowCheckedModeBanner: false, + theme: yaruLight, + darkTheme: yaruDark, + home: const WeatherPage(), + scrollBehavior: const MaterialScrollBehavior().copyWith( + dragDevices: { + PointerDeviceKind.mouse, + PointerDeviceKind.touch, + PointerDeviceKind.stylus, + PointerDeviceKind.unknown, + PointerDeviceKind.trackpad, + }, + ), + ); + } +} diff --git a/lib/app/utils.dart b/lib/src/weather/utils.dart similarity index 97% rename from lib/app/utils.dart rename to lib/src/weather/utils.dart index c548170..81f4667 100644 --- a/lib/app/utils.dart +++ b/lib/src/weather/utils.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_weather_bg_null_safety/utils/weather_type.dart'; import 'package:open_weather_client/models/weather_data.dart'; -import 'package:pulse/weather_data_x.dart'; -import 'package:yaru_icons/yaru_icons.dart'; +import 'weather_data_x.dart'; +import 'package:yaru/icons.dart'; Color getColor(WeatherData weatherData) { final hour = DateTime.fromMillisecondsSinceEpoch( diff --git a/lib/app/city_search_field.dart b/lib/src/weather/view/city_search_field.dart similarity index 89% rename from lib/app/city_search_field.dart rename to lib/src/weather/view/city_search_field.dart index 90af7ca..a21a571 100644 --- a/lib/app/city_search_field.dart +++ b/lib/src/weather/view/city_search_field.dart @@ -1,7 +1,7 @@ -import 'package:pulse/app/weather_model.dart'; +import '../weather_model.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:yaru_icons/yaru_icons.dart'; +import 'package:watch_it/watch_it.dart'; +import 'package:yaru/icons.dart'; class CitySearchField extends StatefulWidget { const CitySearchField({ @@ -29,7 +29,7 @@ class _CitySearchFieldState extends State { @override Widget build(BuildContext context) { - final model = context.watch(); + final model = di(); var textField = TextField( onSubmitted: (value) => model.init(cityName: _controller.text), controller: _controller, diff --git a/lib/app/forecast_tile.dart b/lib/src/weather/view/forecast_tile.dart similarity index 97% rename from lib/app/forecast_tile.dart rename to lib/src/weather/view/forecast_tile.dart index 7f090ad..28fbbf9 100644 --- a/lib/app/forecast_tile.dart +++ b/lib/src/weather/view/forecast_tile.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_weather_bg_null_safety/bg/weather_bg.dart'; import 'package:flutter_weather_bg_null_safety/flutter_weather_bg.dart'; import 'package:open_weather_client/models/weather_data.dart'; -import 'package:pulse/app/utils.dart'; -import 'package:pulse/string_x.dart'; -import 'package:pulse/weather_data_x.dart'; +import '../utils.dart'; +import '../../../string_x.dart'; +import '../weather_data_x.dart'; class ForecastTile extends StatefulWidget { final List data; diff --git a/lib/app/today_tile.dart b/lib/src/weather/view/today_tile.dart similarity index 96% rename from lib/app/today_tile.dart rename to lib/src/weather/view/today_tile.dart index b9ce0a4..4b8ba59 100644 --- a/lib/app/today_tile.dart +++ b/lib/src/weather/view/today_tile.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_weather_bg_null_safety/bg/weather_bg.dart'; import 'package:flutter_weather_bg_null_safety/flutter_weather_bg.dart'; import 'package:open_weather_client/models/weather_data.dart'; -import 'package:pulse/app/utils.dart'; -import 'package:pulse/string_x.dart'; -import 'package:pulse/weather_data_x.dart'; +import '../utils.dart'; +import '../../../string_x.dart'; +import '../weather_data_x.dart'; class TodayTile extends StatelessWidget { final WeatherData data; diff --git a/lib/weather_data_x.dart b/lib/src/weather/weather_data_x.dart similarity index 97% rename from lib/weather_data_x.dart rename to lib/src/weather/weather_data_x.dart index 7711544..56822ec 100644 --- a/lib/weather_data_x.dart +++ b/lib/src/weather/weather_data_x.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:open_weather_client/models/weather_data.dart'; -import 'package:pulse/weekday.dart'; +import 'weekday.dart'; extension WeatherDataX on WeatherData { String get currentTemperature => '${temperature.currentTemperature} °C'; diff --git a/lib/app/weather_model.dart b/lib/src/weather/weather_model.dart similarity index 95% rename from lib/app/weather_model.dart rename to lib/src/weather/weather_model.dart index 6b8fb28..34f0972 100644 --- a/lib/app/weather_model.dart +++ b/lib/src/weather/weather_model.dart @@ -1,17 +1,17 @@ import 'package:geocoding_resolver/geocoding_resolver.dart'; import 'package:geolocator/geolocator.dart'; import 'package:open_weather_client/open_weather.dart'; -import 'package:pulse/weather_data_x.dart'; -import 'package:pulse/weekday.dart'; import 'package:safe_change_notifier/safe_change_notifier.dart'; -class WeatherModel extends SafeChangeNotifier { - WeatherModel(String apiKey) - : _openWeather = OpenWeather(apiKey: apiKey), - geoCoder = GeoCoder(); +import 'weather_data_x.dart'; +import 'weekday.dart'; - GeoCoder geoCoder; +class WeatherModel extends SafeChangeNotifier { + WeatherModel({required OpenWeather openWeather, required GeoCoder geoCoder}) + : _openWeather = openWeather, + _geoCoder = geoCoder; + final GeoCoder _geoCoder; final OpenWeather _openWeather; final GeolocatorPlatform _geolocatorPlatform = GeolocatorPlatform.instance; @@ -26,7 +26,7 @@ class WeatherModel extends SafeChangeNotifier { return ''; } - Address address = await geoCoder.getAddressFromLatLng( + Address address = await _geoCoder.getAddressFromLatLng( latitude: _position!.latitude, longitude: _position!.longitude, ); diff --git a/lib/app/weather_page.dart b/lib/src/weather/weather_page.dart similarity index 93% rename from lib/app/weather_page.dart rename to lib/src/weather/weather_page.dart index b5262a9..1ac98df 100644 --- a/lib/app/weather_page.dart +++ b/lib/src/weather/weather_page.dart @@ -1,20 +1,20 @@ import 'package:flutter/material.dart'; import 'package:open_weather_client/models/weather_data.dart'; -import 'package:provider/provider.dart'; -import 'package:pulse/app/city_search_field.dart'; -import 'package:pulse/app/forecast_tile.dart'; -import 'package:pulse/app/today_tile.dart'; -import 'package:pulse/app/utils.dart'; -import 'package:pulse/app/weather_model.dart'; -import 'package:pulse/weather_data_x.dart'; -import 'package:yaru_widgets/yaru_widgets.dart'; +import 'view/city_search_field.dart'; +import 'view/forecast_tile.dart'; +import 'view/today_tile.dart'; +import 'utils.dart'; +import 'weather_model.dart'; +import 'weather_data_x.dart'; +import 'package:watch_it/watch_it.dart'; +import 'package:yaru/widgets.dart'; -class WeatherPage extends StatelessWidget { +class WeatherPage extends StatelessWidget with WatchItMixin { const WeatherPage({super.key}); @override Widget build(BuildContext context) { - final model = context.watch(); + final model = watchIt(); final mq = MediaQuery.of(context); final theme = Theme.of(context); final light = theme.brightness == Brightness.light; diff --git a/lib/weekday.dart b/lib/src/weather/weekday.dart similarity index 100% rename from lib/weekday.dart rename to lib/src/weather/weekday.dart diff --git a/lib/weather.dart b/lib/weather.dart new file mode 100644 index 0000000..0f697d0 --- /dev/null +++ b/lib/weather.dart @@ -0,0 +1 @@ +export 'src/weather/weather_page.dart'; diff --git a/pubspec.lock b/pubspec.lock index c0d6fd6..9816c68 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,30 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + animated_vector: + dependency: transitive + description: + name: animated_vector + sha256: e15c6596549ca6e2e7491c11fbe168a1dead87475a828a4bc81cf104feca0432 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + animated_vector_annotations: + dependency: transitive + description: + name: animated_vector_annotations + sha256: baa6b4ed98407220f2c9634f7da3cfa5eedb46798e090466f441e666e2f7c8c0 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + archive: + dependency: transitive + description: + name: archive + sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" + url: "https://pub.dev" + source: hosted + version: "3.4.10" args: dependency: transitive description: @@ -49,6 +73,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" crypto: dependency: transitive description: @@ -121,6 +153,14 @@ packages: description: flutter source: sdk version: "0.0.0" + functional_listener: + dependency: transitive + description: + name: functional_listener + sha256: "026d1bd4f66367f11d9ec9f1f1ddb42b89e4484b356972c76d983266cf82f33f" + url: "https://pub.dev" + source: hosted + version: "2.3.1" geoclue: dependency: transitive description: @@ -193,6 +233,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.2" + get_it: + dependency: transitive + description: + name: get_it + sha256: d85128a5dae4ea777324730dc65edd9c9f43155c109d5cc0a69cab74139fbac1 + url: "https://pub.dev" + source: hosted + version: "7.7.0" gsettings: dependency: transitive description: @@ -213,10 +261,10 @@ packages: dependency: "direct main" description: name: handy_window - sha256: "458a9f7d4ae23816e8f33c76596f943a04e7eff13d864e0867f3b40f1647d63d" + sha256: "56b813e58a68b0ee2ab22051400b8b1f1b5cfe88b8cd32288623defb3926245a" url: "https://pub.dev" source: hosted - version: "0.3.1" + version: "0.4.0" http: dependency: transitive description: @@ -233,6 +281,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + image: + dependency: transitive + description: + name: image + sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e" + url: "https://pub.dev" + source: hosted + version: "4.1.7" intl: dependency: "direct main" description: @@ -241,6 +297,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.19.0" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" json_annotation: dependency: transitive description: @@ -249,6 +313,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: transitive description: @@ -261,34 +349,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" + version: "1.11.0" open_weather_client: dependency: "direct main" description: @@ -317,10 +397,18 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.0.1" petitparser: dependency: transitive description: @@ -345,14 +433,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - provider: - dependency: "direct main" + pointycastle: + dependency: transitive description: - name: provider - sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + name: pointycastle + sha256: "79fbafed02cfdbe85ef3fd06c7f4bc2cbcba0177e61b765264853d4253b21744" url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "3.9.0" safe_change_notifier: dependency: "direct main" description: @@ -470,6 +558,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" + watch_it: + dependency: "direct main" + description: + name: watch_it + sha256: "9dc3f552d31f6ae121b0de794ab3cdea5d93627fe69337876ebe4b41bfc3729d" + url: "https://pub.dev" + source: hosted + version: "1.4.1" web: dependency: transitive description: @@ -514,26 +618,10 @@ packages: dependency: "direct main" description: name: yaru - sha256: e9ccb22cb283ecf3f6b21d64dee9764d4abff65a44f48ce21aa13b9eae3e3be5 - url: "https://pub.dev" - source: hosted - version: "1.2.2" - yaru_icons: - dependency: "direct main" - description: - name: yaru_icons - sha256: "2dff89ee31c2dd888e1ce146f0faef1c8de4ffbc90cb6466aacd55c3a9ad0674" - url: "https://pub.dev" - source: hosted - version: "2.4.0" - yaru_widgets: - dependency: "direct main" - description: - name: yaru_widgets - sha256: "0bade922090f25eedcc88cdc15b8a6adbaba4e4b56d793e999224b22c95a19d2" + sha256: e868965bcfbca568f54916e3f59a636a8a6ee39f2e102df8844061cd78a8d20e url: "https://pub.dev" source: hosted - version: "3.6.0" + version: "4.1.0" yaru_window: dependency: transitive description: @@ -576,4 +664,4 @@ packages: version: "0.0.3" sdks: dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + flutter: ">=3.19.5" diff --git a/pubspec.yaml b/pubspec.yaml index 5b730d7..4af40ca 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ version: 1.0.0+1 environment: sdk: ">=3.0.0 <4.0.0" - flutter: ">=3.10.0" + flutter: ">=3.19.5" dependencies: collection: ^1.16.0 @@ -17,20 +17,18 @@ dependencies: geolocator: ^11.0.0 geolocator_apple: ^2.2.7 geolocator_linux: ^0.2.0+2 - handy_window: ^0.3.1 + handy_window: ^0.4.0 intl: ^0.19.0 open_weather_client: ^2.2.0 - provider: ^6.0.5 safe_change_notifier: ^0.3.0 - yaru: ^1.2.2 - yaru_icons: ^2.4.0 - yaru_widgets: ^3.6.0 + yaru: ^4.1.0 flutter_weather_bg_null_safety: git: url: https://github.com/Feichtmeier/flutter_weather_bg_null_safety ref: b9e3943904596809b957b44a3733b3794a43517b geocoding_resolver: ^0.0.3+2 + watch_it: ^1.4.1 dev_dependencies: flutter_lints: ^3.0.1