├── .github └── workflows │ └── easy_dynamic_theme.yaml ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── demo ├── easy_dynamic_theme.png └── widgets.gif ├── example ├── .gitignore ├── .metadata ├── README.md ├── images │ └── background.jpg ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ ├── blur_container.dart │ ├── home.dart │ ├── main.dart │ └── theme.dart ├── pubspec.yaml ├── test │ └── widget_test.dart └── web │ ├── favicon.png │ ├── icons │ ├── Icon-192.png │ └── Icon-512.png │ ├── index.html │ └── manifest.json ├── lib ├── easy_dynamic_theme.dart └── src │ ├── easy_dynamic_widget.dart │ ├── services │ └── shared_preferences_service.dart │ └── widgets │ ├── easy_dynamic_theme_auto_switch.dart │ ├── easy_dynamic_theme_btn.dart │ └── easy_dynamic_theme_switch.dart ├── pubspec.yaml └── test └── src ├── default_app_wrapper.dart ├── easy_dynamic_theme_test.dart ├── services └── shared_preferences_service_test.dart └── widgets ├── easy_dynamic_theme_auto_switch_test.dart ├── easy_dynamic_theme_btn_test.dart └── easy_dynamic_theme_switch_test.dart /.github/workflows/easy_dynamic_theme.yaml: -------------------------------------------------------------------------------- 1 | name: easy_dynamic_theme 2 | 3 | on: 4 | # Trigger the workflow on push 5 | # but only for the master branch 6 | push: 7 | branches: 8 | - master 9 | - develop 10 | pull_request: 11 | branches: 12 | - master 13 | - develop 14 | 15 | jobs: 16 | test: 17 | # Job name is Running Tests 18 | name: Tests 19 | # This job runs on Linux 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v1 23 | - uses: subosito/flutter-action@v1 24 | with: 25 | flutter-version: '2.0.3' 26 | channel: 'stable' 27 | - run: flutter pub get 28 | - run: flutter test --no-pub --coverage 29 | - run: bash <(curl -s https://codecov.io/bash) -t 2854257d-20d6-4d73-a56c-f4ee1c85e9fc 30 | 31 | analyze: 32 | name: Analyze 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: actions/checkout@v1 36 | - uses: subosito/flutter-action@v1 37 | with: 38 | flutter-version: '2.0.3' 39 | channel: 'stable' 40 | - run: flutter pub get 41 | - name: Analyze lib 42 | run: flutter analyze lib 43 | - name: Analyze test 44 | run: flutter analyze test 45 | 46 | format: 47 | name: Format 48 | runs-on: ubuntu-latest 49 | steps: 50 | - uses: actions/checkout@v1 51 | - uses: subosito/flutter-action@v1 52 | with: 53 | flutter-version: '2.0.4' 54 | channel: 'stable' 55 | - run: flutter pub get 56 | - name: Format lib 57 | run: flutter format lib --set-exit-if-changed 58 | - name: Format test 59 | run: flutter format test --set-exit-if-changed 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | .idea 4 | 5 | .packages 6 | .pub/ 7 | 8 | build/ 9 | 10 | *.iml -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: d408d302e22179d598f467e11da5dd968dbdc9ec 8 | channel: beta 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 2.3.1 2 | - **Documentation** 3 | - Add buymeacoffee link on readme file 4 | - Upgrade dependency version to latest (shared_preferences: 2.1.1) 5 | 6 | # 2.3.0 7 | 8 | - **Features** 9 | - Remove deprecated widgets 10 | - Remove deprecated version of the Android embedding in example app 11 | 12 | # 2.2.0 13 | 14 | - **Features** 15 | - Added new widget: **EasyDynamicThemeAutoSwitch**. 16 | - Added tests to increase coverage 17 | 18 | - **Enhances** 19 | - Added tests to increase coverage 20 | 21 | ## 2.1.0 22 | 23 | - **Enhances** 24 | - Added tests to increase coverage 25 | 26 | ## 2.0.2 27 | 28 | - **Documentation** 29 | - Fix images in README file 30 | - Files formatted according to dartfmt. 31 | 32 | ## 2.0.1 33 | 34 | - **Features** 35 | - Added Windows compatibility 36 | 37 | - **Enhances** 38 | - Refactor files structure 39 | 40 | ## 2.0.0 41 | 42 | - **Features** 43 | - Added null safety support. 44 | 45 | ## 1.0.0 46 | 47 | - **Features** 48 | - Added new widget: **EasyDynamicThemeSwitch**. 49 | 50 | - **Documentation** 51 | - Files formatted according to dartfmt. 52 | 53 | ## 0.0.5 54 | 55 | - **Enhances** 56 | - Changed the behavior for **EasyDynamicThemeWidget** on initialThemeMode parameter. 57 | - Changed the behavior for **_toggleTheme** function on initialThemeMode parameter. 58 | 59 | ## 0.0.4 60 | 61 | - **Enhances** 62 | - Refactored and renamed **switchTheme** function to **changeTheme**. 63 | - Wrapped **EasyDynamicThemeWidget** build function in a FutureBuilder. 64 | 65 | - **Documentation** 66 | - Added documentation for *changeTheme* function. 67 | 68 | ## 0.0.3 69 | 70 | - **Documentation** 71 | - Files formatted according to dartfmt. 72 | 73 | ## 0.0.2 74 | 75 | - **Documentation** 76 | - Documentation text changed. 77 | - Added project description. 78 | 79 | ## 0.0.1 80 | 81 | - **Features** 82 | - Added new widget: 83 | - **EasyDynamicThemeBtn**. 84 | - Added new methods: 85 | - **EasyDynamicTheme.of(context).themeMode** 86 | - **EasyDynamicTheme.of(context).switchTheme()** 87 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Rene Lazo Mendez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Easy Dynamic Theme 2 | 3 | This is a new and easy approach on Flutter Themes. 4 | 5 | Automatically get your OS defined Theme (Dynamic), force your prefered one (Light / Dark) and persist your choice in the device. 6 | 7 | ![Pub Version](https://img.shields.io/pub/v/easy_dynamic_theme) 8 | ![flutter tests](https://github.com/rlazom/easy_dynamic_theme/workflows/easy_dynamic_theme/badge.svg?branch=master) 9 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/5f373592e0b3471e8f62229df15de60f)](https://app.codacy.com/gh/rlazom/easy_dynamic_theme?utm_source=github.com&utm_medium=referral&utm_content=rlazom/easy_dynamic_theme&utm_campaign=Badge_Grade_Settings) 10 | [![codecov](https://codecov.io/gh/rlazom/easy_dynamic_theme/branch/master/graph/badge.svg)](https://codecov.io/gh/rlazom/easy_dynamic_theme) 11 | ![GitHub](https://img.shields.io/github/license/rlazom/easy_dynamic_theme) 12 | [![BuyMeACoffee][buy_me_a_coffee_badge]][buy_me_a_coffee] 13 | 14 | Easy peasy, don't you think? ;) 15 | 16 | 17 | 18 | ## Demo 19 | 20 | 21 | 22 | ## Getting Started 23 | 24 | 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. 25 | 26 | ## Minimum Requirements 27 | 28 | - Dart SDK: >=2.12.0 <3.0.0 29 | - Flutter: >= 1.20.0 30 | 31 | ## Installation and Usage 32 | 33 | Once you're familiar with Flutter you may install this package adding `easy_dynamic_theme` to the dependencies list 34 | of the `pubspec.yaml` file as follow: 35 | 36 | ```yaml 37 | dependencies: 38 | flutter: 39 | sdk: flutter 40 | easy_dynamic_theme: ^2.2.0 41 | ``` 42 | 43 | Then run the command `flutter packages get` on the console. 44 | 45 | ## Examples of use 46 | 47 | All magic occurs in your `main.dart` file 48 | 49 | ```dart 50 | import 'package:flutter/material.dart'; 51 | import 'package:easy_dynamic_theme/easy_dynamic_theme.dart'; 52 | import 'home.dart'; 53 | 54 | void main() async { 55 | runApp( 56 | EasyDynamicThemeWidget( 57 | child: MyApp(), 58 | ), 59 | ); 60 | } 61 | 62 | class MyApp extends StatelessWidget { 63 | final String title = 'EDT - Example'; 64 | 65 | @override 66 | Widget build(BuildContext context) { 67 | return MaterialApp( 68 | title: title, 69 | theme: ThemeData.light(), 70 | darkTheme: ThemeData.dark(), 71 | themeMode: EasyDynamicTheme.of(context).themeMode, 72 | home: new MyHomePage(title: title,) 73 | ); 74 | } 75 | } 76 | ``` 77 | 78 | ### How to use predefined Themes 79 | 80 | You can use your own themes as follows: 81 | 82 | In the file `themes.dart` define your *Themes* 83 | 84 | ```dart 85 | import 'package:flutter/material.dart'; 86 | 87 | var lightThemeData = new ThemeData( 88 | primaryColor: Colors.blue, 89 | textTheme: new TextTheme(button: TextStyle(color: Colors.white70)), 90 | brightness: Brightness.light, 91 | accentColor: Colors.blue); 92 | 93 | var darkThemeData = ThemeData( 94 | primaryColor: Colors.blue, 95 | textTheme: new TextTheme(button: TextStyle(color: Colors.black54)), 96 | brightness: Brightness.dark, 97 | accentColor: Colors.blue); 98 | ``` 99 | 100 | And then in your `main.dart` file import your themes file and use them on **MaterialApp** attributes *theme* and *darkTheme* 101 | 102 | ```dart 103 | import 'package:flutter/material.dart'; 104 | import 'package:easy_dynamic_theme/easy_dynamic_theme.dart'; 105 | import 'theme.dart'; 106 | import 'home.dart'; 107 | 108 | void main() async { 109 | runApp( 110 | EasyDynamicThemeWidget( 111 | child: MyApp(), 112 | ), 113 | ); 114 | } 115 | 116 | class MyApp extends StatelessWidget { 117 | final String title = 'EDT - Example'; 118 | 119 | @override 120 | Widget build(BuildContext context) { 121 | return MaterialApp( 122 | title: title, 123 | theme: lightThemeData, 124 | darkTheme: darkThemeData, 125 | themeMode: EasyDynamicTheme.of(context).themeMode, 126 | home: new MyHomePage(title: title,) 127 | ); 128 | } 129 | } 130 | ``` 131 | 132 | ### How to change the ThemeMode in your app 133 | 134 | You can use the function **changeTheme** from anywhere in your app. 135 | 136 | This function have two optional parameters: *dynamic* and *dark*. 137 | If the value of *dynamic* is *true*, it takes precedence over *dark*. 138 | 139 | ```dart 140 | EasyDynamicTheme.of(context).changeTheme(); 141 | ``` 142 | 143 | ### How to get your app current theme 144 | 145 | #### Current app ThemeMode 146 | 147 | ```dart 148 | ThemeMode themeMode = EasyDynamicTheme.of(context).themeMode; 149 | ``` 150 | 151 | The above example will return a value of the *enum* used by **MaterialApp's** **ThemeMode** with one of the following values: 152 | 153 | **system** - *Use either the light or dark theme based on what the user has selected in the system settings.* 154 | 155 | **light** - *Always use the light mode regardless of system preference.* 156 | 157 | **dark** - *Always use the dark mode (if available) regardless of system preference.* 158 | 159 | #### Current Context brightness 160 | 161 | ```dart 162 | Brightness brightness = Theme.of(context).brightness; 163 | ``` 164 | 165 | Or if you want to know if your widget is dark mode based, you can achieve it with: 166 | 167 | ```dart 168 | bool isDarkModeOn = Theme.of(context).brightness == Brightness.dark; 169 | ``` 170 | 171 | ### What about some out-of-the-box widgets? 172 | 173 | #### Right now we have 174 | 175 | - **EasyDynamicThemeBtn**, which is (kind of) a *FlatButton* that displays the icon according to the current theme of your app and allows you to switch between them. 176 | - **EasyDynamicThemeSwitch**, which is a *Switch* widget, based on the current theme's brightness of your context and allows you to switch between **light/dark** them. 177 | - **EasyDynamicThemeAutoSwitch**, which is a *Switch* widget, based on the current theme of your app and allows you to prioritize (or not) your OS defined brightness. 178 | 179 | 180 | [buy_me_a_coffee]: https://www.buymeacoffee.com/rlazom 181 | [buy_me_a_coffee_badge]: https://img.shields.io/badge/donate-buymeacoffee-yellow?logo=buymeacoffee -------------------------------------------------------------------------------- /demo/easy_dynamic_theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/demo/easy_dynamic_theme.png -------------------------------------------------------------------------------- /demo/widgets.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/demo/widgets.gif -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled. 5 | 6 | version: 7 | revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 8 | channel: stable 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 17 | base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 18 | - platform: android 19 | create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 20 | base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 21 | - platform: ios 22 | create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 23 | base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 24 | - platform: linux 25 | create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 26 | base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 27 | - platform: macos 28 | create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 29 | base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 30 | - platform: web 31 | create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 32 | base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 33 | - platform: windows 34 | create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 35 | base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf 36 | 37 | # User provided section 38 | 39 | # List of Local paths (relative to this file) that should be 40 | # ignored by the migrate tool. 41 | # 42 | # Files that are not part of the templates will be ignored by default. 43 | unmanaged_files: 44 | - 'lib/main.dart' 45 | - 'ios/Runner.xcodeproj/project.pbxproj' 46 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # easy_dynamic_theme_example 2 | 3 | Demonstrates how to use the easy_dynamic_theme plugin. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/images/background.jpg -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = ""; 23 | dstSubfolderSpec = 10; 24 | files = ( 25 | ); 26 | name = "Embed Frameworks"; 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 9740EEB11CF90186004384FC /* Flutter */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 65 | ); 66 | name = Flutter; 67 | sourceTree = ""; 68 | }; 69 | 97C146E51CF9000F007C117D = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9740EEB11CF90186004384FC /* Flutter */, 73 | 97C146F01CF9000F007C117D /* Runner */, 74 | 97C146EF1CF9000F007C117D /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 97C146EF1CF9000F007C117D /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 97C146EE1CF9000F007C117D /* Runner.app */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 97C146F01CF9000F007C117D /* Runner */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 92 | 97C147021CF9000F007C117D /* Info.plist */, 93 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 94 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 95 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 96 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 97 | ); 98 | path = Runner; 99 | sourceTree = ""; 100 | }; 101 | /* End PBXGroup section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | 97C146ED1CF9000F007C117D /* Runner */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 107 | buildPhases = ( 108 | 9740EEB61CF901F6004384FC /* Run Script */, 109 | 97C146EA1CF9000F007C117D /* Sources */, 110 | 97C146EB1CF9000F007C117D /* Frameworks */, 111 | 97C146EC1CF9000F007C117D /* Resources */, 112 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 113 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 114 | ); 115 | buildRules = ( 116 | ); 117 | dependencies = ( 118 | ); 119 | name = Runner; 120 | productName = Runner; 121 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 122 | productType = "com.apple.product-type.application"; 123 | }; 124 | /* End PBXNativeTarget section */ 125 | 126 | /* Begin PBXProject section */ 127 | 97C146E61CF9000F007C117D /* Project object */ = { 128 | isa = PBXProject; 129 | attributes = { 130 | LastUpgradeCheck = 1020; 131 | ORGANIZATIONNAME = ""; 132 | TargetAttributes = { 133 | 97C146ED1CF9000F007C117D = { 134 | CreatedOnToolsVersion = 7.3.1; 135 | LastSwiftMigration = 1100; 136 | }; 137 | }; 138 | }; 139 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 140 | compatibilityVersion = "Xcode 9.3"; 141 | developmentRegion = en; 142 | hasScannedForEncodings = 0; 143 | knownRegions = ( 144 | en, 145 | Base, 146 | ); 147 | mainGroup = 97C146E51CF9000F007C117D; 148 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 149 | projectDirPath = ""; 150 | projectRoot = ""; 151 | targets = ( 152 | 97C146ED1CF9000F007C117D /* Runner */, 153 | ); 154 | }; 155 | /* End PBXProject section */ 156 | 157 | /* Begin PBXResourcesBuildPhase section */ 158 | 97C146EC1CF9000F007C117D /* Resources */ = { 159 | isa = PBXResourcesBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 163 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 164 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 165 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 166 | ); 167 | runOnlyForDeploymentPostprocessing = 0; 168 | }; 169 | /* End PBXResourcesBuildPhase section */ 170 | 171 | /* Begin PBXShellScriptBuildPhase section */ 172 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 173 | isa = PBXShellScriptBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | ); 177 | inputPaths = ( 178 | ); 179 | name = "Thin Binary"; 180 | outputPaths = ( 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | shellPath = /bin/sh; 184 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 185 | }; 186 | 9740EEB61CF901F6004384FC /* Run Script */ = { 187 | isa = PBXShellScriptBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | ); 191 | inputPaths = ( 192 | ); 193 | name = "Run Script"; 194 | outputPaths = ( 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | shellPath = /bin/sh; 198 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 199 | }; 200 | /* End PBXShellScriptBuildPhase section */ 201 | 202 | /* Begin PBXSourcesBuildPhase section */ 203 | 97C146EA1CF9000F007C117D /* Sources */ = { 204 | isa = PBXSourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 208 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXSourcesBuildPhase section */ 213 | 214 | /* Begin PBXVariantGroup section */ 215 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 216 | isa = PBXVariantGroup; 217 | children = ( 218 | 97C146FB1CF9000F007C117D /* Base */, 219 | ); 220 | name = Main.storyboard; 221 | sourceTree = ""; 222 | }; 223 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 224 | isa = PBXVariantGroup; 225 | children = ( 226 | 97C147001CF9000F007C117D /* Base */, 227 | ); 228 | name = LaunchScreen.storyboard; 229 | sourceTree = ""; 230 | }; 231 | /* End PBXVariantGroup section */ 232 | 233 | /* Begin XCBuildConfiguration section */ 234 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_ANALYZER_NONNULL = YES; 239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 240 | CLANG_CXX_LIBRARY = "libc++"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 244 | CLANG_WARN_BOOL_CONVERSION = YES; 245 | CLANG_WARN_COMMA = YES; 246 | CLANG_WARN_CONSTANT_CONVERSION = YES; 247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INFINITE_RECURSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 258 | CLANG_WARN_STRICT_PROTOTYPES = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = NO; 264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 265 | ENABLE_NS_ASSERTIONS = NO; 266 | ENABLE_STRICT_OBJC_MSGSEND = YES; 267 | GCC_C_LANGUAGE_STANDARD = gnu99; 268 | GCC_NO_COMMON_BLOCKS = YES; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 276 | MTL_ENABLE_DEBUG_INFO = NO; 277 | SDKROOT = iphoneos; 278 | SUPPORTED_PLATFORMS = iphoneos; 279 | TARGETED_DEVICE_FAMILY = "1,2"; 280 | VALIDATE_PRODUCT = YES; 281 | }; 282 | name = Profile; 283 | }; 284 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 285 | isa = XCBuildConfiguration; 286 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 287 | buildSettings = { 288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 289 | CLANG_ENABLE_MODULES = YES; 290 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 291 | ENABLE_BITCODE = NO; 292 | FRAMEWORK_SEARCH_PATHS = ( 293 | "$(inherited)", 294 | "$(PROJECT_DIR)/Flutter", 295 | ); 296 | INFOPLIST_FILE = Runner/Info.plist; 297 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 298 | LIBRARY_SEARCH_PATHS = ( 299 | "$(inherited)", 300 | "$(PROJECT_DIR)/Flutter", 301 | ); 302 | PRODUCT_BUNDLE_IDENTIFIER = com.mojosapp.easyDynamicThemeExample; 303 | PRODUCT_NAME = "$(TARGET_NAME)"; 304 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 305 | SWIFT_VERSION = 5.0; 306 | VERSIONING_SYSTEM = "apple-generic"; 307 | }; 308 | name = Profile; 309 | }; 310 | 97C147031CF9000F007C117D /* Debug */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ALWAYS_SEARCH_USER_PATHS = NO; 314 | CLANG_ANALYZER_NONNULL = YES; 315 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 316 | CLANG_CXX_LIBRARY = "libc++"; 317 | CLANG_ENABLE_MODULES = YES; 318 | CLANG_ENABLE_OBJC_ARC = YES; 319 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 320 | CLANG_WARN_BOOL_CONVERSION = YES; 321 | CLANG_WARN_COMMA = YES; 322 | CLANG_WARN_CONSTANT_CONVERSION = YES; 323 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 324 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 325 | CLANG_WARN_EMPTY_BODY = YES; 326 | CLANG_WARN_ENUM_CONVERSION = YES; 327 | CLANG_WARN_INFINITE_RECURSION = YES; 328 | CLANG_WARN_INT_CONVERSION = YES; 329 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 330 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 331 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 332 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 333 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 334 | CLANG_WARN_STRICT_PROTOTYPES = YES; 335 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 336 | CLANG_WARN_UNREACHABLE_CODE = YES; 337 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 338 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 339 | COPY_PHASE_STRIP = NO; 340 | DEBUG_INFORMATION_FORMAT = dwarf; 341 | ENABLE_STRICT_OBJC_MSGSEND = YES; 342 | ENABLE_TESTABILITY = YES; 343 | GCC_C_LANGUAGE_STANDARD = gnu99; 344 | GCC_DYNAMIC_NO_PIC = NO; 345 | GCC_NO_COMMON_BLOCKS = YES; 346 | GCC_OPTIMIZATION_LEVEL = 0; 347 | GCC_PREPROCESSOR_DEFINITIONS = ( 348 | "DEBUG=1", 349 | "$(inherited)", 350 | ); 351 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 352 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 353 | GCC_WARN_UNDECLARED_SELECTOR = YES; 354 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 355 | GCC_WARN_UNUSED_FUNCTION = YES; 356 | GCC_WARN_UNUSED_VARIABLE = YES; 357 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 358 | MTL_ENABLE_DEBUG_INFO = YES; 359 | ONLY_ACTIVE_ARCH = YES; 360 | SDKROOT = iphoneos; 361 | TARGETED_DEVICE_FAMILY = "1,2"; 362 | }; 363 | name = Debug; 364 | }; 365 | 97C147041CF9000F007C117D /* Release */ = { 366 | isa = XCBuildConfiguration; 367 | buildSettings = { 368 | ALWAYS_SEARCH_USER_PATHS = NO; 369 | CLANG_ANALYZER_NONNULL = YES; 370 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 371 | CLANG_CXX_LIBRARY = "libc++"; 372 | CLANG_ENABLE_MODULES = YES; 373 | CLANG_ENABLE_OBJC_ARC = YES; 374 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 375 | CLANG_WARN_BOOL_CONVERSION = YES; 376 | CLANG_WARN_COMMA = YES; 377 | CLANG_WARN_CONSTANT_CONVERSION = YES; 378 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 379 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 380 | CLANG_WARN_EMPTY_BODY = YES; 381 | CLANG_WARN_ENUM_CONVERSION = YES; 382 | CLANG_WARN_INFINITE_RECURSION = YES; 383 | CLANG_WARN_INT_CONVERSION = YES; 384 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 385 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 386 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 387 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 388 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 389 | CLANG_WARN_STRICT_PROTOTYPES = YES; 390 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 391 | CLANG_WARN_UNREACHABLE_CODE = YES; 392 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 393 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 394 | COPY_PHASE_STRIP = NO; 395 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 396 | ENABLE_NS_ASSERTIONS = NO; 397 | ENABLE_STRICT_OBJC_MSGSEND = YES; 398 | GCC_C_LANGUAGE_STANDARD = gnu99; 399 | GCC_NO_COMMON_BLOCKS = YES; 400 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 401 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 402 | GCC_WARN_UNDECLARED_SELECTOR = YES; 403 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 404 | GCC_WARN_UNUSED_FUNCTION = YES; 405 | GCC_WARN_UNUSED_VARIABLE = YES; 406 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 407 | MTL_ENABLE_DEBUG_INFO = NO; 408 | SDKROOT = iphoneos; 409 | SUPPORTED_PLATFORMS = iphoneos; 410 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 411 | TARGETED_DEVICE_FAMILY = "1,2"; 412 | VALIDATE_PRODUCT = YES; 413 | }; 414 | name = Release; 415 | }; 416 | 97C147061CF9000F007C117D /* Debug */ = { 417 | isa = XCBuildConfiguration; 418 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 419 | buildSettings = { 420 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 421 | CLANG_ENABLE_MODULES = YES; 422 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 423 | ENABLE_BITCODE = NO; 424 | FRAMEWORK_SEARCH_PATHS = ( 425 | "$(inherited)", 426 | "$(PROJECT_DIR)/Flutter", 427 | ); 428 | INFOPLIST_FILE = Runner/Info.plist; 429 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 430 | LIBRARY_SEARCH_PATHS = ( 431 | "$(inherited)", 432 | "$(PROJECT_DIR)/Flutter", 433 | ); 434 | PRODUCT_BUNDLE_IDENTIFIER = com.mojosapp.easyDynamicThemeExample; 435 | PRODUCT_NAME = "$(TARGET_NAME)"; 436 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 437 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 438 | SWIFT_VERSION = 5.0; 439 | VERSIONING_SYSTEM = "apple-generic"; 440 | }; 441 | name = Debug; 442 | }; 443 | 97C147071CF9000F007C117D /* Release */ = { 444 | isa = XCBuildConfiguration; 445 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 446 | buildSettings = { 447 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 448 | CLANG_ENABLE_MODULES = YES; 449 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 450 | ENABLE_BITCODE = NO; 451 | FRAMEWORK_SEARCH_PATHS = ( 452 | "$(inherited)", 453 | "$(PROJECT_DIR)/Flutter", 454 | ); 455 | INFOPLIST_FILE = Runner/Info.plist; 456 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 457 | LIBRARY_SEARCH_PATHS = ( 458 | "$(inherited)", 459 | "$(PROJECT_DIR)/Flutter", 460 | ); 461 | PRODUCT_BUNDLE_IDENTIFIER = com.mojosapp.easyDynamicThemeExample; 462 | PRODUCT_NAME = "$(TARGET_NAME)"; 463 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 464 | SWIFT_VERSION = 5.0; 465 | VERSIONING_SYSTEM = "apple-generic"; 466 | }; 467 | name = Release; 468 | }; 469 | /* End XCBuildConfiguration section */ 470 | 471 | /* Begin XCConfigurationList section */ 472 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 473 | isa = XCConfigurationList; 474 | buildConfigurations = ( 475 | 97C147031CF9000F007C117D /* Debug */, 476 | 97C147041CF9000F007C117D /* Release */, 477 | 249021D3217E4FDB00AE95B9 /* Profile */, 478 | ); 479 | defaultConfigurationIsVisible = 0; 480 | defaultConfigurationName = Release; 481 | }; 482 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 483 | isa = XCConfigurationList; 484 | buildConfigurations = ( 485 | 97C147061CF9000F007C117D /* Debug */, 486 | 97C147071CF9000F007C117D /* Release */, 487 | 249021D4217E4FDB00AE95B9 /* Profile */, 488 | ); 489 | defaultConfigurationIsVisible = 0; 490 | defaultConfigurationName = Release; 491 | }; 492 | /* End XCConfigurationList section */ 493 | }; 494 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 495 | } 496 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | easy_dynamic_theme_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/blur_container.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class BlurContainer extends StatelessWidget { 5 | final Widget child; 6 | 7 | const BlurContainer({Key? key, required this.child}) : super(key: key); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return ClipRect( 12 | child: Container( 13 | decoration: BoxDecoration(border: Border.all(width: 2)), 14 | child: BackdropFilter( 15 | filter: ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0), 16 | child: Padding( 17 | padding: const EdgeInsets.all(8.0), 18 | child: child, 19 | ), 20 | ), 21 | ), 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/lib/home.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:easy_dynamic_theme/easy_dynamic_theme.dart'; 3 | import 'package:easy_dynamic_theme_example/blur_container.dart'; 4 | 5 | class MyHomePage extends StatefulWidget { 6 | final String title; 7 | 8 | const MyHomePage({Key? key, required this.title}) : super(key: key); 9 | 10 | @override 11 | MyHomePageState createState() => MyHomePageState(); 12 | } 13 | 14 | class MyHomePageState extends State { 15 | int _counter = 0; 16 | 17 | @override 18 | initState() { 19 | super.initState(); 20 | } 21 | 22 | void _incrementCounter() { 23 | setState(() { 24 | _counter++; 25 | }); 26 | } 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return Scaffold( 31 | appBar: AppBar( 32 | title: Text(widget.title), 33 | ), 34 | body: Stack( 35 | alignment: Alignment.center, 36 | children: [ 37 | Image.asset( 38 | 'images/background.jpg', 39 | fit: BoxFit.cover, 40 | width: MediaQuery.of(context).size.width, 41 | ), 42 | Container( 43 | color: Theme.of(context).scaffoldBackgroundColor.withOpacity(0.6), 44 | ), 45 | Column( 46 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 47 | children: [ 48 | Column( 49 | mainAxisSize: MainAxisSize.min, 50 | children: [ 51 | BlurContainer( 52 | child: Column( 53 | mainAxisSize: MainAxisSize.min, 54 | children: [ 55 | EasyDynamicThemeSwitch(), 56 | const Text('EasyDynamicThemeSwitch'), 57 | ], 58 | ), 59 | ), 60 | const SizedBox( 61 | height: 16, 62 | ), 63 | BlurContainer( 64 | child: Column( 65 | mainAxisSize: MainAxisSize.min, 66 | children: [ 67 | EasyDynamicThemeBtn(), 68 | const Text('EasyDynamicThemeBtn'), 69 | ], 70 | ), 71 | ), 72 | const SizedBox( 73 | height: 16, 74 | ), 75 | BlurContainer( 76 | child: Column( 77 | mainAxisSize: MainAxisSize.min, 78 | children: [ 79 | EasyDynamicThemeAutoSwitch(), 80 | const Text('EasyDynamicThemeAutoSwitch'), 81 | ], 82 | ), 83 | ), 84 | ], 85 | ), 86 | BlurContainer( 87 | child: Column( 88 | mainAxisSize: MainAxisSize.min, 89 | children: [ 90 | Text( 91 | 'You have pushed the button this many times:', 92 | style: Theme.of(context).textTheme.titleMedium, 93 | textAlign: TextAlign.justify, 94 | ), 95 | Text( 96 | '$_counter', 97 | style: Theme.of(context).textTheme.headlineMedium, 98 | ), 99 | ], 100 | ), 101 | ), 102 | ], 103 | ), 104 | ], 105 | ), 106 | floatingActionButton: FloatingActionButton( 107 | onPressed: _incrementCounter, 108 | tooltip: 'Increment', 109 | child: Icon(Icons.add, 110 | color: Theme.of(context).textTheme.labelLarge?.color), 111 | ), 112 | ); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:easy_dynamic_theme/easy_dynamic_theme.dart'; 3 | import 'theme.dart'; 4 | import 'home.dart'; 5 | 6 | void main() async { 7 | runApp( 8 | EasyDynamicThemeWidget( 9 | child: const MyApp(), 10 | ), 11 | ); 12 | } 13 | 14 | class MyApp extends StatelessWidget { 15 | final String title = 'EDT - Example'; 16 | 17 | const MyApp({Key? key}) : super(key: key); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return MaterialApp( 22 | title: title, 23 | debugShowCheckedModeBanner: false, 24 | theme: lightThemeData, 25 | darkTheme: darkThemeData, 26 | themeMode: EasyDynamicTheme.of(context).themeMode, 27 | home: MyHomePage( 28 | title: title, 29 | ), 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example/lib/theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | var lightThemeData = ThemeData( 4 | primaryColor: Colors.blue, 5 | textTheme: const TextTheme( 6 | labelLarge: TextStyle(color: Colors.black54), 7 | ), 8 | brightness: Brightness.light, 9 | colorScheme: ColorScheme.fromSwatch().copyWith( 10 | secondary: Colors.blue, 11 | brightness: Brightness.light, 12 | ), 13 | ); 14 | 15 | var darkThemeData = ThemeData( 16 | primaryColor: Colors.blue, 17 | textTheme: const TextTheme( 18 | labelLarge: TextStyle(color: Colors.white70), 19 | ), 20 | brightness: Brightness.dark, 21 | colorScheme: ColorScheme.fromSwatch().copyWith( 22 | secondary: Colors.blue, 23 | brightness: Brightness.dark, 24 | ), 25 | ); 26 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: easy_dynamic_theme_example 2 | description: Demonstrates how to use the easy_dynamic_theme plugin. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | environment: 9 | sdk: ">=2.12.0 <3.0.0" 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | easy_dynamic_theme: 16 | # When depending on this package from a real application you should use: 17 | # easy_dynamic_theme: ^x.y.z 18 | # See https://dart.dev/tools/pub/dependencies#version-constraints 19 | # The example app is bundled with the plugin so we use a path dependency on 20 | # the parent directory to use the current plugin's version. 21 | path: ../ 22 | 23 | 24 | dev_dependencies: 25 | flutter_lints: ^2.0.1 26 | flutter_test: 27 | sdk: flutter 28 | 29 | # For information on the generic Dart part of this file, see the 30 | # following page: https://dart.dev/tools/pub/pubspec 31 | 32 | # The following section is specific to Flutter. 33 | flutter: 34 | 35 | # The following line ensures that the Material Icons font is 36 | # included with your application, so that you can use the icons in 37 | # the material Icons class. 38 | uses-material-design: true 39 | 40 | # To add assets to your application, add an assets section, like this: 41 | assets: 42 | - images/ -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter_test/flutter_test.dart'; 9 | 10 | import 'package:easy_dynamic_theme_example/main.dart'; 11 | 12 | void main() { 13 | testWidgets('Verify Platform version', (WidgetTester tester) async { 14 | // Build our app and trigger a frame. 15 | await tester.pumpWidget(const MyApp()); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rlazom/easy_dynamic_theme/44a4167e50e04a29a4257c19e559157b76e6208a/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | easy_dynamic_theme_example 18 | 19 | 20 | 21 | 24 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "easy_dynamic_theme_example", 3 | "short_name": "easy_dynamic_theme_example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "Demonstrates how to use the easy_dynamic_theme plugin.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /lib/easy_dynamic_theme.dart: -------------------------------------------------------------------------------- 1 | export 'package:easy_dynamic_theme/src/easy_dynamic_widget.dart'; 2 | export 'package:easy_dynamic_theme/src/widgets/easy_dynamic_theme_btn.dart'; 3 | export 'package:easy_dynamic_theme/src/widgets/easy_dynamic_theme_switch.dart'; 4 | export 'package:easy_dynamic_theme/src/widgets/easy_dynamic_theme_auto_switch.dart'; 5 | -------------------------------------------------------------------------------- /lib/src/easy_dynamic_widget.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/material.dart'; 3 | import 'services/shared_preferences_service.dart'; 4 | export 'widgets/easy_dynamic_theme_btn.dart'; 5 | export 'widgets/easy_dynamic_theme_switch.dart'; 6 | 7 | /// Global InheritedWidget to access the data of the plugin 8 | /// Current Theme related data or methods 9 | class EasyDynamicTheme extends InheritedWidget { 10 | final _EasyDynamicThemeWidgetState data; 11 | 12 | const EasyDynamicTheme({ 13 | Key? key, 14 | required this.data, 15 | required Widget child, 16 | }) : super(key: key, child: child); 17 | 18 | static _EasyDynamicThemeWidgetState of(BuildContext context) { 19 | return context.dependOnInheritedWidgetOfExactType()!.data; 20 | } 21 | 22 | @override 23 | bool updateShouldNotify(EasyDynamicTheme old) { 24 | return this != old; 25 | } 26 | } 27 | 28 | /// Widget that will contains the whole app 29 | class EasyDynamicThemeWidget extends StatefulWidget { 30 | final ThemeMode? initialThemeMode; 31 | final Widget child; 32 | 33 | EasyDynamicThemeWidget({Key? key, this.initialThemeMode, required this.child}) 34 | : super(key: key); 35 | 36 | @override 37 | _EasyDynamicThemeWidgetState createState() => _EasyDynamicThemeWidgetState(); 38 | } 39 | 40 | class _EasyDynamicThemeWidgetState extends State { 41 | ThemeMode? themeMode; 42 | late SharedPreferencesService _prefs; 43 | Future? fInit; 44 | 45 | @override 46 | initState() { 47 | super.initState(); 48 | fInit = _loadSharedPreferences(); 49 | } 50 | 51 | /// Loads the Shared Preferences data stored on your device to build the UI accordingly 52 | Future _loadSharedPreferences() async { 53 | _prefs = SharedPreferencesService(); 54 | if (widget.initialThemeMode != null) { 55 | themeMode = widget.initialThemeMode; 56 | _prefs.loadInstance(); 57 | return; 58 | } 59 | await _prefs.loadInstance(); 60 | bool? isDark = _prefs.isDark(); 61 | if (isDark != null) { 62 | themeMode = isDark ? ThemeMode.dark : ThemeMode.light; 63 | } 64 | } 65 | 66 | /// Change your current ThemeMode 67 | /// 68 | /// If you do not send any parameter it will toggle in the following order: 69 | /// 70 | /// dynamic -> light -> dark -> dynamic -> 71 | /// 72 | /// Or you can define boolean values for the parameters "[dynamic]" and/or "[dark]" 73 | /// 74 | /// If the value of "[dynamic]" is true, it takes precedence over "[dark]" 75 | void changeTheme({bool? dynamic, bool? dark}) { 76 | if (dynamic == null && dark == null) { 77 | _toggleTheme(); 78 | return; 79 | } 80 | 81 | ThemeMode? newThemeMode; 82 | bool forceDark = _prefs.isDark() ?? false; 83 | 84 | if (dark != null || dynamic != null) { 85 | forceDark = dark == null ? forceDark : dark; 86 | newThemeMode = (dynamic ?? false) 87 | ? ThemeMode.system 88 | : forceDark 89 | ? ThemeMode.dark 90 | : ThemeMode.light; 91 | } 92 | 93 | if (newThemeMode == ThemeMode.system) { 94 | _prefs.clearPref(SharePrefsAttribute.IS_DARK); 95 | } else { 96 | _prefs.setIsDark(forceDark); 97 | } 98 | 99 | setState(() { 100 | themeMode = newThemeMode; 101 | }); 102 | } 103 | 104 | /// Toggle from your current ThemeMode in the following order: 105 | /// 106 | /// dynamic -> light -> dark -> dynamic -> 107 | void _toggleTheme() { 108 | ThemeMode? currentThemeMode = themeMode; 109 | ThemeMode newThemeMode; 110 | bool? isNewThemeDark; 111 | 112 | if (currentThemeMode == ThemeMode.system) { 113 | newThemeMode = ThemeMode.light; 114 | isNewThemeDark = false; 115 | } else if (currentThemeMode == ThemeMode.light) { 116 | newThemeMode = ThemeMode.dark; 117 | isNewThemeDark = true; 118 | } else { 119 | newThemeMode = ThemeMode.system; 120 | isNewThemeDark = null; 121 | } 122 | 123 | if (isNewThemeDark == null) { 124 | _prefs.clearPref(SharePrefsAttribute.IS_DARK); 125 | } else { 126 | _prefs.setIsDark(isNewThemeDark); 127 | } 128 | 129 | setState(() { 130 | themeMode = newThemeMode; 131 | }); 132 | } 133 | 134 | @override 135 | Widget build(BuildContext context) { 136 | themeMode = themeMode ?? ThemeMode.system; 137 | return FutureBuilder( 138 | future: fInit, 139 | builder: (BuildContext context, AsyncSnapshot snapshot) { 140 | if (snapshot.connectionState == ConnectionState.done) { 141 | return EasyDynamicTheme( 142 | data: this, 143 | child: widget.child, 144 | ); 145 | } 146 | return Container( 147 | key: Key('loading'), 148 | ); 149 | }, 150 | ); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /lib/src/services/shared_preferences_service.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:shared_preferences/shared_preferences.dart'; 3 | 4 | enum SharePrefsAttribute { 5 | IS_DARK, 6 | } 7 | 8 | extension ParseToString on SharePrefsAttribute { 9 | String toShortString() { 10 | return this.toString().split('.').last.toLowerCase(); 11 | } 12 | } 13 | 14 | class SharedPreferencesService { 15 | SharedPreferences? _prefs; 16 | get prefs => _prefs; 17 | set prefs(instance) => _prefs = instance; 18 | 19 | Future loadInstance() async => _prefs = await SharedPreferences.getInstance(); 20 | 21 | bool? isDark() => 22 | _prefs!.getBool(SharePrefsAttribute.IS_DARK.toShortString()); 23 | 24 | setIsDark(bool value) => 25 | _prefs!.setBool(SharePrefsAttribute.IS_DARK.toShortString(), value); 26 | 27 | clearPref(SharePrefsAttribute attribute) => 28 | _prefs!.remove(attribute.toShortString()); 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/widgets/easy_dynamic_theme_auto_switch.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_dynamic_theme/easy_dynamic_theme.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class EasyDynamicThemeAutoSwitch extends StatelessWidget { 5 | @override 6 | Widget build(BuildContext context) { 7 | return Switch( 8 | key: Key('EasyDynamicThemeAutoSwitch'), 9 | value: EasyDynamicTheme.of(context).themeMode == ThemeMode.system, 10 | onChanged: (bool value) => 11 | EasyDynamicTheme.of(context).changeTheme(dynamic: value), 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/widgets/easy_dynamic_theme_btn.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../../easy_dynamic_theme.dart'; 3 | 4 | class EasyDynamicThemeBtn extends StatelessWidget { 5 | IconData _getIcon(BuildContext context) { 6 | var themeMode = EasyDynamicTheme.of(context).themeMode; 7 | return themeMode == ThemeMode.system 8 | ? Icons.brightness_auto 9 | : themeMode == ThemeMode.light 10 | ? Icons.brightness_high 11 | : Icons.brightness_4; 12 | } 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return RawMaterialButton( 17 | key: Key('EasyDynamicThemeBtn'), 18 | shape: CircleBorder(), 19 | onPressed: EasyDynamicTheme.of(context).changeTheme, 20 | child: Padding( 21 | padding: const EdgeInsets.all(12.0), 22 | child: Icon(_getIcon(context), 23 | color: Theme.of(context).textTheme.labelLarge!.color), 24 | ), 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/widgets/easy_dynamic_theme_switch.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_dynamic_theme/easy_dynamic_theme.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class EasyDynamicThemeSwitch extends StatelessWidget { 5 | @override 6 | Widget build(BuildContext context) { 7 | return Switch( 8 | key: Key('EasyDynamicThemeSwitch'), 9 | value: Theme.of(context).brightness == Brightness.dark, 10 | onChanged: (bool value) => 11 | EasyDynamicTheme.of(context).changeTheme(dark: value), 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: easy_dynamic_theme 2 | description: Automatically get your OS defined Theme (Dynamic), force your prefered one (Light / Dark) and persist your choice in the device. 3 | version: 2.3.1 4 | homepage: "https://github.com/rlazom/easy_dynamic_theme" 5 | 6 | environment: 7 | sdk: '>=2.12.0 <3.0.0' 8 | flutter: ">=1.20.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | shared_preferences: ^2.1.1 14 | 15 | dev_dependencies: 16 | flutter_lints: ^2.0.1 17 | flutter_test: 18 | sdk: flutter 19 | 20 | # Mock library for Dart 21 | mockito: ^5.4.0 -------------------------------------------------------------------------------- /test/src/default_app_wrapper.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_dynamic_theme/src/easy_dynamic_widget.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class DefaultAppWrapper extends StatelessWidget { 5 | final Widget child; 6 | final ThemeMode? initialThemeMode; 7 | 8 | const DefaultAppWrapper({ 9 | Key? key, 10 | required this.child, 11 | this.initialThemeMode, 12 | }) : super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return EasyDynamicThemeWidget( 17 | initialThemeMode: initialThemeMode, 18 | child: StatefulBuilder( 19 | builder: (BuildContext context, StateSetter setState) { 20 | return MaterialApp( 21 | theme: ThemeData.light(), 22 | darkTheme: ThemeData.dark(), 23 | themeMode: EasyDynamicTheme.of(context).themeMode, 24 | home: Scaffold( 25 | body: child, 26 | ), 27 | ); 28 | }, 29 | ), 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/src/easy_dynamic_theme_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:easy_dynamic_theme/easy_dynamic_theme.dart'; 4 | import 'package:mockito/mockito.dart'; 5 | import 'package:shared_preferences/shared_preferences.dart'; 6 | import 'package:easy_dynamic_theme/src/services/shared_preferences_service.dart'; 7 | import 'default_app_wrapper.dart'; 8 | 9 | class MockSharedPreferencesService extends Mock 10 | implements SharedPreferencesService {} 11 | 12 | void main() { 13 | SharedPreferencesService mockSharedPreferencesService; 14 | TestWidgetsFlutterBinding.ensureInitialized(); 15 | 16 | group('Check EasyDynamicTheme initialThemeMode feature', () { 17 | testWidgets( 18 | 'starts without define a initialThemeMode should start with ThemeMode.system', 19 | (WidgetTester tester) async { 20 | var appWdt = DefaultAppWrapper( 21 | child: EasyDynamicThemeBtn(), 22 | ); 23 | 24 | mockSharedPreferencesService = MockSharedPreferencesService(); 25 | SharedPreferences.setMockInitialValues({}); 26 | mockSharedPreferencesService.prefs = 27 | await SharedPreferences.getInstance(); 28 | 29 | await tester.pumpWidget(appWdt); 30 | expect(find.byKey(Key('loading')), findsOneWidget); 31 | 32 | await tester.pumpWidget(appWdt); 33 | 34 | expect(find.byKey(Key('loading')), findsNothing); 35 | expect(find.byKey(Key('EasyDynamicThemeBtn')), findsOneWidget); 36 | expect(find.byIcon(Icons.brightness_auto), findsOneWidget); 37 | }); 38 | 39 | testWidgets('starts with an initialThemeMode (ThemeMode.dark)', 40 | (WidgetTester tester) async { 41 | var appWdt = DefaultAppWrapper( 42 | initialThemeMode: ThemeMode.dark, 43 | child: EasyDynamicThemeBtn(), 44 | ); 45 | 46 | await tester.pumpWidget(appWdt); 47 | expect(find.byKey(Key('loading')), findsOneWidget); 48 | 49 | await tester.pumpWidget(appWdt); 50 | 51 | expect(find.byKey(Key('loading')), findsNothing); 52 | expect(find.byKey(Key('EasyDynamicThemeBtn')), findsOneWidget); 53 | expect(find.byIcon(Icons.brightness_4), findsOneWidget); 54 | }); 55 | 56 | testWidgets('starts with an initialThemeMode (ThemeMode.light)', 57 | (WidgetTester tester) async { 58 | var appWdt = DefaultAppWrapper( 59 | initialThemeMode: ThemeMode.light, 60 | child: EasyDynamicThemeBtn(), 61 | ); 62 | 63 | await tester.pumpWidget(appWdt); 64 | expect(find.byKey(Key('loading')), findsOneWidget); 65 | 66 | await tester.pumpWidget(appWdt); 67 | 68 | expect(find.byKey(Key('loading')), findsNothing); 69 | expect(find.byKey(Key('EasyDynamicThemeBtn')), findsOneWidget); 70 | expect(find.byIcon(Icons.brightness_high), findsOneWidget); 71 | }); 72 | 73 | testWidgets('starts with an initialThemeMode (ThemeMode.system)', 74 | (WidgetTester tester) async { 75 | var appWdt = DefaultAppWrapper( 76 | initialThemeMode: ThemeMode.system, 77 | child: EasyDynamicThemeBtn(), 78 | ); 79 | 80 | await tester.pumpWidget(appWdt); 81 | expect(find.byKey(Key('loading')), findsOneWidget); 82 | 83 | await tester.pumpWidget(appWdt); 84 | 85 | expect(find.byKey(Key('loading')), findsNothing); 86 | expect(find.byKey(Key('EasyDynamicThemeBtn')), findsOneWidget); 87 | expect(find.byIcon(Icons.brightness_auto), findsOneWidget); 88 | }); 89 | }); 90 | } 91 | -------------------------------------------------------------------------------- /test/src/services/shared_preferences_service_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_dynamic_theme/src/services/shared_preferences_service.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:shared_preferences/shared_preferences.dart'; 4 | 5 | void main() { 6 | group('Check SharedPreferencesService', () { 7 | SharedPreferencesService sharedPreferencesService; 8 | 9 | testWidgets('Class construction and initialization', 10 | (WidgetTester tester) async { 11 | SharedPreferences.setMockInitialValues({}); 12 | 13 | sharedPreferencesService = new SharedPreferencesService(); 14 | expect(sharedPreferencesService.prefs, null, 15 | reason: "Constructor initializes to null"); 16 | 17 | sharedPreferencesService.prefs = await SharedPreferences.getInstance(); 18 | expect(sharedPreferencesService.prefs != null, true, 19 | reason: "Constructor without parameters initializes to null"); 20 | }); 21 | 22 | testWidgets('should remove "IS_DARK" shared preference value', 23 | (WidgetTester tester) async { 24 | SharedPreferences.setMockInitialValues({'is_dark': true}); 25 | 26 | sharedPreferencesService = new SharedPreferencesService(); 27 | sharedPreferencesService.prefs = await SharedPreferences.getInstance(); 28 | 29 | expect(sharedPreferencesService.isDark(), true, 30 | reason: "The mock sharedPreference value was defined in 'true'"); 31 | 32 | sharedPreferencesService.clearPref(SharePrefsAttribute.IS_DARK); 33 | expect(sharedPreferencesService.isDark(), null, 34 | reason: "The mock sharedPreference value was deleted"); 35 | }); 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /test/src/widgets/easy_dynamic_theme_auto_switch_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_dynamic_theme/src/services/shared_preferences_service.dart'; 2 | import 'package:easy_dynamic_theme/easy_dynamic_theme.dart'; 3 | import 'package:mockito/mockito.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_test/flutter_test.dart'; 6 | import 'package:shared_preferences/shared_preferences.dart'; 7 | import '../default_app_wrapper.dart'; 8 | 9 | class MockSharedPreferencesService extends Mock 10 | implements SharedPreferencesService {} 11 | 12 | void main() { 13 | SharedPreferencesService mockSharedPreferencesService; 14 | 15 | group('Check EasyDynamicThemeAutoSwitch Widget', () { 16 | testWidgets('starts with a loading spinner', (WidgetTester tester) async { 17 | var appWdt = DefaultAppWrapper( 18 | child: EasyDynamicThemeAutoSwitch(), 19 | ); 20 | 21 | await tester.pumpWidget(appWdt); 22 | expect(find.byKey(Key('loading')), findsOneWidget); 23 | }); 24 | 25 | testWidgets('should show the Switch with value for the default case - true', 26 | (WidgetTester tester) async { 27 | mockSharedPreferencesService = MockSharedPreferencesService(); 28 | 29 | var appWdt = DefaultAppWrapper( 30 | child: EasyDynamicThemeAutoSwitch(), 31 | ); 32 | 33 | SharedPreferences.setMockInitialValues({}); 34 | mockSharedPreferencesService.prefs = 35 | await SharedPreferences.getInstance(); 36 | 37 | await tester.pumpWidget(appWdt); 38 | expect(find.byKey(Key('loading')), findsOneWidget); 39 | 40 | await tester.pumpWidget(appWdt); 41 | 42 | final Finder switchFinder = find.byKey(Key('EasyDynamicThemeAutoSwitch')); 43 | expect(switchFinder, findsOneWidget); 44 | expect(find.byKey(Key('loading')), findsNothing); 45 | 46 | final switchWdt = tester.widget(switchFinder); 47 | expect(switchWdt.value, true); 48 | }); 49 | 50 | testWidgets('should show the Switch with value - false', 51 | (WidgetTester tester) async { 52 | mockSharedPreferencesService = MockSharedPreferencesService(); 53 | 54 | var appWdt = DefaultAppWrapper( 55 | child: EasyDynamicThemeAutoSwitch(), 56 | ); 57 | 58 | SharedPreferences.setMockInitialValues({'is_dark': true}); 59 | mockSharedPreferencesService.prefs = 60 | await SharedPreferences.getInstance(); 61 | 62 | await tester.pumpWidget(appWdt); 63 | expect(find.byKey(Key('loading')), findsOneWidget); 64 | 65 | await tester.pumpWidget(appWdt); 66 | 67 | final Finder switchFinder = find.byKey(Key('EasyDynamicThemeAutoSwitch')); 68 | expect(switchFinder, findsOneWidget); 69 | expect(find.byKey(Key('loading')), findsNothing); 70 | 71 | Switch switchWdt = tester.widget(switchFinder); 72 | expect(switchWdt.value, false); 73 | }); 74 | 75 | testWidgets( 76 | 'should show the Switch with value "false" and toggle to "true"', 77 | (WidgetTester tester) async { 78 | mockSharedPreferencesService = MockSharedPreferencesService(); 79 | 80 | var appWdt = DefaultAppWrapper( 81 | child: EasyDynamicThemeAutoSwitch(), 82 | ); 83 | 84 | SharedPreferences.setMockInitialValues({'is_dark': false}); 85 | mockSharedPreferencesService.prefs = 86 | await SharedPreferences.getInstance(); 87 | 88 | await tester.pumpWidget(appWdt); 89 | expect(find.byKey(Key('loading')), findsOneWidget); 90 | 91 | await tester.pumpWidget(appWdt); 92 | 93 | final Finder switchFinder = find.byKey(Key('EasyDynamicThemeAutoSwitch')); 94 | expect(switchFinder, findsOneWidget); 95 | expect(find.byKey(Key('loading')), findsNothing); 96 | 97 | Switch switchWdt = tester.widget(switchFinder); 98 | expect(switchWdt.value, false); 99 | 100 | await tester.tap(switchFinder); 101 | await tester.pumpAndSettle(); 102 | 103 | switchWdt = tester.widget(switchFinder); 104 | expect(switchWdt.value, true); 105 | expect(mockSharedPreferencesService.isDark(), null); 106 | }); 107 | }); 108 | } 109 | -------------------------------------------------------------------------------- /test/src/widgets/easy_dynamic_theme_btn_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_dynamic_theme/src/services/shared_preferences_service.dart'; 2 | import 'package:easy_dynamic_theme/easy_dynamic_theme.dart'; 3 | import 'package:mockito/mockito.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_test/flutter_test.dart'; 6 | import 'package:shared_preferences/shared_preferences.dart'; 7 | import '../default_app_wrapper.dart'; 8 | 9 | class MockSharedPreferencesService extends Mock 10 | implements SharedPreferencesService {} 11 | 12 | void main() { 13 | SharedPreferencesService mockSharedPreferencesService; 14 | 15 | group('Check EasyDynamicThemeBtn Widget - UI', () { 16 | testWidgets('starts with a loading spinner', (WidgetTester tester) async { 17 | var appWdt = DefaultAppWrapper( 18 | child: EasyDynamicThemeBtn(), 19 | ); 20 | 21 | await tester.pumpWidget(appWdt); 22 | expect(find.byKey(Key('loading')), findsOneWidget); 23 | }); 24 | 25 | testWidgets('should show the default widget - automatic icon', 26 | (WidgetTester tester) async { 27 | mockSharedPreferencesService = MockSharedPreferencesService(); 28 | 29 | var appWdt = DefaultAppWrapper( 30 | child: EasyDynamicThemeBtn(), 31 | ); 32 | 33 | SharedPreferences.setMockInitialValues({}); 34 | mockSharedPreferencesService.prefs = 35 | await SharedPreferences.getInstance(); 36 | 37 | await tester.pumpWidget(appWdt); 38 | expect(find.byKey(Key('loading')), findsOneWidget); 39 | 40 | await tester.pumpWidget(appWdt); 41 | 42 | expect(find.byKey(Key('loading')), findsNothing); 43 | expect(find.byKey(Key('EasyDynamicThemeBtn')), findsOneWidget); 44 | expect(find.byIcon(Icons.brightness_auto), findsOneWidget); 45 | }); 46 | 47 | testWidgets('should show the default widget - light icon', 48 | (WidgetTester tester) async { 49 | mockSharedPreferencesService = MockSharedPreferencesService(); 50 | 51 | var appWdt = DefaultAppWrapper( 52 | child: EasyDynamicThemeBtn(), 53 | ); 54 | 55 | SharedPreferences.setMockInitialValues({'is_dark': false}); 56 | mockSharedPreferencesService.prefs = 57 | await SharedPreferences.getInstance(); 58 | 59 | await tester.pumpWidget(appWdt); 60 | expect(find.byKey(Key('loading')), findsOneWidget); 61 | 62 | await tester.pumpWidget(appWdt); 63 | 64 | expect(find.byKey(Key('loading')), findsNothing); 65 | expect(find.byKey(Key('EasyDynamicThemeBtn')), findsOneWidget); 66 | expect(find.byIcon(Icons.brightness_4), findsNothing); 67 | expect(find.byIcon(Icons.brightness_high), findsOneWidget); 68 | }); 69 | 70 | testWidgets('should show the default widget - light icon', 71 | (WidgetTester tester) async { 72 | mockSharedPreferencesService = MockSharedPreferencesService(); 73 | 74 | var materialApp = StatefulBuilder( 75 | builder: (BuildContext context, StateSetter setState) { 76 | return MaterialApp( 77 | themeMode: EasyDynamicTheme.of(context).themeMode, 78 | home: Scaffold( 79 | body: EasyDynamicThemeBtn(), 80 | ), 81 | ); 82 | }, 83 | ); 84 | 85 | var appWdt = EasyDynamicThemeWidget( 86 | child: materialApp, 87 | ); 88 | 89 | SharedPreferences.setMockInitialValues({'is_dark': true}); 90 | mockSharedPreferencesService.prefs = 91 | await SharedPreferences.getInstance(); 92 | 93 | await tester.pumpWidget(appWdt); 94 | expect(find.byKey(Key('loading')), findsOneWidget); 95 | 96 | await tester.pumpWidget(appWdt); 97 | 98 | expect(find.byKey(Key('loading')), findsNothing); 99 | expect(find.byKey(Key('EasyDynamicThemeBtn')), findsOneWidget); 100 | expect(find.byIcon(Icons.brightness_high), findsNothing); 101 | expect(find.byIcon(Icons.brightness_4), findsOneWidget); 102 | }); 103 | }); 104 | 105 | group('Check EasyDynamicThemeBtn Widget - Interactions', () { 106 | SharedPreferencesService sharedPreferencesService; 107 | 108 | testWidgets('test the interactions with the widget', 109 | (WidgetTester tester) async { 110 | sharedPreferencesService = new SharedPreferencesService(); 111 | 112 | var appWdt = DefaultAppWrapper( 113 | child: EasyDynamicThemeBtn(), 114 | ); 115 | 116 | SharedPreferences.setMockInitialValues({}); 117 | expect(sharedPreferencesService.prefs, null, 118 | reason: "Constructor initializes to null"); 119 | 120 | sharedPreferencesService.prefs = await SharedPreferences.getInstance(); 121 | expect(sharedPreferencesService.prefs != null, true, 122 | reason: "Constructor without parameters initializes to null"); 123 | 124 | await tester.pumpWidget(appWdt); 125 | expect(find.byKey(Key('loading')), findsOneWidget); 126 | 127 | await tester.pumpWidget(appWdt); 128 | 129 | final Finder btnWidgetFinder = find.byKey(Key('EasyDynamicThemeBtn')); 130 | final btnWdt = tester.widget(btnWidgetFinder); 131 | 132 | expect(find.byKey(Key('loading')), findsNothing); 133 | expect(btnWidgetFinder, findsOneWidget); 134 | expect(find.byIcon(Icons.brightness_auto), findsOneWidget); 135 | 136 | btnWdt.onPressed!(); 137 | await tester.pumpAndSettle(); 138 | 139 | expect(find.byKey(Key('loading')), findsNothing); 140 | expect(find.byIcon(Icons.brightness_high), findsOneWidget); 141 | 142 | btnWdt.onPressed!(); 143 | await tester.pumpAndSettle(); 144 | 145 | expect(sharedPreferencesService.isDark(), true); 146 | expect(find.byIcon(Icons.brightness_4), findsOneWidget); 147 | 148 | btnWdt.onPressed!(); 149 | await tester.pumpAndSettle(); 150 | 151 | expect(sharedPreferencesService.isDark(), null); 152 | expect(find.byIcon(Icons.brightness_auto), findsOneWidget); 153 | }); 154 | }); 155 | } 156 | -------------------------------------------------------------------------------- /test/src/widgets/easy_dynamic_theme_switch_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:easy_dynamic_theme/src/services/shared_preferences_service.dart'; 2 | import 'package:easy_dynamic_theme/easy_dynamic_theme.dart'; 3 | import 'package:mockito/mockito.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_test/flutter_test.dart'; 6 | import 'package:shared_preferences/shared_preferences.dart'; 7 | import '../default_app_wrapper.dart'; 8 | 9 | class MockSharedPreferencesService extends Mock 10 | implements SharedPreferencesService {} 11 | 12 | void main() { 13 | SharedPreferencesService mockSharedPreferencesService; 14 | 15 | group('Check EasyDynamicThemeSwitch Widget', () { 16 | testWidgets('starts with a loading spinner', (WidgetTester tester) async { 17 | var appWdt = DefaultAppWrapper( 18 | child: EasyDynamicThemeSwitch(), 19 | ); 20 | 21 | await tester.pumpWidget(appWdt); 22 | expect(find.byKey(Key('loading')), findsOneWidget); 23 | }); 24 | 25 | testWidgets( 26 | 'should show the Switch with value for the default case - false', 27 | (WidgetTester tester) async { 28 | mockSharedPreferencesService = MockSharedPreferencesService(); 29 | 30 | var appWdt = DefaultAppWrapper( 31 | child: EasyDynamicThemeSwitch(), 32 | ); 33 | 34 | SharedPreferences.setMockInitialValues({}); 35 | mockSharedPreferencesService.prefs = 36 | await SharedPreferences.getInstance(); 37 | 38 | await tester.pumpWidget(appWdt); 39 | expect(find.byKey(Key('loading')), findsOneWidget); 40 | 41 | await tester.pumpWidget(appWdt); 42 | 43 | final Finder switchFinder = find.byKey(Key('EasyDynamicThemeSwitch')); 44 | expect(switchFinder, findsOneWidget); 45 | expect(find.byKey(Key('loading')), findsNothing); 46 | 47 | final switchWdt = tester.widget(switchFinder); 48 | expect(switchWdt.value, false); 49 | }); 50 | 51 | testWidgets('should show the Switch with value - true', 52 | (WidgetTester tester) async { 53 | mockSharedPreferencesService = MockSharedPreferencesService(); 54 | 55 | var appWdt = DefaultAppWrapper( 56 | child: EasyDynamicThemeSwitch(), 57 | ); 58 | 59 | SharedPreferences.setMockInitialValues({'is_dark': true}); 60 | mockSharedPreferencesService.prefs = 61 | await SharedPreferences.getInstance(); 62 | 63 | await tester.pumpWidget(appWdt); 64 | expect(find.byKey(Key('loading')), findsOneWidget); 65 | 66 | await tester.pumpWidget(appWdt); 67 | 68 | final Finder switchFinder = find.byKey(Key('EasyDynamicThemeSwitch')); 69 | expect(switchFinder, findsOneWidget); 70 | expect(find.byKey(Key('loading')), findsNothing); 71 | 72 | Switch switchWdt = tester.widget(switchFinder); 73 | expect(switchWdt.value, true); 74 | }); 75 | 76 | testWidgets( 77 | 'should show the Switch with value "false" and toggle to "true"', 78 | (WidgetTester tester) async { 79 | mockSharedPreferencesService = MockSharedPreferencesService(); 80 | 81 | var appWdt = DefaultAppWrapper( 82 | child: EasyDynamicThemeSwitch(), 83 | ); 84 | 85 | SharedPreferences.setMockInitialValues({'is_dark': false}); 86 | mockSharedPreferencesService.prefs = 87 | await SharedPreferences.getInstance(); 88 | 89 | await tester.pumpWidget(appWdt); 90 | expect(find.byKey(Key('loading')), findsOneWidget); 91 | 92 | await tester.pumpWidget(appWdt); 93 | 94 | final Finder switchFinder = find.byKey(Key('EasyDynamicThemeSwitch')); 95 | expect(switchFinder, findsOneWidget); 96 | expect(find.byKey(Key('loading')), findsNothing); 97 | 98 | Switch switchWdt = tester.widget(switchFinder); 99 | expect(switchWdt.value, false); 100 | 101 | await tester.tap(switchFinder); 102 | await tester.pumpAndSettle(); 103 | 104 | switchWdt = tester.widget(switchFinder); 105 | expect(switchWdt.value, true); 106 | }); 107 | }); 108 | } 109 | --------------------------------------------------------------------------------