diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c2867b..64429f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,19 @@ # CHANGE LOG +## 2.0.0 + +**BREAKING CHANGES** + +* Migration to null-safety ([#62](https://github.com/Norbert515/dynamic_theme/issues/62), [#60](https://github.com/Norbert515/dynamic_theme/issues/60), [#59](https://github.com/Norbert515/dynamic_theme/issues/59)) +* Now use the `ThemeMode` instead of `Brightness` ([#49](https://github.com/Norbert515/dynamic_theme/issues/49)). +* `ThemedWidgetBuilder themedWidgetBuilder` takes now the following parameters: `BuildContext, ThemeMode, ThemeData`. +* `data` parameter is now optional and has the type `ThemeDataWithThemeModeBuilder`. +* `defaultBrightness` became `defaultThemeMode` and use by default `ThemeMode.system`. +* `loadBrightnessOnStart` became `loadThemeOnStart`. +* import `package:dynamic_theme/dynamic_theme.dart` for both `DynamicTheme` and `BrightnessSwitcherDialog`. + ## 1.0.1 -- Update local_storage dependency to latest 0.5.0 -- Added and fixed linter rules -- Fixed default Dark mode problem from PRs +* Update local_storage dependency to latest 0.5.0 +* Added and fixed linter rules +* Fixed default Dark mode problem from PRs diff --git a/README.md b/README.md index 5756f2e..851dc06 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,94 @@ # dynamic_theme + ## Dynamically changing your theme without hassle ![](https://github.com/Norbert515/dynamic_theme/blob/master/assets/theme.png) This packages manages changing your theme during runtime and persiting that theme. -### I wrote a medium post about this, check it out [here](https://proandroiddev.com/how-to-dynamically-change-the-theme-in-flutter-698bd022d0f0)! - ## Include in your project + ``` dependencies: - dynamic_theme: ^1.0.1 + dynamic_theme: ^2.0.0 ``` + run packages get and import it + ``` import 'package:dynamic_theme/dynamic_theme.dart'; ``` -if you want the dialog: -``` -import 'package:dynamic_theme/theme_switcher_widgets.dart'; -``` ## Usage -Wrap your material app like this: + +### Light & Dark mode + +If all you want is to change the theme between light and dark you can just use the `themeMode` parameter and set the light theme with the `theme` property and dark theme with the `darkTheme` property. + ```dart +class MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return DynamicTheme( + themedWidgetBuilder: (_, themeMode, __) { + return MaterialApp( + title: 'Flutter Demo', + themeMode: themeMode, + theme: ThemeData.light(), + darkTheme: ThemeData.dark(), + home: MyHomePage(title: 'Flutter Demo Home Page'), + ); + } + ); + } +} +``` +### Custom theme + +If you want to apply some custom `ThemeData` you can use the `data` parameter to provide a custom `ThemeData` and rely on the `themeData` from the `themedWidgetBuilder` . + +```dart class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return new DynamicTheme( - defaultBrightness: Brightness.light, - data: (brightness) => new ThemeData( + return DynamicTheme( + data: (themeMode) => ThemeData( primarySwatch: Colors.indigo, - brightness: brightness, + brightness: themeMode == ThemeMode.dark ? Brightness.dark : Brightness.light, ), - themedWidgetBuilder: (context, theme) { - return new MaterialApp( + themedWidgetBuilder: (_, __, themeData) { + return MaterialApp( title: 'Flutter Demo', - theme: theme, - home: new MyHomePage(title: 'Flutter Demo Home Page'), + theme: themeData, + home: MyHomePage(title: 'Flutter Demo Home Page'), ); } ); } } - ``` Change the theme like this: + ```dart - void changeBrightness() { - DynamicTheme.of(context).setBrightness(Theme.of(context).brightness == Brightness.dark? Brightness.light: Brightness.dark); - } +void changeThemeMode() { + DynamicTheme.of(context).setThemeMode(Theme.of(context).brightness == Brightness.dark ? ThemeMode.light : ThemeMode.dark); +} - void changeColor() { - DynamicTheme.of(context).setThemeData(new ThemeData( - primaryColor: Theme.of(context).primaryColor == Colors.indigo? Colors.red: Colors.indigo - )); - } - +void changeColor() { + DynamicTheme.of(context).setThemeData(ThemeData( + primaryColor: Theme.of(context).primaryColor == Colors.indigo ? Colors.red : Colors.indigo + )); +} ``` -When changing the brightness with `setBrightness`, it is additionally stored in the shared preferences. +When changing the theme mode with `setThemeMode` , it is additionally stored in the shared preferences. ## Also included -### A dialog widget to change the brightness! +### A dialog widget to change the theme mode ! + ![](https://github.com/Norbert515/dynamic_theme/blob/master/assets/dialogs.png) ## Getting Started diff --git a/analysis_options.yaml b/analysis_options.yaml index 86ad603..b0a8093 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,170 +1,27 @@ -# Specify analysis options. -# -# Until there are meta linter rules, each desired lint must be explicitly enabled. -# See: https://github.com/dart-lang/linter/issues/288 -# -# For a list of lints, see: http://dart-lang.github.io/linter/lints/ -# See the configuration guide for more -# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer -# -# There are other similar analysis options files in the flutter repos, -# which should be kept in sync with this file: -# -# - analysis_options.yaml (this file) -# - packages/flutter/lib/analysis_options_user.yaml -# - https://github.com/flutter/plugins/blob/master/analysis_options.yaml -# - https://github.com/flutter/engine/blob/master/analysis_options.yaml -# -# This file contains the analysis options used by Flutter tools, such as IntelliJ, -# Android Studio, and the `flutter analyze` command. +include: package:flutter_lints/flutter.yaml analyzer: + exclude: + - lib/**.g.dart + - test/**.mocks.dart + - lib/generated_plugin_registrant.dart strong-mode: - implicit-dynamic: false + implicit-casts: false errors: - # treat missing required parameters as a warning (not a hint) missing_required_param: warning - # treat missing returns as a warning (not a hint) missing_return: warning - # allow having TODOs in the code - todo: ignore - exclude: - - 'bin/cache/**' - # the following two are relative to the stocks example and the flutter package respectively - # see https://github.com/dart-lang/sdk/issues/28463 - - 'lib/i18n/stock_messages_*.dart' - - 'lib/src/http/**' + # todo: ignore linter: rules: - # these rules are documented on and in the same order as - # the Dart Lint rules page to make maintenance easier - # https://github.com/dart-lang/linter/blob/master/example/all.yaml - always_declare_return_types - - always_put_control_body_on_new_line - # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 - - always_require_non_null_named_parameters - - always_specify_types - - annotate_overrides - # - avoid_annotating_with_dynamic # conflicts with always_specify_types - - avoid_as - # - avoid_bool_literals_in_conditional_expressions # not yet tested - # - avoid_catches_without_on_clauses # we do this commonly - # - avoid_catching_errors # we do this commonly - - avoid_classes_with_only_static_members - # - avoid_double_and_int_checks # only useful when targeting JS runtime - - avoid_empty_else - - avoid_field_initializers_in_const_classes - - avoid_function_literals_in_foreach_calls - # - avoid_implementing_value_types # not yet tested - - avoid_init_to_null - # - avoid_js_rounded_ints # only useful when targeting JS runtime - - avoid_null_checks_in_equality_operators - # - avoid_positional_boolean_parameters # not yet tested - # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) - - avoid_relative_lib_imports - - avoid_renaming_method_parameters - - avoid_return_types_on_setters - # - avoid_returning_null # there are plenty of valid reasons to return null - - avoid_returning_null_for_void - # - avoid_returning_this # there are plenty of valid reasons to return this - # - avoid_setters_without_getters # not yet tested - # - avoid_single_cascade_in_expression_statements # not yet tested - - avoid_slow_async_io - - avoid_types_as_parameter_names - # - avoid_types_on_closure_parameters # conflicts with always_specify_types - - avoid_unused_constructor_parameters - - avoid_void_async - - await_only_futures - - camel_case_types - - cancel_subscriptions - # - cascade_invocations # not yet tested - # - close_sinks # not reliable enough - # - comment_references # blocked on https://github.com/flutter/flutter/issues/20765 - # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204 - - control_flow_in_finally - # - curly_braces_in_flow_control_structures # not yet tested - - directives_ordering - - empty_catches - - empty_constructor_bodies - - empty_statements - # - file_names # not yet tested - - flutter_style_todos - - hash_and_equals - - implementation_imports - # - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811 - - iterable_contains_unrelated_type - # - join_return_with_assignment # not yet tested - - library_names - - library_prefixes - # - lines_longer_than_80_chars # not yet tested - - list_remove_unrelated_type - # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181 - - no_adjacent_strings_in_list - - no_duplicate_case_values - - non_constant_identifier_names - # - null_closures # not yet tested - # - omit_local_variable_types # opposite of always_specify_types - # - one_member_abstracts # too many false positives - # - only_throw_errors # https://github.com/flutter/flutter/issues/5792 - - overridden_fields - - package_api_docs - - package_names - - package_prefixed_library_names - # - parameter_assignments # we do this commonly - - prefer_adjacent_string_concatenation - - prefer_asserts_in_initializer_lists - - prefer_collection_literals - - prefer_conditional_assignment - - prefer_const_constructors - - prefer_const_constructors_in_immutables - - prefer_const_declarations - - prefer_const_literals_to_create_immutables - # - prefer_constructors_over_static_methods # not yet tested - - prefer_contains - - prefer_equal_for_default_values - # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods - - prefer_final_fields - - prefer_final_locals - - prefer_foreach - # - prefer_function_declarations_over_variables # not yet tested - - prefer_generic_function_type_aliases - - prefer_initializing_formals - # - prefer_int_literals # not yet tested - # - prefer_interpolation_to_compose_strings # not yet tested - - prefer_is_empty - - prefer_is_not_empty - - prefer_iterable_whereType - # - prefer_mixin # https://github.com/dart-lang/language/issues/32 - - prefer_single_quotes - - prefer_typing_uninitialized_variables - - prefer_void_to_null - # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml - - recursive_getters - - slash_for_doc_comments - - sort_constructors_first - - sort_pub_dependencies - - sort_unnamed_constructors_first - - test_types_in_equals - - throw_in_finally - # - type_annotate_public_apis # subset of always_specify_types - - type_init_formals - # - unawaited_futures # too many false positives - - unnecessary_brace_in_string_interps - - unnecessary_const - - unnecessary_getters_setters - # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498 - - unnecessary_new - - unnecessary_null_aware_assignments - - unnecessary_null_in_if_null_operators - - unnecessary_overrides - - unnecessary_parenthesis - - unnecessary_statements - - unnecessary_this - - unrelated_type_equality_checks - - use_rethrow_when_possible - # - use_setters_to_change_properties # not yet tested - # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 - # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review - - valid_regexps - # - void_checks # not yet tested + - avoid_bool_literals_in_conditional_expressions + - avoid_escaping_inner_quotes + - avoid_positional_boolean_parameters + - parameter_assignments + - prefer_null_aware_method_calls + - require_trailing_commas + - use_is_even_rather_than_modulo + - use_named_constants + - use_to_and_as_if_applicable + - prefer_relative_imports \ No newline at end of file diff --git a/example/.gitignore b/example/.gitignore index ded98f2..0fa6b67 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -36,9 +36,11 @@ lib/generated_plugin_registrant.dart # Symbolication related app.*.symbols -.flutter-plugins -.flutter-plugins-dependencies -ios/Flutter/flutter_export_environment.sh # Obfuscation related app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/example/.metadata b/example/.metadata index 8cab361..ee7f61d 100644 --- a/example/.metadata +++ b/example/.metadata @@ -4,5 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: 44b7e7d3f42f050a79712daab253af06e9daf530 - channel: beta + revision: cf4400006550b70f28e4b4af815151d1e74846c6 + channel: stable + +project_type: app diff --git a/example/README.md b/example/README.md index 43b0d35..a135626 100644 --- a/example/README.md +++ b/example/README.md @@ -1,8 +1,16 @@ # example -A new Flutter example. +A new Flutter project. ## Getting Started -For help getting started with Flutter, view our online -[documentation](https://flutter.io/). +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml new file mode 100644 index 0000000..61b6c4d --- /dev/null +++ b/example/analysis_options.yaml @@ -0,0 +1,29 @@ +# 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 + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/example/android/.gitignore b/example/android/.gitignore index 0a741cb..6f56801 100644 --- a/example/android/.gitignore +++ b/example/android/.gitignore @@ -9,3 +9,5 @@ GeneratedPluginRegistrant.java # Remember to never publicly share your keystore. # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app key.properties +**/*.keystore +**/*.jks diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index a8fddcf..5fe3c92 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -11,24 +11,43 @@ if (flutterRoot == null) { throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") } +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 29 + compileSdkVersion flutter.compileSdkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } - lintOptions { - disable 'InvalidPackage' + sourceSets { + main.java.srcDirs += 'src/main/kotlin' } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.yourcompany.example" - minSdkVersion 16 - targetSdkVersion 29 - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + applicationId "com.example.example" + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName } buildTypes { @@ -45,7 +64,5 @@ flutter { } dependencies { - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..c208884 --- /dev/null +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 204bf22..3f41384 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,42 +1,32 @@ - - - - - - + package="com.example.example"> + - - - - - + + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> - - + + + diff --git a/example/android/app/src/main/java/com/yourcompany/example/MainActivity.java b/example/android/app/src/main/java/com/yourcompany/example/MainActivity.java deleted file mode 100644 index d45a314..0000000 --- a/example/android/app/src/main/java/com/yourcompany/example/MainActivity.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.yourcompany.example; - -import io.flutter.embedding.android.FlutterActivity; - -public class MainActivity extends FlutterActivity { - -} diff --git a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt new file mode 100644 index 0000000..e793a00 --- /dev/null +++ b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..3db14bb --- /dev/null +++ b/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml index 8a3609b..d460d1e 100644 --- a/example/android/app/src/main/res/values/styles.xml +++ b/example/android/app/src/main/res/values/styles.xml @@ -1,12 +1,18 @@ - + + diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..c208884 --- /dev/null +++ b/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/build.gradle b/example/android/build.gradle index 6de3728..24047dc 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,18 +1,20 @@ buildscript { + ext.kotlin_version = '1.3.50' repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() - jcenter() + mavenCentral() } } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index a5965ab..94adc3a 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,4 +1,3 @@ org.gradle.jvmargs=-Xmx1536M -android.enableR8=true android.useAndroidX=true -android.enableJetifier=true \ No newline at end of file +android.enableJetifier=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 63ab3ae..bc6a58a 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 5a2f14f..44e62bc 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,15 +1,11 @@ include ':app' -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/example/android/settings_aar.gradle b/example/android/settings_aar.gradle deleted file mode 100644 index e7b4def..0000000 --- a/example/android/settings_aar.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':app' diff --git a/example/example.iml b/example/example.iml index b3a2b0c..e5c8371 100644 --- a/example/example.iml +++ b/example/example.iml @@ -3,13 +3,16 @@ + + + - + \ No newline at end of file diff --git a/example/example_android.iml b/example/example_android.iml deleted file mode 100644 index b050030..0000000 --- a/example/example_android.iml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/example/ios/.gitignore b/example/ios/.gitignore index e96ef60..7a7f987 100644 --- a/example/ios/.gitignore +++ b/example/ios/.gitignore @@ -1,3 +1,4 @@ +**/dgph *.mode1v3 *.mode2v3 *.moved-aside @@ -18,6 +19,7 @@ Flutter/App.framework Flutter/Flutter.framework Flutter/Flutter.podspec Flutter/Generated.xcconfig +Flutter/ephemeral/ Flutter/app.flx Flutter/app.zip Flutter/flutter_assets/ diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 6c2de80..8d4492f 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -20,11 +20,7 @@ ???? CFBundleVersion 1.0 - UIRequiredDeviceCapabilities - - arm64 - MinimumOSVersion - 8.0 + 9.0 diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig index e8efba1..592ceee 100644 --- a/example/ios/Flutter/Debug.xcconfig +++ b/example/ios/Flutter/Debug.xcconfig @@ -1,2 +1 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig index 399e934..592ceee 100644 --- a/example/ios/Flutter/Release.xcconfig +++ b/example/ios/Flutter/Release.xcconfig @@ -1,2 +1 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Podfile b/example/ios/Podfile deleted file mode 100644 index d077b08..0000000 --- a/example/ios/Podfile +++ /dev/null @@ -1,69 +0,0 @@ -# Uncomment this line to define a global platform for your project -# platform :ios, '9.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def parse_KV_file(file, separator='=') - file_abs_path = File.expand_path(file) - if !File.exists? file_abs_path - return []; - end - pods_ary = [] - skip_line_start_symbols = ["#", "/"] - File.foreach(file_abs_path) { |line| - next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } - plugin = line.split(pattern=separator) - if plugin.length == 2 - podname = plugin[0].strip() - path = plugin[1].strip() - podpath = File.expand_path("#{path}", file_abs_path) - pods_ary.push({:name => podname, :path => podpath}); - else - puts "Invalid plugin specification: #{line}" - end - } - return pods_ary -end - -target 'Runner' do - # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock - # referring to absolute paths on developers' machines. - system('rm -rf .symlinks') - system('mkdir -p .symlinks/plugins') - - # Flutter Pods - generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') - if generated_xcode_build_settings.empty? - puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." - end - generated_xcode_build_settings.map { |p| - if p[:name] == 'FLUTTER_FRAMEWORK_DIR' - symlink = File.join('.symlinks', 'flutter') - File.symlink(File.dirname(p[:path]), symlink) - pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) - end - } - - # Plugin Pods - plugin_pods = parse_KV_file('../.flutter-plugins') - plugin_pods.map { |p| - symlink = File.join('.symlinks', 'plugins', p[:name]) - File.symlink(p[:path], symlink) - pod p[:name], :path => File.join(symlink, 'ios') - } -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['ENABLE_BITCODE'] = 'NO' - end - end -end diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 7fd3612..6edd238 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,21 +3,13 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; - 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; }; - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; - 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -30,8 +22,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -41,17 +31,13 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; @@ -63,8 +49,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -74,10 +58,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, - 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, @@ -91,7 +72,6 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, ); sourceTree = ""; }; @@ -106,27 +86,18 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( - 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, - 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C147021CF9000F007C117D /* Info.plist */, - 97C146F11CF9000F007C117D /* Supporting Files */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, ); path = Runner; sourceTree = ""; }; - 97C146F11CF9000F007C117D /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 97C146F21CF9000F007C117D /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -156,17 +127,18 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0910; - ORGANIZATIONNAME = "The Chromium Authors"; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; }; }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -188,11 +160,8 @@ buildActionMask = 2147483647; files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -212,7 +181,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; @@ -235,8 +204,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, - 97C146F31CF9000F007C117D /* main.m in Sources */, + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -263,9 +231,79 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -277,12 +315,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -309,7 +349,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -319,7 +359,6 @@ }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -331,12 +370,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -357,9 +398,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -369,22 +413,20 @@ isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { - ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CURRENT_PROJECT_VERSION = 1; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( + LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/Flutter", + "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.example; + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -393,22 +435,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CURRENT_PROJECT_VERSION = 1; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( + LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/Flutter", + "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.example; + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; @@ -421,6 +460,7 @@ buildConfigurations = ( 97C147031CF9000F007C117D /* Debug */, 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -430,6 +470,7 @@ buildConfigurations = ( 97C147061CF9000F007C117D /* Debug */, 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 1d526a1..919434a 100644 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 1263ac8..c87d15a 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ - - - - + + - - + + + + IDEDidComputeMac32BitWarning + + + diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/example/ios/Runner/AppDelegate.h b/example/ios/Runner/AppDelegate.h deleted file mode 100644 index cf210d2..0000000 --- a/example/ios/Runner/AppDelegate.h +++ /dev/null @@ -1,6 +0,0 @@ -#import -#import - -@interface AppDelegate : FlutterAppDelegate - -@end diff --git a/example/ios/Runner/AppDelegate.m b/example/ios/Runner/AppDelegate.m deleted file mode 100644 index 112becd..0000000 --- a/example/ios/Runner/AppDelegate.m +++ /dev/null @@ -1,12 +0,0 @@ -#include "AppDelegate.h" -#include "GeneratedPluginRegistrant.h" - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [GeneratedPluginRegistrant registerWithRegistry:self]; - // Override point for customization after application launch. - return [super application:application didFinishLaunchingWithOptions:launchOptions]; -} - -@end diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index 3d43d11..dc9ada4 100644 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index 2983932..27491e8 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -3,7 +3,9 @@ CFBundleDevelopmentRegion - en + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Example CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -15,21 +17,17 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0 + $(FLUTTER_BUILD_NAME) CFBundleSignature ???? CFBundleVersion - 1 + $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main - UIRequiredDeviceCapabilities - - arm64 - UISupportedInterfaceOrientations UIInterfaceOrientationPortrait @@ -44,6 +42,6 @@ UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance - + diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/example/ios/Runner/main.m b/example/ios/Runner/main.m deleted file mode 100644 index 0ccc450..0000000 --- a/example/ios/Runner/main.m +++ /dev/null @@ -1,9 +0,0 @@ -#import -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/example/lib/main.dart b/example/lib/main.dart index 1ea5fa3..9e212bd 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,23 +1,29 @@ import 'package:dynamic_theme/dynamic_theme.dart'; -import 'package:dynamic_theme/theme_switcher_widgets.dart'; import 'package:flutter/material.dart'; -void main() => runApp(MyApp()); +void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return DynamicTheme( - defaultBrightness: Brightness.light, - data: (Brightness brightness) => ThemeData( + defaultThemeMode: ThemeMode.light, + loadThemeOnStart: true, + data: (mode) => ThemeData( primarySwatch: Colors.indigo, - brightness: brightness, + brightness: mode == ThemeMode.dark ? Brightness.dark : Brightness.light, ), - loadBrightnessOnStart: true, - themedWidgetBuilder: (BuildContext context, ThemeData theme) { + themedWidgetBuilder: ( + BuildContext context, + ThemeMode mode, + ThemeData? data, + ) { return MaterialApp( + themeMode: mode, title: 'Flutter Demo', - theme: theme, + theme: data, home: const MyHomePage(title: 'Flutter Demo Home Page'), ); }, @@ -26,7 +32,8 @@ class MyApp extends StatelessWidget { } class MyHomePage extends StatefulWidget { - const MyHomePage({Key key, this.title}) : super(key: key); + const MyHomePage({Key? key, required this.title}) : super(key: key); + final String title; @override @@ -45,9 +52,10 @@ class _MyHomePageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( - onPressed: DynamicTheme.of(context).toggleBrightness, + onPressed: DynamicTheme.of(context).toggleThemeMode, child: const Text('Toggle brightness'), ), + const SizedBox(height: 16), ElevatedButton( onPressed: changeColor, child: const Text('Change color'), @@ -79,8 +87,8 @@ class _MyHomePageState extends State { context: context, builder: (BuildContext context) { return BrightnessSwitcherDialog( - onSelectedTheme: (Brightness brightness) { - DynamicTheme.of(context).setBrightness(brightness); + onSelectedTheme: (ThemeMode mode) { + DynamicTheme.of(context).setThemeMode(mode); }, ); }, diff --git a/example/pubspec.lock b/example/pubspec.lock index 3428756..a298c46 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -21,14 +21,14 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" clock: dependency: transitive description: @@ -49,14 +49,14 @@ packages: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "0.1.2" + version: "1.0.4" dynamic_theme: - dependency: "direct dev" + dependency: "direct main" description: path: ".." relative: true source: path - version: "2.0.0-nullsafety" + version: "2.0.0" fake_async: dependency: transitive description: @@ -70,19 +70,26 @@ packages: name: ffi url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.2" file: dependency: transitive description: name: file url: "https://pub.dartlang.org" source: hosted - version: "6.1.0" + version: "6.1.2" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" flutter_test: dependency: "direct dev" description: flutter @@ -100,20 +107,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.6.3" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.7.0" path: dependency: transitive description: @@ -127,7 +141,7 @@ packages: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.2" path_provider_platform_interface: dependency: transitive description: @@ -141,49 +155,63 @@ packages: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.4" platform: dependency: transitive description: name: platform url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" process: dependency: transitive description: name: process url: "https://pub.dartlang.org" source: hosted - version: "4.1.0" + version: "4.2.4" shared_preferences: dependency: transitive description: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.9" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + shared_preferences_ios: + dependency: transitive + description: + name: shared_preferences_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.3" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" shared_preferences_platform_interface: dependency: transitive description: @@ -197,14 +225,14 @@ packages: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.2" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.0.3" sky_engine: dependency: transitive description: flutter @@ -216,7 +244,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -251,7 +279,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19" + version: "0.4.3" typed_data: dependency: transitive description: @@ -265,14 +293,14 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" win32: dependency: transitive description: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.0.4" + version: "2.3.1" xdg_directories: dependency: transitive description: @@ -281,5 +309,5 @@ packages: source: hosted version: "0.2.0" sdks: - dart: ">=2.12.0 <3.0.0" - flutter: ">=1.20.0" + dart: ">=2.15.0 <3.0.0" + flutter: ">=2.5.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 190c809..316149b 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,30 +1,55 @@ name: example -description: A new Flutter example. -version: 1.0.1 -author: 'Norbert Kozsir ' -homepage: 'https://github.com/Norbert515/dynamic_theme' +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 environment: - # Works in Dart 1 (starting with 1.20.1), and works in Dart 2. - sdk: '>=1.20.1 <3.0.0' + sdk: ">=2.15.0 <3.0.0" +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. dependencies: flutter: sdk: flutter + # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.0 + cupertino_icons: ^1.0.2 + dynamic_theme: + path: ../ dev_dependencies: flutter_test: sdk: flutter - dynamic_theme: - path: ../ + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^1.0.0 # For information on the generic Dart part of this file, see the -# following page: https://www.dartlang.org/tools/pub/pubspec +# following page: https://dart.dev/tools/pub/pubspec # The following section is specific to Flutter. flutter: @@ -36,14 +61,14 @@ flutter: # To add assets to your application, add an assets section, like this: # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.io/assets-and-images/#resolution-aware. + # https://flutter.dev/assets-and-images/#resolution-aware. # For details regarding adding assets from package dependencies, see - # https://flutter.io/assets-and-images/#from-packages + # https://flutter.dev/assets-and-images/#from-packages # To add custom fonts to your application, add a fonts section here, # in this "flutter" section. Each entry in this list should have a @@ -62,5 +87,5 @@ flutter: # - asset: fonts/TrajanPro_Bold.ttf # weight: 700 # - # For details regarding fonts from package dependencies, - # see https://flutter.io/custom-fonts/#from-packages + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart deleted file mode 100644 index f395dac..0000000 --- a/example/test/widget_test.dart +++ /dev/null @@ -1,29 +0,0 @@ -// This is a basic Flutter widget test. -// To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter -// provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to -// find child widgets in the widget tree, read text, and verify that the values of widget properties -// are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:example/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} diff --git a/example/web/favicon.png b/example/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/example/web/favicon.png differ diff --git a/example/web/icons/Icon-192.png b/example/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/example/web/icons/Icon-192.png differ diff --git a/example/web/icons/Icon-512.png b/example/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/example/web/icons/Icon-512.png differ diff --git a/example/web/icons/Icon-maskable-192.png b/example/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000..eb9b4d7 Binary files /dev/null and b/example/web/icons/Icon-maskable-192.png differ diff --git a/example/web/icons/Icon-maskable-512.png b/example/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000..d69c566 Binary files /dev/null and b/example/web/icons/Icon-maskable-512.png differ diff --git a/example/web/index.html b/example/web/index.html new file mode 100644 index 0000000..b6b9dd2 --- /dev/null +++ b/example/web/index.html @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + example + + + + + + + diff --git a/example/web/manifest.json b/example/web/manifest.json new file mode 100644 index 0000000..096edf8 --- /dev/null +++ b/example/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/lib/dynamic_theme.dart b/lib/dynamic_theme.dart index 8f6d988..dc0d605 100644 --- a/lib/dynamic_theme.dart +++ b/lib/dynamic_theme.dart @@ -1,151 +1,4 @@ -import 'dart:async'; +library dynamic_theme; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:flutter/material.dart'; - -typedef ThemedWidgetBuilder = Widget Function(BuildContext context, ThemeData data); - -typedef ThemeDataWithBrightnessBuilder = ThemeData Function(Brightness brightness); - -class DynamicTheme extends StatefulWidget { - const DynamicTheme({ - Key? key, - required this.data, - required this.themedWidgetBuilder, - this.defaultBrightness = Brightness.light, - this.loadBrightnessOnStart = true, - }) : super(key: key); - - /// Builder that gets called when the brightness or theme changes - final ThemedWidgetBuilder themedWidgetBuilder; - - /// Callback that returns the latest brightness - final ThemeDataWithBrightnessBuilder data; - - /// The default brightness on start - /// - /// Defaults to `Brightness.light` - final Brightness defaultBrightness; - - /// Whether or not to load the brightness on start - /// - /// Defaults to `true` - final bool loadBrightnessOnStart; - - @override - DynamicThemeState createState() => DynamicThemeState(); - - static DynamicThemeState? of(BuildContext context) { - return context.findAncestorStateOfType(); - } -} - -class DynamicThemeState extends State { - late ThemeData _themeData; - - Brightness _brightness = Brightness.light; - - bool _shouldLoadBrightness = true; - - static const String _sharedPreferencesKey = 'isDark'; - - /// Get the current `ThemeData` - ThemeData get themeData => _themeData; - - /// Get the current `Brightness` - Brightness get brightness => _brightness; - - @override - void initState() { - super.initState(); - _initVariables(); - _loadBrightness(); - } - - /// Loads the brightness depending on the `loadBrightnessOnStart` value - Future _loadBrightness() async { - if (!_shouldLoadBrightness) { - return; - } - final bool isDark = await _getBrightnessBool(); - _brightness = isDark ? Brightness.dark : Brightness.light; - _themeData = widget.data(_brightness); - if (mounted) { - setState(() {}); - } - } - - /// Initializes the variables - void _initVariables() { - _brightness = widget.defaultBrightness; - _themeData = widget.data(_brightness); - _shouldLoadBrightness = widget.loadBrightnessOnStart; - } - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - _themeData = widget.data(_brightness); - } - - @override - void didUpdateWidget(DynamicTheme oldWidget) { - super.didUpdateWidget(oldWidget); - _themeData = widget.data(_brightness); - } - - /// Sets the new brightness - /// Rebuilds the tree - Future setBrightness(Brightness brightness) async { - // Update state with new values - setState(() { - _themeData = widget.data(brightness); - _brightness = brightness; - }); - // Save the brightness - await _saveBrightness(brightness); - } - - /// Toggles the brightness from dark to light - Future toggleBrightness() async { - // If brightness is dark, set it to light - // If it's not dark, set it to dark - if (_brightness == Brightness.dark) - await setBrightness(Brightness.light); - else - await setBrightness(Brightness.dark); - } - - /// Changes the theme using the provided `ThemeData` - void setThemeData(ThemeData data) { - setState(() { - _themeData = data; - }); - } - - /// Saves the provided brightness in `SharedPreferences` - Future _saveBrightness(Brightness brightness) async { - //! Shouldn't save the brightness if you don't want to load it - if (!_shouldLoadBrightness) { - return; - } - final SharedPreferences prefs = await SharedPreferences.getInstance(); - // Saves whether or not the provided brightness is dark - await prefs.setBool( - _sharedPreferencesKey, brightness == Brightness.dark ? true : false); - } - - /// Returns a boolean that gives you the latest brightness - Future _getBrightnessBool() async { - final SharedPreferences prefs = await SharedPreferences.getInstance(); - // Gets the bool stored in prefs - // Or returns whether or not the `defaultBrightness` is dark - return prefs.getBool(_sharedPreferencesKey) ?? - widget.defaultBrightness == Brightness.dark; - } - - @override - Widget build(BuildContext context) { - return widget.themedWidgetBuilder(context, _themeData); - } -} +export 'src/dynamic_theme.dart'; +export 'src/theme_switcher_widgets.dart'; diff --git a/lib/src/dynamic_theme.dart b/lib/src/dynamic_theme.dart new file mode 100644 index 0000000..5a0e130 --- /dev/null +++ b/lib/src/dynamic_theme.dart @@ -0,0 +1,187 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +typedef ThemedWidgetBuilder = Widget Function( + BuildContext, + ThemeMode, + ThemeData?, +); + +typedef ThemeDataWithThemeModeBuilder = ThemeData Function(ThemeMode); + +extension on ThemeMode { + String get string => toString().split('.').last; +} + +extension on String { + ThemeMode toThemeMode() { + switch (this) { + case 'system': + return ThemeMode.system; + case 'light': + return ThemeMode.light; + case 'dark': + return ThemeMode.dark; + default: + throw Exception('Unknown theme mode: $this'); + } + } +} + +/// Creates a widget that applies a theme to a child widget. You can change the +/// theme by calling `setThemeMode`. +class DynamicTheme extends StatefulWidget { + const DynamicTheme({ + Key? key, + required this.themedWidgetBuilder, + this.data, + this.defaultThemeMode = ThemeMode.system, + this.loadThemeOnStart = true, + }) : super(key: key); + + /// Builder that gets called when the theme changes. + final ThemedWidgetBuilder themedWidgetBuilder; + + /// Callback that returns the latest [ThemeMode]. + final ThemeDataWithThemeModeBuilder? data; + + /// The default theme on start + /// + /// Defaults to `ThemeMode.system` + final ThemeMode defaultThemeMode; + + /// Whether or not to load the theme on start. + /// + /// Defaults to `true` + final bool loadThemeOnStart; + + @override + DynamicThemeState createState() => DynamicThemeState(); + + static DynamicThemeState of(BuildContext context) { + return context.findAncestorStateOfType()!; + } +} + +class DynamicThemeState extends State { + ThemeMode _themeMode = ThemeMode.light; + bool _shouldLoadThemeMode = true; + + ThemeData? _themeData; + + static const _sharedPreferencesKey = 'themeMode'; + + /// Get the current `ThemeData` + ThemeData get themeData => _themeData ?? Theme.of(context); + + /// Get the current `ThemeMode`. + ThemeMode get themeMode => _themeMode; + + @override + void initState() { + super.initState(); + _initVariables(); + _loadThemeMode(); + } + + /// Loads the theme depending on the `loadThemeOnStart` value. + Future _loadThemeMode() async { + if (!_shouldLoadThemeMode) { + return; + } + final myThemeMode = await _getThemeMode(); + _themeMode = myThemeMode; + _themeData = widget.data?.call(_themeMode); + if (mounted) { + setState(() {}); + } + } + + /// Initializes the variables. + void _initVariables() { + _themeMode = widget.defaultThemeMode; + _themeData = widget.data?.call(themeMode); + _shouldLoadThemeMode = widget.loadThemeOnStart; + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _themeData = widget.data?.call(_themeMode); + } + + @override + void didUpdateWidget(DynamicTheme oldWidget) { + super.didUpdateWidget(oldWidget); + _themeData = widget.data?.call(_themeMode); + } + + /// Sets the new theme + /// Rebuilds the tree + Future setThemeMode(ThemeMode themeMode) async { + // Update state with new values + setState(() { + _themeData = widget.data?.call(themeMode); + _themeMode = themeMode; + }); + await _saveThemeMode(themeMode); + } + + /// Changes the theme using the provided `ThemeData` + void setThemeData(ThemeData data) { + setState(() { + _themeData = data; + }); + } + + /// Toggles [ThemeMode.light] to [ThemeMode.dark] and vice versa. + /// + /// If the current theme is [ThemeMode.system], it will be set to + /// [ThemeMode.light] or [ThemeMode.dark] depending on the current system + /// brightness. + Future toggleThemeMode() async { + switch (_themeMode) { + case ThemeMode.system: + // If brightness is dark, set it to light + // If it's not dark, set it to dark + final b = Theme.of(context).brightness; + if (b == Brightness.dark) { + await setThemeMode(ThemeMode.light); + } else { + await setThemeMode(ThemeMode.dark); + } + break; + case ThemeMode.light: + await setThemeMode(ThemeMode.dark); + break; + case ThemeMode.dark: + await setThemeMode(ThemeMode.light); + break; + } + } + + /// Saves the provided themeMode in [SharedPreferences]. + Future _saveThemeMode(ThemeMode themeMode) async { + //! Shouldn't save the themeMode if you don't want to load it + if (!_shouldLoadThemeMode) { + return; + } + final SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setString(_sharedPreferencesKey, themeMode.string); + } + + /// Returns a [ThemeMode] that gives you the latest brightness. + Future _getThemeMode() async { + final SharedPreferences prefs = await SharedPreferences.getInstance(); + // Gets the ThemeMode stored in prefs or returns the [defaultThemeMode]. + return prefs.getString(_sharedPreferencesKey)?.toThemeMode() ?? + widget.defaultThemeMode; + } + + @override + Widget build(BuildContext context) { + return widget.themedWidgetBuilder(context, _themeMode, _themeData); + } +} diff --git a/lib/src/theme_switcher_widgets.dart b/lib/src/theme_switcher_widgets.dart new file mode 100644 index 0000000..6c79bd9 --- /dev/null +++ b/lib/src/theme_switcher_widgets.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; + +extension on Brightness { + ThemeMode toThemeMode() { + return this == Brightness.dark ? ThemeMode.dark : ThemeMode.light; + } +} + +class BrightnessSwitcherDialog extends StatelessWidget { + const BrightnessSwitcherDialog({Key? key, required this.onSelectedTheme}) + : super(key: key); + + final ValueChanged onSelectedTheme; + + @override + Widget build(BuildContext context) { + return SimpleDialog( + title: const Text('Select Theme'), + children: [ + RadioListTile( + value: ThemeMode.light, + groupValue: Theme.of(context).brightness.toThemeMode(), + onChanged: (ThemeMode? value) { + onSelectedTheme(ThemeMode.light); + }, + title: const Text('Light'), + ), + RadioListTile( + value: ThemeMode.dark, + groupValue: Theme.of(context).brightness.toThemeMode(), + onChanged: (ThemeMode? value) { + onSelectedTheme(ThemeMode.dark); + }, + title: const Text('Spooky 👻'), + ), + ], + ); + } +} diff --git a/lib/theme_switcher_widgets.dart b/lib/theme_switcher_widgets.dart deleted file mode 100644 index bc1ecc6..0000000 --- a/lib/theme_switcher_widgets.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:flutter/material.dart'; - -class BrightnessSwitcherDialog extends StatelessWidget { - const BrightnessSwitcherDialog({Key? key, required this.onSelectedTheme}) - : super(key: key); - - final ValueChanged onSelectedTheme; - - @override - Widget build(BuildContext context) { - return SimpleDialog( - title: const Text('Select Theme'), - children: [ - RadioListTile( - value: Brightness.light, - groupValue: Theme.of(context).brightness, - onChanged: (Brightness? value) { - onSelectedTheme(Brightness.light); - }, - title: const Text('Light'), - ), - RadioListTile( - value: Brightness.dark, - groupValue: Theme.of(context).brightness, - onChanged: (Brightness? value) { - onSelectedTheme(Brightness.dark); - }, - title: const Text('Spooky 👻'), - ), - ], - ); - } -} diff --git a/pubspec.lock b/pubspec.lock index 4417315..5791b28 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -21,14 +21,14 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" clock: dependency: transitive description: @@ -69,6 +69,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" flutter_test: dependency: "direct dev" description: flutter @@ -86,20 +93,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.6.3" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.7.0" path: dependency: transitive description: @@ -155,7 +169,21 @@ packages: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.0.9" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + shared_preferences_ios: + dependency: transitive + description: + name: shared_preferences_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" shared_preferences_linux: dependency: transitive description: @@ -202,7 +230,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -237,7 +265,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19" + version: "0.4.3" typed_data: dependency: transitive description: @@ -251,7 +279,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" win32: dependency: transitive description: @@ -267,5 +295,5 @@ packages: source: hosted version: "0.2.0" sdks: - dart: ">=2.12.0 <3.0.0" - flutter: ">=1.20.0" + dart: ">=2.14.0 <3.0.0" + flutter: ">=2.5.0" diff --git a/pubspec.yaml b/pubspec.yaml index e23a839..6722684 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,6 @@ name: dynamic_theme description: Changes the theme during runtime, also presists brightness settings across restarts -version: 2.0.0-nullsafety -author: 'Norbert Kozsir ' +version: 2.0.0 homepage: 'https://github.com/Norbert515/dynamic_theme' environment: @@ -10,8 +9,9 @@ environment: dependencies: flutter: sdk: flutter - shared_preferences: ^2.0.5 + shared_preferences: ">=2.0.0 <3.0.0" dev_dependencies: + flutter_lints: ^1.0.0 flutter_test: sdk: flutter diff --git a/test/easy_theme_test_change.dart b/test/easy_theme_change_test.dart similarity index 54% rename from test/easy_theme_test_change.dart rename to test/easy_theme_change_test.dart index 952d2be..8bd22b4 100644 --- a/test/easy_theme_test_change.dart +++ b/test/easy_theme_change_test.dart @@ -8,9 +8,10 @@ GlobalKey easyThemeKey = GlobalKey(); void main() { testWidgets('change brightness', (WidgetTester tester) async { - await tester.pumpWidget(MyApp()); + await tester.pumpWidget(const MyApp()); - MaterialApp app = find.byType(MaterialApp).evaluate().first.widget as MaterialApp; + MaterialApp app = + find.byType(MaterialApp).evaluate().first.widget as MaterialApp; expect(app.theme?.brightness, equals(Brightness.dark)); await tester.tap(find.byKey(key)); @@ -28,36 +29,48 @@ void main() { } class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return DynamicTheme( - key: easyThemeKey, - defaultBrightness: Brightness.dark, - data: (Brightness brightness) { - return ThemeData( - primarySwatch: Colors.indigo, - brightness: brightness, - ); - }, - themedWidgetBuilder: (BuildContext context, ThemeData theme) { - return MaterialApp( - title: 'Flutter Demo', - theme: theme, - home: ButtonPage(), - ); - }); + key: easyThemeKey, + defaultThemeMode: ThemeMode.dark, + data: (ThemeMode mode) { + return ThemeData( + primarySwatch: Colors.indigo, + brightness: + mode == ThemeMode.dark ? Brightness.dark : Brightness.light, + ); + }, + themedWidgetBuilder: ( + BuildContext context, + ThemeMode mode, + ThemeData? theme, + ) { + return MaterialApp( + themeMode: mode, + title: 'Flutter Demo', + theme: theme, + home: const ButtonPage(), + ); + }, + ); } } class ButtonPage extends StatelessWidget { + const ButtonPage({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ElevatedButton( onPressed: () { - DynamicTheme.of(context)?.setBrightness( - Theme.of(context).brightness == Brightness.dark - ? Brightness.light - : Brightness.dark); + DynamicTheme.of(context).setThemeMode( + Theme.of(context).brightness == Brightness.dark + ? ThemeMode.light + : ThemeMode.dark, + ); }, key: key, child: Container(), diff --git a/test/easy_theme_test.dart b/test/easy_theme_test.dart index 25c4809..52afea6 100644 --- a/test/easy_theme_test.dart +++ b/test/easy_theme_test.dart @@ -8,7 +8,7 @@ GlobalKey easyThemeKey = GlobalKey(); void main() { testWidgets('test finds state', (WidgetTester tester) async { - await tester.pumpWidget(MyApp()); + await tester.pumpWidget(const MyApp()); expect(state, equals(null)); @@ -20,28 +20,39 @@ void main() { } class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return DynamicTheme( - key: easyThemeKey, - defaultBrightness: Brightness.light, - data: (Brightness brightness) { - return ThemeData( + key: easyThemeKey, + defaultThemeMode: ThemeMode.light, + themedWidgetBuilder: ( + BuildContext context, + ThemeMode mode, + ThemeData? theme, + ) { + return MaterialApp( + themeMode: mode, + title: 'Flutter Demo', + theme: ThemeData( + primarySwatch: Colors.indigo, + brightness: Brightness.light, + ), + darkTheme: ThemeData( primarySwatch: Colors.indigo, - brightness: brightness, - ); - }, - themedWidgetBuilder: (BuildContext context, ThemeData theme) { - return MaterialApp( - title: 'Flutter Demo', - theme: theme, - home: ButtonPage(), - ); - }); + brightness: Brightness.dark, + ), + home: const ButtonPage(), + ); + }, + ); } } class ButtonPage extends StatelessWidget { + const ButtonPage({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ElevatedButton(