├── .github └── workflows │ ├── analyze_code_style.yml │ └── build.yml ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── README.md ├── fimber ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── doc │ └── colorize_fimber_test.PNG ├── example │ └── example.dart ├── lib │ ├── fimber.dart │ └── src │ │ ├── colorize.dart │ │ ├── data_size.dart │ │ ├── filename_format.dart │ │ └── fimber_base.dart ├── pubspec.yaml └── test │ ├── colorize_test.dart │ ├── custom_format_test.dart │ └── fimber_test.dart ├── fimber_io ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── example │ └── fimber_io_example.dart ├── lib │ ├── fimber_io.dart │ └── src │ │ ├── file_log.dart │ │ └── socket_log.dart ├── pubspec.yaml └── test │ ├── fileformat_test.dart │ └── socket_test.dart └── flutter_fimber ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── main │ ├── AndroidManifest.xml │ └── kotlin │ │ └── com │ │ └── magillus │ │ └── flutter_fimber │ │ └── FlutterFimberPlugin.kt │ └── test │ └── kotlin │ └── com │ └── magillus │ └── flutter_fimber │ └── FlutterFimberPluginTest.kt ├── example ├── .gitignore ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── magillus │ │ │ │ │ └── flutter_fimber_example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── integration_test │ └── plugin_integration_test.dart ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── 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 │ └── RunnerTests │ │ └── RunnerTests.swift ├── lib │ └── main.dart ├── linux │ ├── .gitignore │ ├── CMakeLists.txt │ ├── flutter │ │ ├── CMakeLists.txt │ │ ├── generated_plugin_registrant.cc │ │ ├── generated_plugin_registrant.h │ │ └── generated_plugins.cmake │ ├── main.cc │ ├── my_application.cc │ └── my_application.h ├── macos │ ├── .gitignore │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Podfile │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── app_icon_1024.png │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ └── app_icon_64.png │ │ ├── Base.lproj │ │ └── MainMenu.xib │ │ ├── Configs │ │ ├── AppInfo.xcconfig │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── Warnings.xcconfig │ │ ├── DebugProfile.entitlements │ │ ├── Info.plist │ │ ├── MainFlutterWindow.swift │ │ └── Release.entitlements ├── pubspec.yaml ├── test │ └── widget_test.dart └── windows │ ├── .gitignore │ ├── CMakeLists.txt │ ├── flutter │ ├── CMakeLists.txt │ ├── generated_plugin_registrant.cc │ ├── generated_plugin_registrant.h │ └── generated_plugins.cmake │ └── runner │ ├── CMakeLists.txt │ ├── Runner.rc │ ├── flutter_window.cpp │ ├── flutter_window.h │ ├── main.cpp │ ├── resource.h │ ├── resources │ └── app_icon.ico │ ├── runner.exe.manifest │ ├── utils.cpp │ ├── utils.h │ ├── win32_window.cpp │ └── win32_window.h ├── ios ├── .gitignore ├── Assets │ └── .gitkeep ├── Classes │ ├── FlutterFimberPlugin.h │ ├── FlutterFimberPlugin.m │ └── SwiftFlutterFimberPlugin.swift └── flutter_fimber.podspec ├── lib ├── flutter_fimber.dart ├── flutter_fimber_method_channel.dart ├── flutter_fimber_platform_interface.dart └── src │ └── flutter_fimber_base.dart ├── linux ├── CMakeLists.txt ├── flutter_fimber_plugin.cc └── include │ └── flutter_fimber │ └── flutter_fimber_plugin.h ├── macos ├── Classes │ └── FlutterFimberPlugin.swift └── flutter_fimber.podspec ├── pubspec.yaml ├── test ├── flutter_fimber_method_channel_test.dart └── flutter_fimber_test.dart └── windows ├── .gitignore ├── CMakeLists.txt ├── flutter_fimber_plugin.cpp ├── flutter_fimber_plugin.h ├── flutter_fimber_plugin_c_api.cpp └── include └── flutter_fimber └── flutter_fimber_plugin_c_api.h /.github/workflows/analyze_code_style.yml: -------------------------------------------------------------------------------- 1 | name: Analyze Code Style 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [ main ] 7 | pull_request: 8 | branches: [ main ] 9 | 10 | jobs: 11 | analyze_code_style: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - name: Setup Flutter 18 | id: flutter 19 | uses: DanTup/gh-actions/setup-flutter@master 20 | with: 21 | channel: 2.2.2 22 | 23 | - name: Install dependencies - Fimber 24 | run: cd fimber && flutter pub get 25 | 26 | - name: Analyze project source - Fimber 27 | run: cd fimber && flutter analyze --no-pub --no-fatal-infos --no-fatal-warnings 28 | 29 | - name: Install dependencies - Fimber IO 30 | run: cd fimber_io && flutter pub get 31 | 32 | - name: Analyze project source - Fimber 33 | run: cd fimber_io && flutter analyze --no-pub --no-fatal-infos --no-fatal-warnings 34 | 35 | - name: Install dependencies - Fimber 36 | run: cd flutter_fimber && flutter pub get 37 | 38 | - name: Analyze project source - Fimber 39 | run: cd flutter_fimber && flutter analyze --no-pub --no-fatal-infos --no-fatal-warnings 40 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # src: https://gist.github.com/rodydavis/bde9a9a8c2fcdcf3474c0f50248f2e3a 2 | 3 | name: Flutter Checks 4 | on: 5 | workflow_dispatch: 6 | pull_request: 7 | branches: 8 | - main 9 | push: 10 | branches: 11 | - main 12 | 13 | # Cancel jobs and just run the last one 14 | concurrency: 15 | group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/main' && github.run_number || github.ref }} 16 | cancel-in-progress: true 17 | 18 | jobs: 19 | unit_test: 20 | name: Unit Test 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v1 24 | - uses: subosito/flutter-action@v1 25 | with: 26 | flutter-version: '2.0.0' 27 | - name: Install dependencies - Fimber 28 | run: cd fimber && flutter pub get 29 | - run: cd fimber && flutter config --enable-web 30 | - name: Run tests - Fimber 31 | run: cd fimber && flutter test 32 | - name: Install dependencies - Fimber IO 33 | run: cd fimber_io && flutter pub get 34 | - run: cd fimber_io && flutter config --enable-web 35 | - name: Run tests - Fimber IO 36 | run: cd fimber_io && flutter test 37 | - name: Install dependencies - Flutter Fimber 38 | run: cd flutter_fimber && flutter pub get 39 | - run: cd flutter_fimber && flutter config --enable-web 40 | - name: Run tests - Fimber 41 | run: cd flutter_fimber && flutter test 42 | 43 | 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | **/.dart_tool/ 3 | .packages 4 | .pub/ 5 | *.iml 6 | .idea 7 | .metadata 8 | 9 | */fimber.iml 10 | */flutter_fimber.iml 11 | 12 | **/build/ 13 | **/ios/.generated/ 14 | **/ios/Flutter/Generated.xcconfig 15 | **/ios/Runner/GeneratedPluginRegistrant.* 16 | **/android/local.properties 17 | **/pubspec.lock 18 | .flutter-plugins* 19 | flutter_fimber/example/.flutter-plugins-dependencies 20 | flutter_fimber/example/ios/Flutter/flutter_export_environment.sh 21 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "fimber", 9 | "cwd": "fimber", 10 | "request": "launch", 11 | "type": "dart" 12 | }, 13 | { 14 | "name": "fimber_io", 15 | "cwd": "fimber_io", 16 | "request": "launch", 17 | "type": "dart" 18 | }, 19 | { 20 | "name": "flutter_fimber", 21 | "cwd": "flutter_fimber", 22 | "request": "launch", 23 | "type": "dart" 24 | }, 25 | { 26 | "name": "flutter_fimber (profile mode)", 27 | "cwd": "flutter_fimber", 28 | "request": "launch", 29 | "type": "dart", 30 | "flutterMode": "profile" 31 | }, 32 | { 33 | "name": "example", 34 | "cwd": "flutter_fimber/example", 35 | "request": "launch", 36 | "type": "dart" 37 | }, 38 | { 39 | "name": "example (profile mode)", 40 | "cwd": "flutter_fimber/example", 41 | "request": "launch", 42 | "type": "dart", 43 | "flutterMode": "profile" 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "MicroPython.executeButton": [ 3 | { 4 | "text": "▶", 5 | "tooltip": "Run", 6 | "alignment": "left", 7 | "command": "extension.executeFile", 8 | "priority": 3.5 9 | } 10 | ], 11 | "MicroPython.syncButton": [ 12 | { 13 | "text": "$(sync)", 14 | "tooltip": "sync", 15 | "alignment": "left", 16 | "command": "extension.execute", 17 | "priority": 4 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Analyze Code Style](https://github.com/magillus/flutter-fimber/actions/workflows/analyze_code_style.yml/badge.svg)](https://github.com/magillus/flutter-fimber/actions/workflows/analyze_code_style.yml) 2 | 3 | 4 | # fimber 5 | 6 | Extensible logging for Dart and Flutter. 7 | 8 | Package is based on famous Android logging library API - [Timber](https://github.com/JakeWharton/timber), this is library for simplify logging for Flutter. 9 | Using similar (as far as Dart lang allows) method API with same concepts for tree and planting logging tree. 10 | Also check out `flutter_fimber` which extends `fimber` to platform specific output and logging style. 11 | 12 | ## Getting Started 13 | 14 | To start add using it: 15 | ### Add `fimber` to `pubspec.yaml` 16 | 17 | #### pre-nullsafety 18 | 19 | ```yaml 20 | dependencies: 21 | fimber: ^0.6.6 22 | ``` 23 | - remember about import in file you plan to use Fimber 24 | 25 | ```dart 26 | import 'package:fimber/fimber.dart'; 27 | 28 | ``` 29 | 30 | ### Initialize logging tree on start of your application 31 | 32 | ```dart 33 | 34 | void main() { 35 | Fimber.plantTree(DebugTree()); 36 | // app code here ... 37 | 38 | // DebugTree options for time elapsed 39 | // by default DebugTree will output timestamp of the VM/Flutter app 40 | // to enable elapsed time since planting the tree log 41 | Fimber.plantTree(DebugTree.elapsed()); 42 | 43 | } 44 | 45 | ``` 46 | 47 | ### Start using it with static methods: 48 | 49 | ```dart 50 | import 'fimber.dart'; 51 | 52 | 53 | void main() { 54 | var parameter = 343.0; 55 | // use directly 56 | Fimber.i("Test message $argument"); 57 | Fimber.i("Extra error message", ex: Exception("Test thorwable")); 58 | 59 | // other log levels 60 | Fimber.d("DEBUG"); 61 | Fimber.v("VERBOSE"); 62 | Fimber.w("WARN"); 63 | 64 | try { 65 | throw Exception("Exception thrown"); 66 | } catch (e, stacktrace) { 67 | // providing `stacktrace` will better show where issue was thrown 68 | // if not provided will use log line location. 69 | Fimber.i("Error caught.", ex: e, stacktrace: stacktrace); 70 | } 71 | } 72 | 73 | ``` 74 | 75 | This will log the value and grab a TAG from stacktrace - that is little costly and if more logs will be done per second. 76 | 77 | ### Colorize logs - `ColorizeStyle` 78 | 79 | `useColors` property set to true will use default colors of the logos, you can change the mapping with in `colorizeMap` for `DebugTree` and `CustomFormatTree` 80 | The `useColors` by default is disabled. 81 | 82 | `ColorizeStyle` Aggregates list of `AnsiStyle` so you can combine styles together. 83 | 84 | `AnsiStyle` is combination of [`AnsiColor`](lib/colorize.dart) and [`AnsiSelection`](lib/colorize.dart) values 85 | 86 | Here is output of test output. 87 | 88 | ![Colorize Test Output](doc/colorize_fimber_test.PNG "Colorize Test Output") 89 | 90 | 91 | ### Create tagged version of Fimber 92 | 93 | And use its instance inside class, you can create logger for a dart file or for a class. 94 | 95 | ```dart 96 | var logger = FimberLog("MY_TAG"); 97 | 98 | void main() { 99 | 100 | logger.d("Test message"); 101 | } 102 | 103 | // or inside a class 104 | class SomeBloc { 105 | var logger = FimberLog("SomeBloc"); 106 | String fetchMessage() { 107 | logger.d("About to fetch some data."); 108 | //... 109 | var data = "load something"; 110 | 111 | logger.d("Retrived data (len = ${data.length}"); 112 | return data; 113 | } 114 | } 115 | ``` 116 | 117 | ### Use block function and pass method that uses logger. 118 | 119 | Use this function to log multiple messages with same tag, allows optional return value. 120 | Due to nature of auto-tag generation from stacktrace this block only does it once and create local FimberLog instance to pass into the anonymous method. 121 | 122 | ```dart 123 | var someMessage = "Test message from inside of block"; 124 | var output = Fimber.block((log) { 125 | log.d("Started block"); 126 | var i = 0; 127 | for (i = 0; i < 10; i++) { 128 | log.d("$someMessage, value: $i"); 129 | } 130 | log.i("End of block"); 131 | return i; 132 | }); 133 | ``` 134 | ### Custon line formatters 135 | 136 | Use custom line formatters to define your logging format. 137 | 138 | ```dart 139 | 140 | Fimber.plantTree(CustomFormatTree( 141 | logFormat: "${CustomFormatTree.TIME_ELAPSED_TOKEN} ${CustomFormatTree 142 | .MESSAGE_TOKEN} ${CustomFormatTree.TIME_STAMP_TOKEN}" 143 | )); 144 | ``` 145 | 146 | 147 | ## **Deprecated** moved to [`fimber_io`](https://pub.dev/packages/fimber_io/) package 148 | 149 | 150 | ```dart 151 | import 'package:fimber_io/fimber_io.dart'; 152 | 153 | Fimber.plantTree(FimberFileTree("my-Log-File.txt", 154 | logFormat: "${CustomFormatTree.TIME_ELAPSED_TOKEN} ${CustomFormatTree 155 | .MESSAGE_TOKEN} ${CustomFormatTree.TIME_STAMP_TOKEN}" 156 | )); 157 | ``` 158 | 159 | Use file log tree - the logs will go to a log file (Useful in DartVM apps). 160 | There are log rolling with size and time/date interval, so it is possible to setup log output per hour/day or any other time. 161 | 162 | see: `SizeRollingFileTree` or `TimedRollingFileTree` or use abstract class `RollingFileTree` to create your own version of rolling log file. 163 | 164 | 165 | ## TODO - road map 166 | 167 | - See [Issues on Github](https://github.com/magillus/flutter-fimber/issues) 168 | - Add Crashlytics plugin (maybe other remote logger tools) with [flutter_crashlytics](https://pub.dartlang.org/packages/flutter_crashlytics) 169 | 170 | ## Licence 171 | 172 | ``` 173 | 174 | Copyright 2018 Mateusz Perlak 175 | 176 | Licensed under the Apache License, Version 2.0 (the "License"); 177 | you may not use this file except in compliance with the License. 178 | You may obtain a copy of the License at 179 | 180 | http://www.apache.org/licenses/LICENSE-2.0 181 | 182 | Unless required by applicable law or agreed to in writing, software 183 | distributed under the License is distributed on an "AS IS" BASIS, 184 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 185 | See the License for the specific language governing permissions and 186 | limitations under the License. 187 | ``` 188 | -------------------------------------------------------------------------------- /fimber/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.7.0] - Dart 3 update. 2 | 3 | ## [0.6.6] - Bugfix for log matcher to include package not only files 4 | 5 | ## [0.6.5] - Bug fixes 6 | 7 | -- Update android dependencies to mavenCentral (from jcenter) [#116](https://github.com/magillus/flutter-fimber/issues/116) 8 | -- Fix for Log without exception but with stack trace [#115](https://github.com/magillus/flutter-fimber/issues/115) 9 | 10 | ## [0.6.4] - Added log line/path to file to [CustomFormatTree] 11 | 12 | -- Additional tokens for [CustomFormatTree] with filename/filepath log line and character. 13 | 14 | ## [0.6.1] - UnPlantableTree interface 15 | 16 | -- Added support for Unplantable Trees, that will have end of lifecycle method for cleanup after it is removed. 17 | 18 | ## [0.6.0] - Release of Nullsafety 19 | 20 | - Update to support null-safety 21 | 22 | ## [0.5.0-nullsafety.1] - first RC - Updated to support dart null-safety 23 | 24 | -- No other fixes/updates, just null-safety 25 | 26 | ## [0.4.4] - Fix for printing color when with level output 27 | 28 | Same as 0.4.3 - missed one usecase. 29 | 30 | ## [0.4.3] - Fix for printing color when with level output 31 | 32 | - [\#78 issue](https://github.com/magillus/flutter-fimber/issues/78) Fixing coloring output on the formatted log output. 33 | 34 | ## [0.4.2] - Fixed versioning 35 | 36 | - fixed versioning 37 | 38 | ## [0.4.1] - Bug fixes 39 | 40 | - [\#75 issue](https://github.com/magillus/flutter-fimber/issues/75) - Fix for TimedRollingFileTree missing passed logLevels and logFormat 41 | - [\#73 issue](https://github.com/magillus/flutter-fimber/issues/73) - Fix for mute levels list not being distinct 42 | 43 | ## [0.4.0] - Release of Fimber ready for Web (JS/FlutterWeb) 44 | 45 | - Moving File loggers to separate [`fimber_io`](https://pub.dev/packages/fimber_io/) package 46 | - Clean up 47 | 48 | ## [0.4.0-dev] - Removing dependency on dart::io. 49 | 50 | - If want to use File loggers use [`fimber_io`](https://pub.dev/packages/fimber_io/) package 51 | 52 | ## [0.3.3] - Deprecating dart:io dependency 53 | 54 | - Removing FileLogging and moving it to separate package: `fimber_io` 55 | - 0.4.0 version will remove dependency on dart::io - so that Fimber can be used in Web projects. 56 | 57 | ## [0.3.2] - Bug fix for Time rolling tree. 58 | 59 | - [\#52 issue](https://github.com/magillus/flutter-fimber/issues/52) Fix for check of new file format based on timeSpan intervals. 60 | 61 | ## [0.3.1] - Bug fixes around File rolling tree 62 | 63 | - initialize `outputFileName` variable by [@sceee](https://github.com/sceee) 64 | - removed unnecessary async that caused SizeRollingFileTree constructor to not construct the first logfile correctly before writes to the uninitialized filename could happen by [@sceee](https://github.com/sceee) 65 | 66 | ## [0.3.0] - Code styles updates and bug fixes 67 | 68 | - Code styles updates based on pedantic lint rules. 69 | - bug fix for TAG generation taking from correct stacktrace location = index 4. 70 | 71 | ## [0.2.1] - Auto create directory for log files 72 | 73 | ## [0.2.0] - Colorize logs 74 | 75 | - Added ANSI colorized option for `DebugTree` and `CustomFormatTree` (by default it is disabled) 76 | - `AnsiStyle` classes as extra for adding any colorful output for console. 77 | 78 | ## [0.1.11] - FileLog bugfix 79 | 80 | - FileLog bug fix for conflicts on file append. 81 | - FileLog uses flush buffer as temporary storage and writes to disk in 2 cases: 1 every 500ms and when ever buffer size exceeds 1kB. 82 | - Added unit tests for new bug. 83 | - docs update 84 | 85 | ## [0.1.10] - FileLog append fix, mute levels 86 | 87 | - bug fix for file log bug where new lines were overriding file not append lines. 88 | - Added log level muting from `Fimber.mute` and `Fimber.unmute` 89 | 90 | ## [0.1.9] - CustomFormatTree and FileLogTree 91 | 92 | - Custom format tree and File logging tree based on custom format. This will allow DartVM apps to output to defined file. 93 | 94 | ## [0.1.8] - Support for stacktrace optional parameter 95 | 96 | - Stacktrace optional parameter after adding `ex` can be provided from `try catch` block's second parameter 97 | ```dart 98 | try { 99 | ... 100 | } catch (ex, stacktrace) { 101 | Fimber.e("log message", ex:ex, stacktrace: stacktrace); 102 | } 103 | 104 | ``` 105 | ## [0.1.7] - Changed the `ex` class 106 | 107 | - Accepting dynamic (any class) on `ex` property of Logger. 108 | This allows to pass Error or Exception or any other value to log statement - `toString()` is used for printout 109 | 110 | ## [0.1.6] - DebugTree time options 111 | 112 | - Added Elapsed time option for debug tree logging (useful for server side/dart vm logging) 113 | - Added Time option for debug tree 114 | 115 | ## [0.1.5] - bug fixes 116 | 117 | - Bug fix for log tag auto creation inside constructor. 118 | - Added tests for factory method logging after constructor log tag fix. 119 | 120 | ## [0.1.4] - iOS exception stacktrace logging 121 | 122 | - no update on fimber, only mirror update for flutter_fimber iOS plugin 123 | 124 | ## [0.1.3] - iOS plugin part for logging 125 | 126 | - Added support for iOS log output. 127 | - Un-plant tree option. 128 | - Block function operation. 129 | 130 | ## [0.1.2] - only dart package form `fimber` 131 | 132 | - Small changes around packaging and removing any flutter references. 133 | - Revert to print from debugPrint for dart only support. 134 | - DebugTree got printLog method to override to support other solution to print formatted log line tou output stream, will be helpful in AndroidDebugTree (for example). 135 | - Updates to stacktrace dumping for DebugTree and added method to extract stacktrace. 136 | 137 | ## [0.1.1] - Small updates 138 | 139 | Small updates 140 | 141 | ## [0.1.0] - First Version 142 | 143 | Initial version with Fimber debugging and DebugTree 144 | -------------------------------------------------------------------------------- /fimber/README.md: -------------------------------------------------------------------------------- 1 | # fimber 2 | 3 | Extensible logging for Dart and Flutter. 4 | 5 | Package is based on famous Android logging library API - [Timber](https://github.com/JakeWharton/timber), this is library for simplify logging for Flutter. 6 | Using similar (as far as Dart lang allows) method API with same concepts for tree and planting logging tree. 7 | Also check out `flutter_fimber` which extends `fimber` to platform specific output and logging style. 8 | 9 | ## Getting Started 10 | 11 | To start add using it: 12 | ### Add `fimber` to `pubspec.yaml` 13 | 14 | #### pre-nullsafety 15 | 16 | ```yaml 17 | dependencies: 18 | fimber: ^0.7.0 19 | ``` 20 | - remember about import in file you plan to use Fimber 21 | 22 | ```dart 23 | import 'package:fimber/fimber.dart'; 24 | 25 | ``` 26 | 27 | ### Initialize logging tree on start of your application 28 | 29 | ```dart 30 | 31 | void main() { 32 | Fimber.plantTree(DebugTree()); 33 | // app code here ... 34 | 35 | // DebugTree options for time elapsed 36 | // by default DebugTree will output timestamp of the VM/Flutter app 37 | // to enable elapsed time since planting the tree log 38 | Fimber.plantTree(DebugTree.elapsed()); 39 | 40 | } 41 | 42 | ``` 43 | 44 | ### Remove a tree from logging 45 | 46 | If the `Tree` implements `UnPlantableTree` interface, its methods will be called. 47 | 48 | ```dart 49 | 50 | void main() { 51 | var myDebugTree = DebugTree(); 52 | 53 | Fimber.plantTree(myDebugTree; 54 | 55 | /// Do something 56 | 57 | Fimber.unplantTree(myDebugTree); 58 | 59 | } 60 | 61 | ### Start using it with static methods: 62 | 63 | ```dart 64 | import 'fimber.dart'; 65 | 66 | 67 | void main() { 68 | var parameter = 343.0; 69 | // use directly 70 | Fimber.i("Test message $argument"); 71 | Fimber.i("Extra error message", ex: Exception("Test thorwable")); 72 | 73 | // other log levels 74 | Fimber.d("DEBUG"); 75 | Fimber.v("VERBOSE"); 76 | Fimber.w("WARN"); 77 | 78 | try { 79 | throw Exception("Exception thrown"); 80 | } catch (e, stacktrace) { 81 | // providing `stacktrace` will better show where issue was thrown 82 | // if not provided will use log line location. 83 | Fimber.i("Error caught.", ex: e, stacktrace: stacktrace); 84 | } 85 | } 86 | 87 | ``` 88 | 89 | This will log the value and grab a TAG from stacktrace - that is little costly and if more logs will be done per second. 90 | 91 | ### Colorize logs - `ColorizeStyle` 92 | 93 | `useColors` property set to true will use default colors of the logos, you can change the mapping with in `colorizeMap` for `DebugTree` and `CustomFormatTree` 94 | The `useColors` by default is disabled. 95 | 96 | `ColorizeStyle` Aggregates list of `AnsiStyle` so you can combine styles together. 97 | 98 | `AnsiStyle` is combination of [`AnsiColor`](lib/colorize.dart) and [`AnsiSelection`](lib/colorize.dart) values 99 | 100 | Here is output of test output. 101 | 102 | ![Colorize Test Output](doc/colorize_fimber_test.PNG "Colorize Test Output") 103 | 104 | ### CustomFormatTree format your line of code 105 | 106 | Use any of the Tokens at [CustomFormatTree] class to configure the log lines. 107 | 108 | more at file 109 | ```dart 110 | 111 | /// Format token for time stamp 112 | static const String timeStampToken = "{TIME_STAMP}"; 113 | 114 | /// Format token for time elapsed 115 | static const String timeElapsedToken = "{TIME_ELAPSED}"; 116 | 117 | /// Format token for log level character 118 | static const String levelToken = "{LEVEL}"; 119 | 120 | /// Format token for log tag 121 | static const String tagToken = "{TAG}"; 122 | 123 | /// Format token for main log message 124 | static const String messageToken = "{MESSAGE}"; 125 | 126 | /// Format token for exception message 127 | static const String exceptionMsgToken = "{EX_MSG}"; 128 | 129 | /// Format token for exception's stacktrace 130 | static const String exceptionStackToken = "{EX_STACK}"; 131 | 132 | /// Format token for file path. 133 | static const String filePathToken = "{FILE_PATH}"; 134 | 135 | /// Format token for file name. 136 | static const String fileNameToken = "{FILE_NAME}"; 137 | 138 | /// Format token for file's line number 139 | static const String lineNumberToken = "{LINE_NUMBER}"; 140 | 141 | /// Format token for character index on the line 142 | static const String charAtIndexToken = "{CHAR_INDEX}"; 143 | ``` 144 | 145 | 146 | ### Create tagged version of Fimber 147 | 148 | And use its instance inside class, you can create logger for a dart file or for a class. 149 | 150 | ```dart 151 | var logger = FimberLog("MY_TAG"); 152 | 153 | void main() { 154 | 155 | logger.d("Test message"); 156 | } 157 | 158 | // or inside a class 159 | class SomeBloc { 160 | var logger = FimberLog("SomeBloc"); 161 | String fetchMessage() { 162 | logger.d("About to fetch some data."); 163 | //... 164 | var data = "load something"; 165 | 166 | logger.d("Retrived data (len = ${data.length}"); 167 | return data; 168 | } 169 | } 170 | ``` 171 | 172 | ### Use block function and pass method that uses logger. 173 | 174 | Use this function to log multiple messages with same tag, allows optional return value. 175 | Due to nature of auto-tag generation from stacktrace this block only does it once and create local FimberLog instance to pass into the anonymous method. 176 | 177 | ```dart 178 | var someMessage = "Test message from inside of block"; 179 | var output = Fimber.block((log) { 180 | log.d("Started block"); 181 | var i = 0; 182 | for (i = 0; i < 10; i++) { 183 | log.d("$someMessage, value: $i"); 184 | } 185 | log.i("End of block"); 186 | return i; 187 | }); 188 | ``` 189 | 190 | ## **Deprecated** moved to [`fimber_io`](https://pub.dev/packages/fimber_io/) package 191 | 192 | ### Custom line formatters 193 | 194 | Use custom line formatters to define your logging format. 195 | 196 | ```dart 197 | import 'package:fimber_io/fimber_io.dart'; 198 | 199 | ... 200 | 201 | Fimber.plantTree(FimberFileTree("my-Log-File.txt", 202 | logFormat: "${CustomFormatTree.timeElapsedToken} ${CustomFormatTree 203 | .messageToken} ${CustomFormatTree.timeStampToken}" 204 | )); 205 | ``` 206 | 207 | Use file log tree - the logs will go to a log file (Useful in DartVM apps). 208 | There are log rolling with size and time/date interval, so it is possible to setup log output per hour/day or any other time. 209 | 210 | see: `SizeRollingFileTree` or `TimedRollingFileTree` or use abstract class `RollingFileTree` to create your own version of rolling log file. 211 | 212 | 213 | ## TODO - road map 214 | 215 | - See [Issues on Github](https://github.com/magillus/flutter-fimber/issues) 216 | - Add Crashlytics plugin (maybe other remote logger tools) with [flutter_crashlytics](https://pub.dartlang.org/packages/flutter_crashlytics) 217 | 218 | ## Licence 219 | 220 | ``` 221 | 222 | Copyright 2018 Mateusz Perlak 223 | 224 | Licensed under the Apache License, Version 2.0 (the "License"); 225 | you may not use this file except in compliance with the License. 226 | You may obtain a copy of the License at 227 | 228 | http://www.apache.org/licenses/LICENSE-2.0 229 | 230 | Unless required by applicable law or agreed to in writing, software 231 | distributed under the License is distributed on an "AS IS" BASIS, 232 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 233 | See the License for the specific language governing permissions and 234 | limitations under the License. 235 | ``` -------------------------------------------------------------------------------- /fimber/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lint/package.yaml 2 | 3 | linter: 4 | rules: 5 | always_use_package_imports: false 6 | prefer_relative_imports: true -------------------------------------------------------------------------------- /fimber/doc/colorize_fimber_test.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/fimber/doc/colorize_fimber_test.PNG -------------------------------------------------------------------------------- /fimber/example/example.dart: -------------------------------------------------------------------------------- 1 | import 'package:fimber/fimber.dart'; 2 | 3 | void main() { 4 | // plant a tree - DebugTree() 5 | Fimber.plantTree(DebugTree()); 6 | 7 | Fimber.d("Test message", ex: Exception("test error")); 8 | const parameter = 100.0; 9 | Fimber.w("Test message with parameter: $parameter"); 10 | 11 | final logger = FimberLog("MY_TAG"); 12 | logger.d("Test message", ex: Exception("test error")); 13 | logger.w("Test message with parameter: $parameter"); 14 | 15 | try { 16 | throw Exception("Exception thrown"); 17 | // ignore: avoid_catches_without_on_clauses 18 | } catch (e, stacktrace) { 19 | // providing stacktrace will better show where issue was thrown 20 | Fimber.i("Error caught.", ex: e, stacktrace: stacktrace); 21 | } 22 | // save time without auto tag generation on each call in call block. 23 | Fimber.withTag("TEST BLOCK", (log) { 24 | log.d("Started block"); 25 | for (var i = 0; i >= 1; i++) { 26 | log.d("value: $i"); 27 | } 28 | log.i("End of block"); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /fimber/lib/fimber.dart: -------------------------------------------------------------------------------- 1 | export 'package:fimber/src/colorize.dart'; 2 | export 'package:fimber/src/data_size.dart'; 3 | export 'package:fimber/src/filename_format.dart'; 4 | export 'package:fimber/src/fimber_base.dart'; 5 | -------------------------------------------------------------------------------- /fimber/lib/src/data_size.dart: -------------------------------------------------------------------------------- 1 | /// Data size helper to help to calculate bytes/kilobytes, etc... 2 | class DataSize { 3 | /// Kilo bytes value in bytes 4 | static const bytesInKilo = 1024; 5 | 6 | /// Mega bytes value in bytes 7 | static const byteInMega = bytesInKilo * bytesInKilo; 8 | 9 | /// Giga bytes value in bytes 10 | static const bytesInGiga = byteInMega * bytesInKilo; 11 | 12 | /// Tera bytes value in bytes 13 | static const bytesInTera = bytesInGiga * bytesInKilo; 14 | 15 | /// Real size in bytes. 16 | int realSize = 0; 17 | 18 | /// Create DataSize object with predefined size as optional. 19 | DataSize({ 20 | int kilobytes = 0, 21 | int megabytes = 0, 22 | int gigabytes = 0, 23 | int terabytes = 0, 24 | int bytes = 0, 25 | }) { 26 | realSize = bytes; 27 | realSize += kilobytes * bytesInKilo; 28 | realSize += megabytes * byteInMega; 29 | realSize += gigabytes * bytesInGiga; 30 | realSize += terabytes * bytesInTera; 31 | } 32 | 33 | @override 34 | String toString() { 35 | if (realSize / bytesInTera > 0) { 36 | return "${realSize / bytesInTera} TB"; 37 | } else if (realSize / bytesInGiga > 0) { 38 | return "${realSize / bytesInGiga} GB"; 39 | } else if (realSize / byteInMega > 0) { 40 | return "${realSize / byteInMega} MB"; 41 | } else if (realSize / bytesInKilo > 0) { 42 | return "${realSize / bytesInKilo} KB"; 43 | } 44 | return "$realSize B"; 45 | } 46 | 47 | /// Creates DataSize object with bytes value. 48 | factory DataSize.bytes(int value) { 49 | return DataSize(bytes: value); 50 | } 51 | 52 | /// Creates DataSize object with kilo bytes value. 53 | factory DataSize.kilo(int value) { 54 | return DataSize(kilobytes: value); 55 | } 56 | 57 | /// Creates DataSize object with mega bytes value. 58 | factory DataSize.mega(int value) { 59 | return DataSize(megabytes: value); 60 | } 61 | 62 | /// Creates DataSize object with giga bytes value. 63 | factory DataSize.giga(int value) { 64 | return DataSize(gigabytes: value); 65 | } 66 | 67 | /// Creates DataSize object with tera bytes value. 68 | factory DataSize.tera(int value) { 69 | return DataSize(terabytes: value); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /fimber/lib/src/filename_format.dart: -------------------------------------------------------------------------------- 1 | /// File formatting with dates for rotation date logging 2 | /// with TimedRollingFileTree. 3 | /// 4 | class LogFileNameFormatter { 5 | static const _year2charToken = "YY"; 6 | static const _fullYearToken = "YYYY"; 7 | static const _month2charToken = "MM"; 8 | static const _month3charToken = "MMM"; 9 | static const _monthToken = "MMMM"; 10 | static const _dayToken = "DD"; 11 | static const _dayOfWeekToken = "ddd"; 12 | static const _hour12Token = "hh"; 13 | static const _hour24Token = "HH"; 14 | static const _hourPmAmToken = "aa"; 15 | static const _minutesToken = "mm"; 16 | static const _secondsToken = "SS"; 17 | 18 | static const _dayFormat = "$_fullYearToken$_month2charToken$_dayToken"; 19 | static const _timeFormat = "$_hour24Token$_minutesToken$_secondsToken"; 20 | 21 | /// Filename format for files created with this formatter. 22 | String filenameFormat = "log_YYMMDD-HH.txt"; 23 | 24 | /// Creates LogFileNameFormatter with given format or by default 25 | LogFileNameFormatter({this.filenameFormat = "log_YYMMDD-HH.txt"}); 26 | 27 | /// Factory method to create date and time filename formatter with 28 | /// prefix and postfix. 29 | factory LogFileNameFormatter.full({ 30 | String prefix = "log_", 31 | String postfix = ".txt", 32 | }) { 33 | return LogFileNameFormatter( 34 | filenameFormat: "$prefix${_dayFormat}_$_timeFormat$postfix", 35 | ); 36 | } 37 | 38 | /// Factory method to create hourly filename formatter with 39 | /// prefix and postifx. 40 | factory LogFileNameFormatter.hourly({ 41 | String prefix = "log_", 42 | String postfix = ".txt", 43 | }) { 44 | return LogFileNameFormatter( 45 | filenameFormat: "$prefix${_dayFormat}_$_dayToken$postfix", 46 | ); 47 | } 48 | 49 | /// Factory method to create daily filename formatter with 50 | /// prefix and postfix 51 | factory LogFileNameFormatter.daily({ 52 | String prefix = "log_", 53 | String postfix = ".txt", 54 | }) { 55 | return LogFileNameFormatter( 56 | filenameFormat: "$prefix${_dayFormat}_$_dayToken$postfix", 57 | ); 58 | } 59 | 60 | /// Factory method to create weekly filename formatter with 61 | /// prefix and postfix 62 | factory LogFileNameFormatter.weekly({ 63 | String prefix = "log_", 64 | String postfix = ".txt", 65 | }) { 66 | return LogFileNameFormatter(filenameFormat: "$prefix$_dayFormat$postfix"); 67 | } 68 | 69 | /// Formats date time based on defined formatter 70 | String format(DateTime dateTime) { 71 | final name = filenameFormat; 72 | return name 73 | .replaceAll(_fullYearToken, dateTime.year.toString().padLeft(4, '0')) 74 | .replaceAll( 75 | _year2charToken, 76 | (dateTime.year % 1000).toString().padLeft(2, '0'), 77 | ) 78 | .replaceAll(_monthToken, _month(dateTime.month)) 79 | .replaceAll(_month3charToken, _month3(dateTime.month)) 80 | .replaceAll(_month2charToken, dateTime.month.toString().padLeft(2, '0')) 81 | .replaceAll(_dayToken, dateTime.day.toString().padLeft(2, '0')) 82 | .replaceAll(_dayOfWeekToken, _dayOfWeek(dateTime.weekday)) 83 | .replaceAll( 84 | _hour12Token, 85 | (dateTime.hour % 12).toString().padLeft(2, '0'), 86 | ) 87 | .replaceAll(_hour24Token, dateTime.hour.toString().padLeft(2, '0')) 88 | .replaceAll(_hourPmAmToken, _amPmHour(dateTime.hour)) 89 | .replaceAll( 90 | _hourPmAmToken.toUpperCase(), 91 | _amPmHour(dateTime.hour).toUpperCase(), 92 | ) 93 | .replaceAll(_secondsToken, dateTime.second.toString().padLeft(2, '0')) 94 | .replaceAll(_minutesToken, dateTime.minute.toString().padLeft(2, '0')); 95 | } 96 | 97 | String _amPmHour(int hour) { 98 | if (hour > 12) { 99 | return "pm"; 100 | } else { 101 | return "am"; 102 | } 103 | } 104 | 105 | String _dayOfWeek(int day) { 106 | switch (day) { 107 | case DateTime.monday: 108 | return "Mon"; 109 | case DateTime.tuesday: 110 | return "Tue"; 111 | case DateTime.wednesday: 112 | return "Wed"; 113 | case DateTime.thursday: 114 | return "Thu"; 115 | case DateTime.friday: 116 | return "Fri"; 117 | case DateTime.saturday: 118 | return "Sat"; 119 | case DateTime.sunday: 120 | return "Sun"; 121 | default: 122 | return "NA"; 123 | } 124 | } 125 | 126 | String _month3(int month) { 127 | switch (month) { 128 | // todo internationalization from external file 129 | case 1: 130 | return "Jan"; 131 | case 2: 132 | return "Feb"; 133 | case 3: 134 | return "Mar"; 135 | case 4: 136 | return "Arp"; 137 | case 5: 138 | return "May"; 139 | case 6: 140 | return "Jun"; 141 | case 7: 142 | return "Jul"; 143 | case 8: 144 | return "Aug"; 145 | case 9: 146 | return "Sep"; 147 | case 10: 148 | return "Oct"; 149 | case 11: 150 | return "Nov"; 151 | case 12: 152 | return "Dec"; 153 | default: 154 | return "NA"; 155 | } 156 | } 157 | 158 | String _month(int month) { 159 | switch (month) { 160 | // todo internationalization from external file 161 | case 1: 162 | return "January"; 163 | case 2: 164 | return "February"; 165 | case 3: 166 | return "March"; 167 | case 4: 168 | return "Arpil"; 169 | case 5: 170 | return "May"; 171 | case 6: 172 | return "June"; 173 | case 7: 174 | return "July"; 175 | case 8: 176 | return "August"; 177 | case 9: 178 | return "September"; 179 | case 10: 180 | return "October"; 181 | case 11: 182 | return "November"; 183 | case 12: 184 | return "December"; 185 | default: 186 | return "NA"; 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /fimber/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: fimber 2 | description: Extensible logging for Flutter - based on Timber on Android, using similar (as far as Dart lang allows) method API with same concepts for tree and planting logging tree. 3 | version: 0.7.0 4 | homepage: https://github.com/magillus/flutter-fimber/tree/master/fimber 5 | 6 | environment: 7 | sdk: '>=2.12.0 <4.0.0' 8 | 9 | dev_dependencies: 10 | lint: ^2.0.0 11 | test: ^1.0.0 12 | -------------------------------------------------------------------------------- /fimber/test/colorize_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:fimber/fimber.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() async { 5 | group('Colorize', () { 6 | setUp(() { 7 | print("setup test - Colorize"); 8 | Fimber.clearAll(); 9 | }); 10 | tearDown(() { 11 | print("tear down test - Colorize"); 12 | Fimber.clearAll(); 13 | }); 14 | 15 | test("Test colors", () async { 16 | var colorize = Colorize(foreground: AnsiColor.red); 17 | print("TEXT"); 18 | print(colorize.wrap("TEXT")); 19 | colorize = 20 | Colorize(foreground: AnsiColor.blue, background: AnsiColor.black); 21 | print(colorize.wrap("TEXT STRING WITH BLUE")); 22 | colorize = 23 | Colorize(foreground: AnsiColor.cyan, background: AnsiColor.green); 24 | print("${colorize.wrap("TEXT more tests")}\n" 25 | "${colorize.wrap("TEST TEXT....", foreground: AnsiColor.white)}"); 26 | 27 | print(Colorize.wrapWith("Magenta", foreground: AnsiColor.magenta)); 28 | print( 29 | Colorize.wrapWith( 30 | "Blue reversed", 31 | foreground: AnsiColor.blue, 32 | reverse: true, 33 | ), 34 | ); 35 | print( 36 | Colorize.wrapWith( 37 | "Yellow and Green bright reversed", 38 | background: AnsiColor.green, 39 | foreground: AnsiColor.yellow, 40 | reverse: true, 41 | ), 42 | ); 43 | print(Colorize.wrapWith("Yellow bright", bright: AnsiColor.yellow)); 44 | 45 | print(Colorize.wrapWith("Some text", foreground: AnsiColor.magenta)); 46 | print(""); 47 | }); 48 | 49 | test("Test stylize", () { 50 | final style = ColorizeStyle([ 51 | AnsiStyle(AnsiSelection.foreground, color: AnsiColor.green), 52 | AnsiStyle(AnsiSelection.background, color: AnsiColor.blue) 53 | ]); 54 | print(style.wrap("TEST GREEN ON blue")); 55 | 56 | final styleB = ColorizeStyle([ 57 | AnsiStyle.background(AnsiColor.yellow), 58 | AnsiStyle.foreground(AnsiColor.black) 59 | ]); 60 | print(styleB.wrap("Test black on yellow background")); 61 | 62 | final styleGray30 = ColorizeStyle( 63 | [AnsiStyle.foreground(AnsiColor.bits)..bit9Pallete = 240], 64 | ); 65 | print(styleGray30.wrap("Test with gray 30")); 66 | final styleGray60 = ColorizeStyle( 67 | [AnsiStyle.foreground(AnsiColor.bits)..bit9Pallete = 249], 68 | ); 69 | print(styleGray60.wrap("Test with gray 60")); 70 | }); 71 | }); 72 | } 73 | -------------------------------------------------------------------------------- /fimber/test/custom_format_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:fimber/fimber.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group("Custom format", () { 6 | test('Format based logger', () { 7 | print(""); 8 | 9 | Fimber.clearAll(); 10 | final defaultFormat = AssertFormattedTree(); 11 | 12 | final elapsedMsg = AssertFormattedTree.elapsed( 13 | logFormat: '''${CustomFormatTree.timeElapsedToken} 14 | ${CustomFormatTree.messageToken}''', 15 | ); 16 | Fimber.plantTree(defaultFormat); 17 | Fimber.plantTree(elapsedMsg); 18 | 19 | Fimber.i("Test message A"); 20 | Fimber.i("Test Message B", ex: Exception("Test exception")); 21 | 22 | assert( 23 | defaultFormat.logLineHistory[0] 24 | .contains("I main..: Test message A"), 25 | ); 26 | assert( 27 | defaultFormat.logLineHistory[1] 28 | .contains("I main..: Test Message B"), 29 | ); 30 | expect( 31 | defaultFormat.logLineHistory[0] 32 | .substring("2019-01-18T09:15:08.980493".length + 1), 33 | "I main..: Test message A", 34 | ); 35 | 36 | assert(elapsedMsg.logLineHistory[0].contains("Test message A")); 37 | expect( 38 | "Test message A", 39 | elapsedMsg.logLineHistory[0].substring("0:00:00.008303".length + 1), 40 | ); 41 | }); 42 | }); 43 | } 44 | 45 | class AssertFormattedTree extends CustomFormatTree { 46 | AssertFormattedTree({ 47 | String logFormat = CustomFormatTree.defaultFormat, 48 | }) : super(logFormat: logFormat); 49 | 50 | factory AssertFormattedTree.elapsed({ 51 | String logFormat = CustomFormatTree.defaultFormat, 52 | }) { 53 | return AssertFormattedTree(logFormat: logFormat); 54 | } 55 | 56 | List logLineHistory = []; 57 | 58 | @override 59 | void printLine(String line, {String? level}) { 60 | logLineHistory.add(line); 61 | super.printLine(line, level: level); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /fimber_io/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .packages 4 | # Remove the following pattern if you wish to check in your lock file 5 | pubspec.lock 6 | 7 | # Conventional directory for build outputs 8 | build/ 9 | 10 | # Directory created by dartdoc 11 | doc/api/ 12 | -------------------------------------------------------------------------------- /fimber_io/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.7.0] - Dart 3 update. 2 | 3 | ## [0.6.6] - Bugfix 4 | 5 | -- Fix for path detection inf SizeRollingFileTree 6 | -- catchup to fimber main version 7 | 8 | ## [0.6.5] - Bug fixes 9 | 10 | -- Update android dependencies to mavenCentral (from jcenter) [#116](https://github.com/magillus/flutter-fimber/issues/116) 11 | -- Fix for Log without exception but with stack trace [#115](https://github.com/magillus/flutter-fimber/issues/115) 12 | 13 | ## [0.6.4] - Added log line/path to file to [CustomFormatTree] 14 | 15 | -- Additional tokens for [CustomFormatTree] with filename/filepath log line and character. 16 | 17 | ## [0.6.3] - SizeRollingFileTree bug fix 18 | 19 | -- [\#86](https://github.com/magillus/flutter-fimber/issues/86) - fix for this bug 20 | 21 | ## [0.6.2] - Build and merge fix 22 | 23 | ## [0.6.1-dev] Network Logger dev release 24 | 25 | - Added TCP/UDB socket loggers that allow network based connection to send logs. 26 | 27 | ## [0.6.1] - Build fix 28 | 29 | ## [0.6.0] - Release to null-safety on stable 30 | 31 | - Update to null-safety support on stable channel 32 | 33 | ## [0.5.0-nullsafety.1] - Updated to support dart null-safety 34 | 35 | - No other fixes/updates, just null-safety 36 | 37 | ## [0.4.4] - Fix for printing color when with level output 38 | 39 | Same as 0.4.3 - missed one usecase. 40 | 41 | ## [0.4.3] - Fix for printing color when with level output 42 | 43 | - [\#78 issue](https://github.com/magillus/flutter-fimber/issues/78) Fixing coloring output on the formatted log output. 44 | 45 | ## [0.4.2] - Fixed versioning 46 | 47 | - fixed versioning 48 | 49 | ## [0.4.1] - Bug fixes 50 | 51 | - [\#75 issue](https://github.com/magillus/flutter-fimber/issues/75) - Fix for TimedRollingFileTree missing passed logLevels and logFormat 52 | - [\#73 issue](https://github.com/magillus/flutter-fimber/issues/73) - Fix for mute levels list not being distinct 53 | 54 | ## 0.4.0 Fimber dependency on dart::io separated 55 | 56 | - moved all File based and dart::io package dependent code from `fimber` to `fimber_io` 57 | 58 | ## 0.3.3 fimber_io split from fimber package 59 | 60 | 61 | -------------------------------------------------------------------------------- /fimber_io/README.md: -------------------------------------------------------------------------------- 1 | # fimber_io 2 | 3 | Extensible logging for Flutter. Dart::IO version with File loggers. 4 | 5 | Package is based on famous Android logging library API - [Timber](https://github.com/JakeWharton/timber), this is library for simplify logging for Flutter. 6 | Using similar (as far as Dart lang allows) method API with same concepts for tree and planting logging tree. 7 | Also check out `flutter_fimber` which extends `fimber` to platform specific output and logging style. 8 | 9 | ## Getting Started 10 | 11 | To start add using it: 12 | ### Add `fimber_io` to `pubspec.yaml` 13 | ```yaml 14 | dependencies: 15 | fimber_io: ^0.7.0 16 | ``` 17 | - remember about import in file you plan to use Fimber 18 | ```dart 19 | import 'package:fimber_io/fimber_io.dart'; 20 | 21 | ``` 22 | 23 | ### Initialize logging tree on start of your application 24 | 25 | ```dart 26 | 27 | void main() { 28 | Fimber.plantTree(DebugTree()); 29 | // app code here ... 30 | 31 | // DebugTree options for time elapsed 32 | // by default DebugTree will output timestamp of the VM/Flutter app 33 | // to enable elapsed time since planting the tree log 34 | Fimber.plantTree(DebugTree.elapsed()); 35 | 36 | } 37 | 38 | ``` 39 | 40 | ### Start using it with static methods: 41 | 42 | ```dart 43 | import 'fimber.dart'; 44 | 45 | 46 | void main() { 47 | var parameter = 343.0; 48 | // use directly 49 | Fimber.i("Test message $argument"); 50 | Fimber.i("Extra error message", ex: Exception("Test thorwable")); 51 | 52 | // other log levels 53 | Fimber.d("DEBUG"); 54 | Fimber.v("VERBOSE"); 55 | Fimber.w("WARN"); 56 | 57 | try { 58 | throw Exception("Exception thrown"); 59 | } catch (e, stacktrace) { 60 | // providing `stacktrace` will better show where issue was thrown 61 | // if not provided will use log line location. 62 | Fimber.i("Error caught.", ex: e, stacktrace: stacktrace); 63 | } 64 | } 65 | 66 | ``` 67 | 68 | This will log the value and grab a TAG from stacktrace - that is little costly and if more logs will be done per second. 69 | 70 | ### Colorize logs - `ColorizeStyle` 71 | 72 | `useColors` property set to true will use default colors of the logos, you can change the mapping with in `colorizeMap` for `DebugTree` and `CustomFormatTree` 73 | The `useColors` by default is disabled. 74 | 75 | `ColorizeStyle` Aggregates list of `AnsiStyle` so you can combine styles together. 76 | 77 | `AnsiStyle` is combination of [`AnsiColor`](lib/colorize.dart) and [`AnsiSelection`](lib/colorize.dart) values 78 | 79 | Here is output of test output. 80 | 81 | ![Colorize Test Output](doc/colorize_fimber_test.PNG "Colorize Test Output") 82 | 83 | 84 | ### Create tagged version of Fimber 85 | 86 | And use its instance inside class, you can create logger for a dart file or for a class. 87 | 88 | ```dart 89 | var logger = FimberLog("MY_TAG"); 90 | 91 | void main() { 92 | 93 | logger.d("Test message"); 94 | } 95 | 96 | // or inside a class 97 | class SomeBloc { 98 | var logger = FimberLog("SomeBloc"); 99 | String fetchMessage() { 100 | logger.d("About to fetch some data."); 101 | //... 102 | var data = "load something"; 103 | 104 | logger.d("Retrived data (len = ${data.length}"); 105 | return data; 106 | } 107 | } 108 | ``` 109 | 110 | ### Use block function and pass method that uses logger. 111 | 112 | Use this function to log multiple messages with same tag, allows optional return value. 113 | Due to nature of auto-tag generation from stacktrace this block only does it once and create local FimberLog instance to pass into the anonymous method. 114 | 115 | ```dart 116 | var someMessage = "Test message from inside of block"; 117 | var output = Fimber.block((log) { 118 | log.d("Started block"); 119 | var i = 0; 120 | for (i = 0; i < 10; i++) { 121 | log.d("$someMessage, value: $i"); 122 | } 123 | log.i("End of block"); 124 | return i; 125 | }); 126 | ``` 127 | 128 | ### Custom line formatters 129 | 130 | Use custom line formatters to define your logging format. 131 | 132 | ```dart 133 | Fimber.plantTree(FimberFileTree("my-Log-File.txt", 134 | logFormat: "${CustomFormatTree.TIME_ELAPSED_TOKEN} ${CustomFormatTree 135 | .MESSAGE_TOKEN} ${CustomFormatTree.TIME_STAMP_TOKEN}" 136 | )); 137 | ``` 138 | 139 | Use file log tree - the logs will go to a log file (Useful in DartVM apps). 140 | There are log rolling with size and time/date interval, so it is possible to setup log output per hour/day or any other time. 141 | 142 | see: `SizeRollingFileTree` or `TimedRollingFileTree` or use abstract class `RollingFileTree` to create your own version of rolling log file. 143 | 144 | 145 | ## TODO - road map 146 | 147 | - See [Issues on Github](https://github.com/magillus/flutter-fimber/issues) 148 | - Add Crashlytics plugin (maybe other remote logger tools) with [flutter_crashlytics](https://pub.dartlang.org/packages/flutter_crashlytics) 149 | 150 | ## Licence 151 | 152 | ``` 153 | 154 | Copyright 2018 Mateusz Perlak 155 | 156 | Licensed under the Apache License, Version 2.0 (the "License"); 157 | you may not use this file except in compliance with the License. 158 | You may obtain a copy of the License at 159 | 160 | http://www.apache.org/licenses/LICENSE-2.0 161 | 162 | Unless required by applicable law or agreed to in writing, software 163 | distributed under the License is distributed on an "AS IS" BASIS, 164 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 165 | See the License for the specific language governing permissions and 166 | limitations under the License. 167 | ``` -------------------------------------------------------------------------------- /fimber_io/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lint/package.yaml 2 | 3 | linter: 4 | rules: 5 | always_use_package_imports: false 6 | prefer_relative_imports: true -------------------------------------------------------------------------------- /fimber_io/example/fimber_io_example.dart: -------------------------------------------------------------------------------- 1 | import 'package:fimber_io/fimber_io.dart'; 2 | 3 | void main() { 4 | // todo example with files. 5 | Fimber.plantTree(FimberFileTree.elapsed('test.log')); 6 | 7 | Fimber.i('Test log'); 8 | Fimber.d('Test DEBUG'); 9 | } 10 | -------------------------------------------------------------------------------- /fimber_io/lib/fimber_io.dart: -------------------------------------------------------------------------------- 1 | export 'package:fimber/fimber.dart'; 2 | export 'src/file_log.dart'; 3 | export 'src/socket_log.dart'; 4 | -------------------------------------------------------------------------------- /fimber_io/lib/src/socket_log.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | import 'dart:io'; 4 | 5 | import '../fimber_io.dart'; 6 | 7 | /// NetworkLoggingTree uses TCP or UDP sockets to send log entries to. 8 | /// 9 | /// Example in terminal: 10 | /// nc -kvl 5601 | grep TheClassName 11 | class NetworkLoggingTree extends CustomFormatTree implements UnPlantableTree { 12 | /// Creates isntance of [NetworkLoggingTree] 13 | NetworkLoggingTree._( 14 | this._server, 15 | this._port, 16 | this.timeout, { 17 | this.isTcpSocket = false, 18 | }) : super( 19 | useColors: true, 20 | logFormat: 21 | '${CustomFormatTree.levelToken} ${CustomFormatTree.tagToken}: ${CustomFormatTree.messageToken}', 22 | ); 23 | 24 | /// Creates UDP version of the [NetworkLoggingTree] 25 | factory NetworkLoggingTree.udp( 26 | String server, 27 | int port, { 28 | Duration timeout = const Duration(seconds: 10), 29 | }) => 30 | NetworkLoggingTree._(server, port, timeout); 31 | 32 | /// Creates TCP version of the [NetworkLoggingTree] 33 | factory NetworkLoggingTree.tcp( 34 | String server, 35 | int port, { 36 | Duration timeout = const Duration(seconds: 10), 37 | }) => 38 | NetworkLoggingTree._(server, port, timeout, isTcpSocket: true); 39 | 40 | /// Connection timeout (used on TCP socket) 41 | final Duration timeout; 42 | final String _server; 43 | final int _port; 44 | 45 | /// If true it is TCP socket to be used. 46 | final bool isTcpSocket; 47 | 48 | Completer? _socketUdpComplete; 49 | Completer? _socketTcpComplete; 50 | RawDatagramSocket? _socketUdp; 51 | Socket? _socket; 52 | 53 | @override 54 | void planted() { 55 | // start socket and listen 56 | if (isTcpSocket) { 57 | _prepareTcpSocket(); 58 | } else { 59 | _prepareUdpSocket(); 60 | } 61 | } 62 | 63 | void _prepareUdpSocket() { 64 | if (_socketUdpComplete == null) { 65 | _socketUdpComplete = Completer(); 66 | print('UDP Socket about to open.'); 67 | _socketUdpComplete?.future.then((value) { 68 | print('Socket opened. $value'); 69 | _socketUdp = value; 70 | }); 71 | _socketUdpComplete?.complete( 72 | RawDatagramSocket.bind( 73 | _server, 74 | 0, // use any available port 75 | ), 76 | ); 77 | } 78 | } 79 | 80 | void _prepareTcpSocket() { 81 | if (_socketTcpComplete == null) { 82 | _socketTcpComplete = Completer(); 83 | print('TCP Socket about to open.'); 84 | _socketTcpComplete?.future.then((value) { 85 | print('TCP Socket opened. $value'); 86 | _socket = value; 87 | }); 88 | _socketTcpComplete 89 | ?.complete(Socket.connect(_server, _port, timeout: timeout)); 90 | } 91 | } 92 | 93 | @override 94 | void unplanted() { 95 | _socket?.close(); 96 | _socketTcpComplete = null; 97 | _socket = null; 98 | _socketUdp?.close(); 99 | _socketUdpComplete = null; 100 | _socketUdp = null; 101 | } 102 | 103 | @override 104 | void printLine(String line, {String? level}) { 105 | super.printLine(line, level: level); 106 | if (isTcpSocket) { 107 | if (_socket != null) { 108 | print('TCP socket available - will send: ${line.length}'); 109 | _socket?.writeln(line); 110 | } else { 111 | print('No socket available - will wait for one with this message.'); 112 | _socketTcpComplete?.future.then((value) => value.writeln(line)); 113 | } 114 | } else { 115 | if (_socketUdp != null) { 116 | final bytesToSend = utf8.encoder.convert(line).toList(); 117 | print('UDP socket available - will send: ${bytesToSend.length}'); 118 | _socketUdp?.send(bytesToSend, InternetAddress(_server), _port); 119 | } else { 120 | print('No socket available - will wait for one with this message.'); 121 | 122 | /// TODO make a small cache locally before socket is available 123 | _socketUdpComplete?.future.then( 124 | (value) => value.send( 125 | utf8.encoder.convert(line).toList(), 126 | InternetAddress(_server), 127 | _port, 128 | ), 129 | ); 130 | } 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /fimber_io/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: fimber_io 2 | description: Version of Fimber package with support for File based loggers - dependent on dart::io 3 | version: 0.7.0 4 | 5 | homepage: https://github.com/magillus/flutter-fimber/tree/master/fimber 6 | 7 | environment: 8 | sdk: ">=2.12.0 <4.0.0" 9 | 10 | dependencies: 11 | fimber: "^0.7.0" 12 | 13 | dev_dependencies: 14 | lint: ^2.0.0 15 | test: ^1.0.0 16 | -------------------------------------------------------------------------------- /fimber_io/test/socket_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | import 'dart:io'; 4 | 5 | import 'package:fimber_io/fimber_io.dart'; 6 | import 'package:test/test.dart'; 7 | 8 | void main() async { 9 | const testPort = 17779; 10 | 11 | group('UDP Socket log tests.', () { 12 | NetworkLoggingTree logTree; 13 | 14 | final logMessages = []; 15 | late RawDatagramSocket testReceiveSocket; 16 | 17 | setUp(() async { 18 | Fimber.clearAll(); 19 | testReceiveSocket = 20 | await RawDatagramSocket.bind(InternetAddress.anyIPv4, testPort); 21 | 22 | print('Datagram socket ready to receive'); 23 | print('${testReceiveSocket.address.address}:${testReceiveSocket.port}'); 24 | testReceiveSocket.listen( 25 | (RawSocketEvent e) { 26 | print('Socket event: $e'); 27 | final d = testReceiveSocket.receive(); 28 | if (d == null) return; 29 | final message = utf8.decoder.convert(d.data); 30 | logMessages.add(message); 31 | }, 32 | onError: (t) => print('Error with socket $t'), 33 | ); 34 | 35 | logTree = NetworkLoggingTree.udp('127.0.0.1', testPort); 36 | 37 | Fimber.plantTree(logTree); 38 | print('Delay to start sockets'); 39 | await Future.delayed(const Duration(milliseconds: 100)); 40 | 41 | print('Test Setup complete.'); 42 | }); 43 | 44 | tearDown(() { 45 | testReceiveSocket.close(); 46 | Fimber.clearAll(); 47 | print('TearDown.'); 48 | }); 49 | 50 | test('Test UDP socket logger', () async { 51 | Fimber.i('test log out1'); 52 | 53 | await Future.delayed(const Duration(milliseconds: 100)); 54 | 55 | expect(1, logMessages.length); 56 | expect(true, logMessages.last.contains('test log out1')); 57 | }); 58 | }); 59 | 60 | group('TCP Socket log tests.', () { 61 | final logMessages = []; 62 | late ServerSocket testReceiveSocket; 63 | late StreamSubscription socketSubscription; 64 | late StreamSubscription clientSubscription; 65 | 66 | setUp(() async { 67 | Fimber.clearAll(); 68 | testReceiveSocket = 69 | await ServerSocket.bind(InternetAddress.anyIPv4, testPort); 70 | 71 | print('Datagram socket ready to receive'); 72 | print('${testReceiveSocket.address.address}:${testReceiveSocket.port}'); 73 | 74 | socketSubscription = testReceiveSocket.listen( 75 | (client) { 76 | print('Socket connected. $client'); 77 | clientSubscription = client.listen( 78 | (event) { 79 | final message = utf8.decoder.convert(event); 80 | logMessages.add(message); 81 | }, 82 | onError: (t) => print('Error with socket $t'), 83 | ); 84 | }, 85 | onDone: () => print('Socket client disconnected.'), 86 | ); 87 | 88 | print('Delay to start sockets'); 89 | await Future.delayed(const Duration(milliseconds: 100)); 90 | 91 | print('Test Setup complete.'); 92 | }); 93 | 94 | tearDown(() { 95 | clientSubscription.cancel(); 96 | socketSubscription.cancel(); 97 | testReceiveSocket.close(); 98 | print('TearDown.'); 99 | }); 100 | 101 | test('Test TCP socket logger', () async { 102 | final logTree = NetworkLoggingTree.tcp('127.0.0.1', testPort); 103 | 104 | Fimber.plantTree(logTree); 105 | Fimber.i('test log out2'); 106 | 107 | await Future.delayed(const Duration(milliseconds: 100)); 108 | 109 | expect(1, logMessages.length); 110 | expect(true, logMessages.last.contains('test log out2')); 111 | 112 | Fimber.clearAll(); 113 | // TODO fix stalled test - it doesn't exit 114 | }); 115 | 116 | // test('Test TCP not available socket logger', () async { 117 | // var logTree = 118 | // NetworkLoggingTree('127.0.0.1', testPort + 1, isTcpSocket: true); 119 | // Fimber.plantTree(logTree); 120 | 121 | // Fimber.i('test log out3'); 122 | // Fimber.clearAll(); 123 | // }); 124 | }); 125 | } 126 | -------------------------------------------------------------------------------- /flutter_fimber/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 26 | /pubspec.lock 27 | **/doc/api/ 28 | .dart_tool/ 29 | .packages 30 | build/ 31 | -------------------------------------------------------------------------------- /flutter_fimber/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.7.0] - Dart 3 update, android plugin upgrade 2 | 3 | ## 0.0.1 4 | 5 | * TODO: Describe initial release. 6 | -------------------------------------------------------------------------------- /flutter_fimber/LICENSE: -------------------------------------------------------------------------------- 1 | TODO: Add your license here. 2 | -------------------------------------------------------------------------------- /flutter_fimber/README.md: -------------------------------------------------------------------------------- 1 | # flutter_fimber 2 | 3 | A new Flutter plugin project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter 8 | [plug-in package](https://flutter.dev/developing-packages/), 9 | a specialized package that includes platform-specific implementation code for 10 | Android and/or iOS. 11 | 12 | For help getting started with Flutter development, view the 13 | [online documentation](https://flutter.dev/docs), which offers tutorials, 14 | samples, guidance on mobile development, and a full API reference. 15 | 16 | -------------------------------------------------------------------------------- /flutter_fimber/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | always_use_package_imports: false 6 | prefer_relative_imports: true -------------------------------------------------------------------------------- /flutter_fimber/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .cxx 10 | -------------------------------------------------------------------------------- /flutter_fimber/android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.magillus.flutter_fimber' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | ext.kotlin_version = '1.6.10' 6 | repositories { 7 | google() 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:7.1.2' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | mavenCentral() 21 | } 22 | } 23 | 24 | apply plugin: 'com.android.library' 25 | apply plugin: 'kotlin-android' 26 | 27 | android { 28 | compileSdkVersion 31 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | 35 | kotlinOptions { 36 | jvmTarget = '1.8' 37 | } 38 | 39 | sourceSets { 40 | main.java.srcDirs += 'src/main/kotlin' 41 | } 42 | 43 | defaultConfig { 44 | minSdkVersion 16 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /flutter_fimber/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /flutter_fimber/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /flutter_fimber/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /flutter_fimber/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'flutter_fimber' 2 | -------------------------------------------------------------------------------- /flutter_fimber/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /flutter_fimber/android/src/main/kotlin/com/magillus/flutter_fimber/FlutterFimberPlugin.kt: -------------------------------------------------------------------------------- 1 | package com.magillus.flutter_fimber 2 | 3 | import androidx.annotation.NonNull 4 | 5 | import io.flutter.embedding.engine.plugins.FlutterPlugin 6 | import io.flutter.plugin.common.MethodCall 7 | import io.flutter.plugin.common.MethodChannel 8 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler 9 | import io.flutter.plugin.common.MethodChannel.Result 10 | 11 | /** FlutterFimberPlugin */ 12 | class FlutterFimberPlugin: FlutterPlugin, MethodCallHandler { 13 | /// The MethodChannel that will the communication between Flutter and native Android 14 | /// 15 | /// This local reference serves to register the plugin with the Flutter Engine and unregister it 16 | /// when the Flutter Engine is detached from the Activity 17 | private lateinit var channel : MethodChannel 18 | 19 | override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { 20 | channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flutter_fimber") 21 | channel.setMethodCallHandler(this) 22 | } 23 | 24 | override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { 25 | if (call.method == "getPlatformVersion") { 26 | result.success("Android ${android.os.Build.VERSION.RELEASE}") 27 | } else { 28 | result.notImplemented() 29 | } 30 | } 31 | 32 | override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { 33 | channel.setMethodCallHandler(null) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /flutter_fimber/android/src/test/kotlin/com/magillus/flutter_fimber/FlutterFimberPluginTest.kt: -------------------------------------------------------------------------------- 1 | package com.magillus.flutter_fimber 2 | 3 | import io.flutter.plugin.common.MethodCall 4 | import io.flutter.plugin.common.MethodChannel 5 | import kotlin.test.Test 6 | import org.mockito.Mockito 7 | 8 | /* 9 | * This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation. 10 | * 11 | * Once you have built the plugin's example app, you can run these tests from the command 12 | * line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or 13 | * you can run them directly from IDEs that support JUnit such as Android Studio. 14 | */ 15 | 16 | internal class FlutterFimberPluginTest { 17 | @Test 18 | fun onMethodCall_getPlatformVersion_returnsExpectedValue() { 19 | val plugin = FlutterFimberPlugin() 20 | 21 | val call = MethodCall("getPlatformVersion", null) 22 | val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java) 23 | plugin.onMethodCall(call, mockResult) 24 | 25 | Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /flutter_fimber/example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | /build/ 34 | 35 | # Symbolication related 36 | app.*.symbols 37 | 38 | # Obfuscation related 39 | app.*.map.json 40 | 41 | # Android Studio will place build artifacts here 42 | /android/app/debug 43 | /android/app/profile 44 | /android/app/release 45 | -------------------------------------------------------------------------------- /flutter_fimber/example/README.md: -------------------------------------------------------------------------------- 1 | # flutter_fimber_example 2 | 3 | Demonstrates how to use the flutter_fimber 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://docs.flutter.dev/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) 13 | 14 | For help getting started with Flutter development, view the 15 | [online documentation](https://docs.flutter.dev/), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /flutter_fimber/example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion flutter.compileSdkVersion 30 | ndkVersion flutter.ndkVersion 31 | 32 | compileOptions { 33 | sourceCompatibility JavaVersion.VERSION_1_8 34 | targetCompatibility JavaVersion.VERSION_1_8 35 | } 36 | 37 | kotlinOptions { 38 | jvmTarget = '1.8' 39 | } 40 | 41 | sourceSets { 42 | main.java.srcDirs += 'src/main/kotlin' 43 | } 44 | 45 | defaultConfig { 46 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 47 | applicationId "com.magillus.flutterfimber_example" 48 | // You can update the following values to match your application needs. 49 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. 50 | minSdkVersion flutter.minSdkVersion 51 | targetSdkVersion flutter.targetSdkVersion 52 | versionCode flutterVersionCode.toInteger() 53 | versionName flutterVersionName 54 | } 55 | 56 | buildTypes { 57 | release { 58 | // TODO: Add your own signing config for the release build. 59 | // Signing with the debug keys for now, so `flutter run --release` works. 60 | signingConfig signingConfigs.debug 61 | } 62 | } 63 | } 64 | 65 | flutter { 66 | source '../..' 67 | } 68 | 69 | dependencies { 70 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 71 | } 72 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 20 | 29 | 33 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/main/kotlin/com/magillus/flutter_fimber_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.magillus.flutter_fimber_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.21' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.4.2' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip 6 | -------------------------------------------------------------------------------- /flutter_fimber/example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /flutter_fimber/example/integration_test/plugin_integration_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter integration test. 2 | // 3 | // Since integration tests run in a full Flutter application, they can interact 4 | // with the host side of a plugin implementation, unlike Dart unit tests. 5 | // 6 | // For more information about Flutter integration tests, please see 7 | // https://docs.flutter.dev/cookbook/testing/integration/introduction 8 | 9 | 10 | import 'package:flutter_test/flutter_test.dart'; 11 | import 'package:integration_test/integration_test.dart'; 12 | 13 | 14 | void main() { 15 | IntegrationTestWidgetsFlutterBinding.ensureInitialized(); 16 | 17 | testWidgets('getPlatformVersion test', (WidgetTester tester) async { 18 | // final Fimber plugin = Fimber(); 19 | // final String? version = await plugin.getPlatformVersion(); 20 | // // The version string depends on the host platform running the test, so 21 | // // just assert that some non-empty string is returned. 22 | // expect(version?.isNotEmpty, true); 23 | expect(true, isTrue); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | 11.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig" 3 | #include "Generated.xcconfig" 4 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '11.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | target 'RunnerTests' do 36 | inherit! :search_paths 37 | end 38 | end 39 | 40 | post_install do |installer| 41 | installer.pods_project.targets.each do |target| 42 | flutter_additional_ios_build_settings(target) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - flutter_fimber (0.0.1): 4 | - Flutter 5 | - integration_test (0.0.1): 6 | - Flutter 7 | 8 | DEPENDENCIES: 9 | - Flutter (from `Flutter`) 10 | - flutter_fimber (from `.symlinks/plugins/flutter_fimber/ios`) 11 | - integration_test (from `.symlinks/plugins/integration_test/ios`) 12 | 13 | EXTERNAL SOURCES: 14 | Flutter: 15 | :path: Flutter 16 | flutter_fimber: 17 | :path: ".symlinks/plugins/flutter_fimber/ios" 18 | integration_test: 19 | :path: ".symlinks/plugins/integration_test/ios" 20 | 21 | SPEC CHECKSUMS: 22 | Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 23 | flutter_fimber: ec011dfb08d7cbfa16ab6bad8450b99574e6f6a4 24 | integration_test: 13825b8a9334a850581300559b8839134b124670 25 | 26 | PODFILE CHECKSUM: 6b9eb94e9f98a329f2ef624b852a6e42d090af2b 27 | 28 | COCOAPODS: 1.11.3 29 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_fimber/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 | -------------------------------------------------------------------------------- /flutter_fimber/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 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /flutter_fimber/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 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /flutter_fimber/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. -------------------------------------------------------------------------------- /flutter_fimber/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 | -------------------------------------------------------------------------------- /flutter_fimber/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 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | CADisableMinimumFrameDurationOnPhone 47 | 48 | UIApplicationSupportsIndirectInputEvents 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /flutter_fimber/example/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /flutter_fimber/example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_fimber/flutter_fimber.dart'; 5 | 6 | void main() { 7 | /// You can pick one of them or combine, 8 | /// be aware that 2 or more console loggers will output multiple times 9 | // Example tree of using Fimber with color logging 10 | Fimber.plantTree(FimberTree(useColors: true)); 11 | 12 | /// Debug tree with time of process running 13 | Fimber.plantTree(DebugBufferTree.elapsed()); 14 | runApp(MyApp()); 15 | } 16 | 17 | /// Example app for showing usage of Fimber 18 | class MyApp extends StatefulWidget { 19 | @override 20 | _MyAppState createState() => _MyAppState(); 21 | } 22 | 23 | class _MyAppState extends State { 24 | @override 25 | void initState() { 26 | super.initState(); 27 | initPlatformState(); 28 | } 29 | 30 | // Platform messages are asynchronous, so we initialize in an async method. 31 | Future initPlatformState() async { 32 | // If the widget was removed from the tree while the asynchronous platform 33 | // message was in flight, we want to discard the reply rather than calling 34 | // setState to update our non-existent appearance. 35 | if (!mounted) return; 36 | 37 | setState(() {}); 38 | } 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | return MaterialApp( 43 | home: Scaffold( 44 | appBar: AppBar( 45 | title: const Text('Fimber Plugin example app'), 46 | ), 47 | body: Center( 48 | child: Column( 49 | mainAxisAlignment: MainAxisAlignment.center, 50 | children: [ 51 | Text('Fimber test'), 52 | TextButton( 53 | child: Text("LOG - ERROR"), 54 | onPressed: () { 55 | Fimber.e("Error message test ${DateTime.now()}"); 56 | }, 57 | ), 58 | TextButton( 59 | child: Text("LOG - INFO"), 60 | onPressed: () { 61 | Fimber.i("Info message test ${DateTime.now()}"); 62 | }, 63 | ), 64 | TextButton( 65 | child: Text("LOG - DEBUG"), 66 | onPressed: () { 67 | Fimber.d("Debug message test ${DateTime.now()}"); 68 | }, 69 | ), 70 | TextButton( 71 | child: Text("LOG - WARNING with exception"), 72 | onPressed: () { 73 | try { 74 | throw Exception("Test exception here"); 75 | } on Exception catch (e) { 76 | Fimber.w("Warning message test ${DateTime.now()}", ex: e); 77 | } 78 | }, 79 | ), 80 | TextButton( 81 | child: Text("LOG - WARNING with Error and stacktrace"), 82 | onPressed: () { 83 | try { 84 | throw AssertionError(); 85 | } on Exception catch (e, s) { 86 | Fimber.w("Warning message test ${DateTime.now()}", 87 | ex: e, stacktrace: s); 88 | } 89 | }, 90 | ), 91 | ], 92 | ), 93 | ), 94 | ), 95 | ); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /flutter_fimber/example/linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /flutter_fimber/example/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project-level configuration. 2 | cmake_minimum_required(VERSION 3.10) 3 | project(runner LANGUAGES CXX) 4 | 5 | # The name of the executable created for the application. Change this to change 6 | # the on-disk name of your application. 7 | set(BINARY_NAME "flutter_fimber_example") 8 | # The unique GTK application identifier for this application. See: 9 | # https://wiki.gnome.org/HowDoI/ChooseApplicationID 10 | set(APPLICATION_ID "com.magillus.flutter_fimber") 11 | 12 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent 13 | # versions of CMake. 14 | cmake_policy(SET CMP0063 NEW) 15 | 16 | # Load bundled libraries from the lib/ directory relative to the binary. 17 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 18 | 19 | # Root filesystem for cross-building. 20 | if(FLUTTER_TARGET_PLATFORM_SYSROOT) 21 | set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) 22 | set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) 23 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 24 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 25 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 26 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 27 | endif() 28 | 29 | # Define build configuration options. 30 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 31 | set(CMAKE_BUILD_TYPE "Debug" CACHE 32 | STRING "Flutter build mode" FORCE) 33 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 34 | "Debug" "Profile" "Release") 35 | endif() 36 | 37 | # Compilation settings that should be applied to most targets. 38 | # 39 | # Be cautious about adding new options here, as plugins use this function by 40 | # default. In most cases, you should add new options to specific targets instead 41 | # of modifying this function. 42 | function(APPLY_STANDARD_SETTINGS TARGET) 43 | target_compile_features(${TARGET} PUBLIC cxx_std_14) 44 | target_compile_options(${TARGET} PRIVATE -Wall -Werror) 45 | target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") 46 | target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") 47 | endfunction() 48 | 49 | # Flutter library and tool build rules. 50 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 51 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 52 | 53 | # System-level dependencies. 54 | find_package(PkgConfig REQUIRED) 55 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 56 | 57 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") 58 | 59 | # Define the application target. To change its name, change BINARY_NAME above, 60 | # not the value here, or `flutter run` will no longer work. 61 | # 62 | # Any new source files that you add to the application should be added here. 63 | add_executable(${BINARY_NAME} 64 | "main.cc" 65 | "my_application.cc" 66 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 67 | ) 68 | 69 | # Apply the standard set of build settings. This can be removed for applications 70 | # that need different build settings. 71 | apply_standard_settings(${BINARY_NAME}) 72 | 73 | # Add dependency libraries. Add any application-specific dependencies here. 74 | target_link_libraries(${BINARY_NAME} PRIVATE flutter) 75 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) 76 | 77 | # Run the Flutter tool portions of the build. This must not be removed. 78 | add_dependencies(${BINARY_NAME} flutter_assemble) 79 | 80 | # Only the install-generated bundle's copy of the executable will launch 81 | # correctly, since the resources must in the right relative locations. To avoid 82 | # people trying to run the unbundled copy, put it in a subdirectory instead of 83 | # the default top-level location. 84 | set_target_properties(${BINARY_NAME} 85 | PROPERTIES 86 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" 87 | ) 88 | 89 | # Generated plugin build rules, which manage building the plugins and adding 90 | # them to the application. 91 | include(flutter/generated_plugins.cmake) 92 | 93 | 94 | # === Installation === 95 | # By default, "installing" just makes a relocatable bundle in the build 96 | # directory. 97 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") 98 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 99 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 100 | endif() 101 | 102 | # Start with a clean build bundle directory every time. 103 | install(CODE " 104 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") 105 | " COMPONENT Runtime) 106 | 107 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 108 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") 109 | 110 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 111 | COMPONENT Runtime) 112 | 113 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 114 | COMPONENT Runtime) 115 | 116 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 117 | COMPONENT Runtime) 118 | 119 | foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) 120 | install(FILES "${bundled_library}" 121 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 122 | COMPONENT Runtime) 123 | endforeach(bundled_library) 124 | 125 | # Fully re-copy the assets directory on each build to avoid having stale files 126 | # from a previous install. 127 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 128 | install(CODE " 129 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 130 | " COMPONENT Runtime) 131 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 132 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 133 | 134 | # Install the AOT library on non-Debug builds only. 135 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") 136 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 137 | COMPONENT Runtime) 138 | endif() 139 | -------------------------------------------------------------------------------- /flutter_fimber/example/linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.10) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | 12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 13 | # which isn't available in 3.10. 14 | function(list_prepend LIST_NAME PREFIX) 15 | set(NEW_LIST "") 16 | foreach(element ${${LIST_NAME}}) 17 | list(APPEND NEW_LIST "${PREFIX}${element}") 18 | endforeach(element) 19 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 20 | endfunction() 21 | 22 | # === Flutter Library === 23 | # System-level dependencies. 24 | find_package(PkgConfig REQUIRED) 25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 28 | 29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 30 | 31 | # Published to parent scope for install step. 32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 36 | 37 | list(APPEND FLUTTER_LIBRARY_HEADERS 38 | "fl_basic_message_channel.h" 39 | "fl_binary_codec.h" 40 | "fl_binary_messenger.h" 41 | "fl_dart_project.h" 42 | "fl_engine.h" 43 | "fl_json_message_codec.h" 44 | "fl_json_method_codec.h" 45 | "fl_message_codec.h" 46 | "fl_method_call.h" 47 | "fl_method_channel.h" 48 | "fl_method_codec.h" 49 | "fl_method_response.h" 50 | "fl_plugin_registrar.h" 51 | "fl_plugin_registry.h" 52 | "fl_standard_message_codec.h" 53 | "fl_standard_method_codec.h" 54 | "fl_string_codec.h" 55 | "fl_value.h" 56 | "fl_view.h" 57 | "flutter_linux.h" 58 | ) 59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 60 | add_library(flutter INTERFACE) 61 | target_include_directories(flutter INTERFACE 62 | "${EPHEMERAL_DIR}" 63 | ) 64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 65 | target_link_libraries(flutter INTERFACE 66 | PkgConfig::GTK 67 | PkgConfig::GLIB 68 | PkgConfig::GIO 69 | ) 70 | add_dependencies(flutter flutter_assemble) 71 | 72 | # === Flutter tool backend === 73 | # _phony_ is a non-existent file to force this command to run every time, 74 | # since currently there's no way to get a full input/output list from the 75 | # flutter tool. 76 | add_custom_command( 77 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 78 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 79 | COMMAND ${CMAKE_COMMAND} -E env 80 | ${FLUTTER_TOOL_ENVIRONMENT} 81 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 82 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} 83 | VERBATIM 84 | ) 85 | add_custom_target(flutter_assemble DEPENDS 86 | "${FLUTTER_LIBRARY}" 87 | ${FLUTTER_LIBRARY_HEADERS} 88 | ) 89 | -------------------------------------------------------------------------------- /flutter_fimber/example/linux/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | 10 | void fl_register_plugins(FlPluginRegistry* registry) { 11 | } 12 | -------------------------------------------------------------------------------- /flutter_fimber/example/linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void fl_register_plugins(FlPluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /flutter_fimber/example/linux/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | ) 7 | 8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 9 | ) 10 | 11 | set(PLUGIN_BUNDLED_LIBRARIES) 12 | 13 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 18 | endforeach(plugin) 19 | 20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 23 | endforeach(ffi_plugin) 24 | -------------------------------------------------------------------------------- /flutter_fimber/example/linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /flutter_fimber/example/linux/my_application.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | #include 4 | #ifdef GDK_WINDOWING_X11 5 | #include 6 | #endif 7 | 8 | #include "flutter/generated_plugin_registrant.h" 9 | 10 | struct _MyApplication { 11 | GtkApplication parent_instance; 12 | char** dart_entrypoint_arguments; 13 | }; 14 | 15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) 16 | 17 | // Implements GApplication::activate. 18 | static void my_application_activate(GApplication* application) { 19 | MyApplication* self = MY_APPLICATION(application); 20 | GtkWindow* window = 21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); 22 | 23 | // Use a header bar when running in GNOME as this is the common style used 24 | // by applications and is the setup most users will be using (e.g. Ubuntu 25 | // desktop). 26 | // If running on X and not using GNOME then just use a traditional title bar 27 | // in case the window manager does more exotic layout, e.g. tiling. 28 | // If running on Wayland assume the header bar will work (may need changing 29 | // if future cases occur). 30 | gboolean use_header_bar = TRUE; 31 | #ifdef GDK_WINDOWING_X11 32 | GdkScreen* screen = gtk_window_get_screen(window); 33 | if (GDK_IS_X11_SCREEN(screen)) { 34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); 35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) { 36 | use_header_bar = FALSE; 37 | } 38 | } 39 | #endif 40 | if (use_header_bar) { 41 | GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); 42 | gtk_widget_show(GTK_WIDGET(header_bar)); 43 | gtk_header_bar_set_title(header_bar, "flutter_fimber_example"); 44 | gtk_header_bar_set_show_close_button(header_bar, TRUE); 45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); 46 | } else { 47 | gtk_window_set_title(window, "flutter_fimber_example"); 48 | } 49 | 50 | gtk_window_set_default_size(window, 1280, 720); 51 | gtk_widget_show(GTK_WIDGET(window)); 52 | 53 | g_autoptr(FlDartProject) project = fl_dart_project_new(); 54 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); 55 | 56 | FlView* view = fl_view_new(project); 57 | gtk_widget_show(GTK_WIDGET(view)); 58 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); 59 | 60 | fl_register_plugins(FL_PLUGIN_REGISTRY(view)); 61 | 62 | gtk_widget_grab_focus(GTK_WIDGET(view)); 63 | } 64 | 65 | // Implements GApplication::local_command_line. 66 | static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { 67 | MyApplication* self = MY_APPLICATION(application); 68 | // Strip out the first argument as it is the binary name. 69 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); 70 | 71 | g_autoptr(GError) error = nullptr; 72 | if (!g_application_register(application, nullptr, &error)) { 73 | g_warning("Failed to register: %s", error->message); 74 | *exit_status = 1; 75 | return TRUE; 76 | } 77 | 78 | g_application_activate(application); 79 | *exit_status = 0; 80 | 81 | return TRUE; 82 | } 83 | 84 | // Implements GObject::dispose. 85 | static void my_application_dispose(GObject* object) { 86 | MyApplication* self = MY_APPLICATION(object); 87 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); 88 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object); 89 | } 90 | 91 | static void my_application_class_init(MyApplicationClass* klass) { 92 | G_APPLICATION_CLASS(klass)->activate = my_application_activate; 93 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; 94 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose; 95 | } 96 | 97 | static void my_application_init(MyApplication* self) {} 98 | 99 | MyApplication* my_application_new() { 100 | return MY_APPLICATION(g_object_new(my_application_get_type(), 101 | "application-id", APPLICATION_ID, 102 | "flags", G_APPLICATION_NON_UNIQUE, 103 | nullptr)); 104 | } 105 | -------------------------------------------------------------------------------- /flutter_fimber/example/linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '10.14' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_macos_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | use_modular_headers! 32 | 33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) 34 | target 'RunnerTests' do 35 | inherit! :search_paths 36 | end 37 | end 38 | 39 | post_install do |installer| 40 | installer.pods_project.targets.each do |target| 41 | flutter_additional_macos_build_settings(target) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = flutter_fimber_example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.magillus.flutterFimberExample 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2022 com.magillus. All rights reserved. 15 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /flutter_fimber/example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter_fimber/example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_fimber_example 2 | description: Demonstrates how to use the flutter_fimber plugin. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `flutter 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 <4.0.0' 10 | 11 | # Dependencies specify other packages that your package needs in order to work. 12 | # To automatically upgrade your package dependencies to the latest versions 13 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 14 | # dependencies can be manually updated by changing the version numbers below to 15 | # the latest version available on pub.dev. To see which dependencies have newer 16 | # versions available, run `flutter pub outdated`. 17 | dependencies: 18 | flutter: 19 | sdk: flutter 20 | 21 | flutter_fimber: 22 | # When depending on this package from a real application you should use: 23 | # flutter_fimber: ^x.y.z 24 | # See https://dart.dev/tools/pub/dependencies#version-constraints 25 | # The example app is bundled with the plugin so we use a path dependency on 26 | # the parent directory to use the current plugin's version. 27 | path: ../ 28 | 29 | # The following adds the Cupertino Icons font to your application. 30 | # Use with the CupertinoIcons class for iOS style icons. 31 | cupertino_icons: ^1.0.2 32 | 33 | dev_dependencies: 34 | flutter_test: 35 | sdk: flutter 36 | integration_test: 37 | sdk: flutter 38 | test: '^1.0.0' 39 | 40 | # The "flutter_lints" package below contains a set of recommended lints to 41 | # encourage good coding practices. The lint set provided by the package is 42 | # activated in the `analysis_options.yaml` file located at the root of your 43 | # package. See that file for information about deactivating specific lint 44 | # rules and activating additional ones. 45 | flutter_lints: ^2.0.0 46 | 47 | # For information on the generic Dart part of this file, see the 48 | # following page: https://dart.dev/tools/pub/pubspec 49 | 50 | # The following section is specific to Flutter packages. 51 | flutter: 52 | 53 | # The following line ensures that the Material Icons font is 54 | # included with your application, so that you can use the icons in 55 | # the material Icons class. 56 | uses-material-design: true 57 | 58 | # To add assets to your application, add an assets section, like this: 59 | # assets: 60 | # - images/a_dot_burr.jpeg 61 | # - images/a_dot_ham.jpeg 62 | 63 | # An image asset can refer to one or more resolution-specific "variants", see 64 | # https://flutter.dev/assets-and-images/#resolution-aware 65 | 66 | # For details regarding adding assets from package dependencies, see 67 | # https://flutter.dev/assets-and-images/#from-packages 68 | 69 | # To add custom fonts to your application, add a fonts section here, 70 | # in this "flutter" section. Each entry in this list should have a 71 | # "family" key with the font family name, and a "fonts" key with a 72 | # list giving the asset and other descriptors for the font. For 73 | # example: 74 | # fonts: 75 | # - family: Schyler 76 | # fonts: 77 | # - asset: fonts/Schyler-Regular.ttf 78 | # - asset: fonts/Schyler-Italic.ttf 79 | # style: italic 80 | # - family: Trajan Pro 81 | # fonts: 82 | # - asset: fonts/TrajanPro.ttf 83 | # - asset: fonts/TrajanPro_Bold.ttf 84 | # weight: 700 85 | # 86 | # For details regarding fonts from package dependencies, 87 | # see https://flutter.dev/custom-fonts/#from-packages 88 | -------------------------------------------------------------------------------- /flutter_fimber/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 in the flutter_test package. 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/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:flutter_fimber_example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Verify Platform version', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that platform version is retrieved. 19 | expect( 20 | find.byWidgetPredicate( 21 | (Widget widget) => widget is Text && 22 | widget.data!.startsWith('Running on:'), 23 | ), 24 | findsOneWidget, 25 | ); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project-level configuration. 2 | cmake_minimum_required(VERSION 3.14) 3 | project(flutter_fimber_example LANGUAGES CXX) 4 | 5 | # The name of the executable created for the application. Change this to change 6 | # the on-disk name of your application. 7 | set(BINARY_NAME "flutter_fimber_example") 8 | 9 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent 10 | # versions of CMake. 11 | cmake_policy(SET CMP0063 NEW) 12 | 13 | # Define build configuration option. 14 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 15 | if(IS_MULTICONFIG) 16 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" 17 | CACHE STRING "" FORCE) 18 | else() 19 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 20 | set(CMAKE_BUILD_TYPE "Debug" CACHE 21 | STRING "Flutter build mode" FORCE) 22 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 23 | "Debug" "Profile" "Release") 24 | endif() 25 | endif() 26 | # Define settings for the Profile build mode. 27 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 28 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") 29 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") 30 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") 31 | 32 | # Use Unicode for all projects. 33 | add_definitions(-DUNICODE -D_UNICODE) 34 | 35 | # Compilation settings that should be applied to most targets. 36 | # 37 | # Be cautious about adding new options here, as plugins use this function by 38 | # default. In most cases, you should add new options to specific targets instead 39 | # of modifying this function. 40 | function(APPLY_STANDARD_SETTINGS TARGET) 41 | target_compile_features(${TARGET} PUBLIC cxx_std_17) 42 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") 43 | target_compile_options(${TARGET} PRIVATE /EHsc) 44 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") 45 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") 46 | endfunction() 47 | 48 | # Flutter library and tool build rules. 49 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 50 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 51 | 52 | # Application build; see runner/CMakeLists.txt. 53 | add_subdirectory("runner") 54 | 55 | # Generated plugin build rules, which manage building the plugins and adding 56 | # them to the application. 57 | include(flutter/generated_plugins.cmake) 58 | 59 | 60 | # === Installation === 61 | # Support files are copied into place next to the executable, so that it can 62 | # run in place. This is done instead of making a separate bundle (as on Linux) 63 | # so that building and running from within Visual Studio will work. 64 | set(BUILD_BUNDLE_DIR "$") 65 | # Make the "install" step default, as it's required to run. 66 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) 67 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 68 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 69 | endif() 70 | 71 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 72 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") 73 | 74 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 75 | COMPONENT Runtime) 76 | 77 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 78 | COMPONENT Runtime) 79 | 80 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 81 | COMPONENT Runtime) 82 | 83 | if(PLUGIN_BUNDLED_LIBRARIES) 84 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 85 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 86 | COMPONENT Runtime) 87 | endif() 88 | 89 | # Fully re-copy the assets directory on each build to avoid having stale files 90 | # from a previous install. 91 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 92 | install(CODE " 93 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 94 | " COMPONENT Runtime) 95 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 96 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 97 | 98 | # Install the AOT library on non-Debug builds only. 99 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 100 | CONFIGURATIONS Profile;Release 101 | COMPONENT Runtime) 102 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.14) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") 12 | 13 | # === Flutter Library === 14 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") 15 | 16 | # Published to parent scope for install step. 17 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 18 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 19 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 20 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) 21 | 22 | list(APPEND FLUTTER_LIBRARY_HEADERS 23 | "flutter_export.h" 24 | "flutter_windows.h" 25 | "flutter_messenger.h" 26 | "flutter_plugin_registrar.h" 27 | "flutter_texture_registrar.h" 28 | ) 29 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") 30 | add_library(flutter INTERFACE) 31 | target_include_directories(flutter INTERFACE 32 | "${EPHEMERAL_DIR}" 33 | ) 34 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") 35 | add_dependencies(flutter flutter_assemble) 36 | 37 | # === Wrapper === 38 | list(APPEND CPP_WRAPPER_SOURCES_CORE 39 | "core_implementations.cc" 40 | "standard_codec.cc" 41 | ) 42 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") 43 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN 44 | "plugin_registrar.cc" 45 | ) 46 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") 47 | list(APPEND CPP_WRAPPER_SOURCES_APP 48 | "flutter_engine.cc" 49 | "flutter_view_controller.cc" 50 | ) 51 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") 52 | 53 | # Wrapper sources needed for a plugin. 54 | add_library(flutter_wrapper_plugin STATIC 55 | ${CPP_WRAPPER_SOURCES_CORE} 56 | ${CPP_WRAPPER_SOURCES_PLUGIN} 57 | ) 58 | apply_standard_settings(flutter_wrapper_plugin) 59 | set_target_properties(flutter_wrapper_plugin PROPERTIES 60 | POSITION_INDEPENDENT_CODE ON) 61 | set_target_properties(flutter_wrapper_plugin PROPERTIES 62 | CXX_VISIBILITY_PRESET hidden) 63 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) 64 | target_include_directories(flutter_wrapper_plugin PUBLIC 65 | "${WRAPPER_ROOT}/include" 66 | ) 67 | add_dependencies(flutter_wrapper_plugin flutter_assemble) 68 | 69 | # Wrapper sources needed for the runner. 70 | add_library(flutter_wrapper_app STATIC 71 | ${CPP_WRAPPER_SOURCES_CORE} 72 | ${CPP_WRAPPER_SOURCES_APP} 73 | ) 74 | apply_standard_settings(flutter_wrapper_app) 75 | target_link_libraries(flutter_wrapper_app PUBLIC flutter) 76 | target_include_directories(flutter_wrapper_app PUBLIC 77 | "${WRAPPER_ROOT}/include" 78 | ) 79 | add_dependencies(flutter_wrapper_app flutter_assemble) 80 | 81 | # === Flutter tool backend === 82 | # _phony_ is a non-existent file to force this command to run every time, 83 | # since currently there's no way to get a full input/output list from the 84 | # flutter tool. 85 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") 86 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) 87 | add_custom_command( 88 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 89 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} 90 | ${CPP_WRAPPER_SOURCES_APP} 91 | ${PHONY_OUTPUT} 92 | COMMAND ${CMAKE_COMMAND} -E env 93 | ${FLUTTER_TOOL_ENVIRONMENT} 94 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" 95 | windows-x64 $ 96 | VERBATIM 97 | ) 98 | add_custom_target(flutter_assemble DEPENDS 99 | "${FLUTTER_LIBRARY}" 100 | ${FLUTTER_LIBRARY_HEADERS} 101 | ${CPP_WRAPPER_SOURCES_CORE} 102 | ${CPP_WRAPPER_SOURCES_PLUGIN} 103 | ${CPP_WRAPPER_SOURCES_APP} 104 | ) 105 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | 10 | void RegisterPlugins(flutter::PluginRegistry* registry) { 11 | } 12 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | ) 7 | 8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 9 | ) 10 | 11 | set(PLUGIN_BUNDLED_LIBRARIES) 12 | 13 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 18 | endforeach(plugin) 19 | 20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 23 | endforeach(ffi_plugin) 24 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(runner LANGUAGES CXX) 3 | 4 | # Define the application target. To change its name, change BINARY_NAME in the 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer 6 | # work. 7 | # 8 | # Any new source files that you add to the application should be added here. 9 | add_executable(${BINARY_NAME} WIN32 10 | "flutter_window.cpp" 11 | "main.cpp" 12 | "utils.cpp" 13 | "win32_window.cpp" 14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 15 | "Runner.rc" 16 | "runner.exe.manifest" 17 | ) 18 | 19 | # Apply the standard set of build settings. This can be removed for applications 20 | # that need different build settings. 21 | apply_standard_settings(${BINARY_NAME}) 22 | 23 | # Add preprocessor definitions for the build version. 24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") 25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") 26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") 27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") 28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") 29 | 30 | # Disable Windows macros that collide with C++ standard library functions. 31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 32 | 33 | # Add dependency libraries and include directories. Add any application-specific 34 | # dependencies here. 35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 36 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 37 | 38 | # Run the Flutter tool portions of the build. This must not be removed. 39 | add_dependencies(${BINARY_NAME} flutter_assemble) 40 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Version 61 | // 62 | 63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) 64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0,0 67 | #endif 68 | 69 | #if defined(FLUTTER_VERSION) 70 | #define VERSION_AS_STRING FLUTTER_VERSION 71 | #else 72 | #define VERSION_AS_STRING "1.0.0" 73 | #endif 74 | 75 | VS_VERSION_INFO VERSIONINFO 76 | FILEVERSION VERSION_AS_NUMBER 77 | PRODUCTVERSION VERSION_AS_NUMBER 78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 79 | #ifdef _DEBUG 80 | FILEFLAGS VS_FF_DEBUG 81 | #else 82 | FILEFLAGS 0x0L 83 | #endif 84 | FILEOS VOS__WINDOWS32 85 | FILETYPE VFT_APP 86 | FILESUBTYPE 0x0L 87 | BEGIN 88 | BLOCK "StringFileInfo" 89 | BEGIN 90 | BLOCK "040904e4" 91 | BEGIN 92 | VALUE "CompanyName", "com.magillus" "\0" 93 | VALUE "FileDescription", "flutter_fimber_example" "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "flutter_fimber_example" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2022 com.magillus. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "flutter_fimber_example.exe" "\0" 98 | VALUE "ProductName", "flutter_fimber_example" "\0" 99 | VALUE "ProductVersion", VERSION_AS_STRING "\0" 100 | END 101 | END 102 | BLOCK "VarFileInfo" 103 | BEGIN 104 | VALUE "Translation", 0x409, 1252 105 | END 106 | END 107 | 108 | #endif // English (United States) resources 109 | ///////////////////////////////////////////////////////////////////////////// 110 | 111 | 112 | 113 | #ifndef APSTUDIO_INVOKED 114 | ///////////////////////////////////////////////////////////////////////////// 115 | // 116 | // Generated from the TEXTINCLUDE 3 resource. 117 | // 118 | 119 | 120 | ///////////////////////////////////////////////////////////////////////////// 121 | #endif // not APSTUDIO_INVOKED 122 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include 4 | 5 | #include "flutter/generated_plugin_registrant.h" 6 | 7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project) 8 | : project_(project) {} 9 | 10 | FlutterWindow::~FlutterWindow() {} 11 | 12 | bool FlutterWindow::OnCreate() { 13 | if (!Win32Window::OnCreate()) { 14 | return false; 15 | } 16 | 17 | RECT frame = GetClientArea(); 18 | 19 | // The size here must match the window dimensions to avoid unnecessary surface 20 | // creation / destruction in the startup path. 21 | flutter_controller_ = std::make_unique( 22 | frame.right - frame.left, frame.bottom - frame.top, project_); 23 | // Ensure that basic setup of the controller was successful. 24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 25 | return false; 26 | } 27 | RegisterPlugins(flutter_controller_->engine()); 28 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 29 | return true; 30 | } 31 | 32 | void FlutterWindow::OnDestroy() { 33 | if (flutter_controller_) { 34 | flutter_controller_ = nullptr; 35 | } 36 | 37 | Win32Window::OnDestroy(); 38 | } 39 | 40 | LRESULT 41 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 42 | WPARAM const wparam, 43 | LPARAM const lparam) noexcept { 44 | // Give Flutter, including plugins, an opportunity to handle window messages. 45 | if (flutter_controller_) { 46 | std::optional result = 47 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 48 | lparam); 49 | if (result) { 50 | return *result; 51 | } 52 | } 53 | 54 | switch (message) { 55 | case WM_FONTCHANGE: 56 | flutter_controller_->engine()->ReloadSystemFonts(); 57 | break; 58 | } 59 | 60 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 61 | } 62 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "win32_window.h" 10 | 11 | // A window that does nothing but host a Flutter view. 12 | class FlutterWindow : public Win32Window { 13 | public: 14 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 15 | explicit FlutterWindow(const flutter::DartProject& project); 16 | virtual ~FlutterWindow(); 17 | 18 | protected: 19 | // Win32Window: 20 | bool OnCreate() override; 21 | void OnDestroy() override; 22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 23 | LPARAM const lparam) noexcept override; 24 | 25 | private: 26 | // The project to run. 27 | flutter::DartProject project_; 28 | 29 | // The Flutter instance hosted by this window. 30 | std::unique_ptr flutter_controller_; 31 | }; 32 | 33 | #endif // RUNNER_FLUTTER_WINDOW_H_ 34 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "utils.h" 7 | 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 9 | _In_ wchar_t *command_line, _In_ int show_command) { 10 | // Attach to console when present (e.g., 'flutter run') or create a 11 | // new console when running with a debugger. 12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 13 | CreateAndAttachConsole(); 14 | } 15 | 16 | // Initialize COM, so that it is available for use in the library and/or 17 | // plugins. 18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 19 | 20 | flutter::DartProject project(L"data"); 21 | 22 | std::vector command_line_arguments = 23 | GetCommandLineArguments(); 24 | 25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 26 | 27 | FlutterWindow window(project); 28 | Win32Window::Point origin(10, 10); 29 | Win32Window::Size size(1280, 720); 30 | if (!window.CreateAndShow(L"flutter_fimber_example", origin, size)) { 31 | return EXIT_FAILURE; 32 | } 33 | window.SetQuitOnClose(true); 34 | 35 | ::MSG msg; 36 | while (::GetMessage(&msg, nullptr, 0, 0)) { 37 | ::TranslateMessage(&msg); 38 | ::DispatchMessage(&msg); 39 | } 40 | 41 | ::CoUninitialize(); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/example/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /flutter_fimber/example/windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr); 51 | std::string utf8_string; 52 | if (target_length == 0 || target_length > utf8_string.max_size()) { 53 | return utf8_string; 54 | } 55 | utf8_string.resize(target_length); 56 | int converted_length = ::WideCharToMultiByte( 57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 58 | -1, utf8_string.data(), 59 | target_length, nullptr, nullptr); 60 | if (converted_length == 0) { 61 | return std::string(); 62 | } 63 | return utf8_string; 64 | } 65 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /flutter_fimber/example/windows/runner/win32_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_WIN32_WINDOW_H_ 2 | #define RUNNER_WIN32_WINDOW_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be 11 | // inherited from by classes that wish to specialize with custom 12 | // rendering and input handling 13 | class Win32Window { 14 | public: 15 | struct Point { 16 | unsigned int x; 17 | unsigned int y; 18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {} 19 | }; 20 | 21 | struct Size { 22 | unsigned int width; 23 | unsigned int height; 24 | Size(unsigned int width, unsigned int height) 25 | : width(width), height(height) {} 26 | }; 27 | 28 | Win32Window(); 29 | virtual ~Win32Window(); 30 | 31 | // Creates and shows a win32 window with |title| and position and size using 32 | // |origin| and |size|. New windows are created on the default monitor. Window 33 | // sizes are specified to the OS in physical pixels, hence to ensure a 34 | // consistent size to will treat the width height passed in to this function 35 | // as logical pixels and scale to appropriate for the default monitor. Returns 36 | // true if the window was created successfully. 37 | bool CreateAndShow(const std::wstring& title, 38 | const Point& origin, 39 | const Size& size); 40 | 41 | // Release OS resources associated with window. 42 | void Destroy(); 43 | 44 | // Inserts |content| into the window tree. 45 | void SetChildContent(HWND content); 46 | 47 | // Returns the backing Window handle to enable clients to set icon and other 48 | // window properties. Returns nullptr if the window has been destroyed. 49 | HWND GetHandle(); 50 | 51 | // If true, closing this window will quit the application. 52 | void SetQuitOnClose(bool quit_on_close); 53 | 54 | // Return a RECT representing the bounds of the current client area. 55 | RECT GetClientArea(); 56 | 57 | protected: 58 | // Processes and route salient window messages for mouse handling, 59 | // size change and DPI. Delegates handling of these to member overloads that 60 | // inheriting classes can handle. 61 | virtual LRESULT MessageHandler(HWND window, 62 | UINT const message, 63 | WPARAM const wparam, 64 | LPARAM const lparam) noexcept; 65 | 66 | // Called when CreateAndShow is called, allowing subclass window-related 67 | // setup. Subclasses should return false if setup fails. 68 | virtual bool OnCreate(); 69 | 70 | // Called when Destroy is called. 71 | virtual void OnDestroy(); 72 | 73 | private: 74 | friend class WindowClassRegistrar; 75 | 76 | // OS callback called by message pump. Handles the WM_NCCREATE message which 77 | // is passed when the non-client area is being created and enables automatic 78 | // non-client DPI scaling so that the non-client area automatically 79 | // responsponds to changes in DPI. All other messages are handled by 80 | // MessageHandler. 81 | static LRESULT CALLBACK WndProc(HWND const window, 82 | UINT const message, 83 | WPARAM const wparam, 84 | LPARAM const lparam) noexcept; 85 | 86 | // Retrieves a class instance pointer for |window| 87 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 88 | 89 | bool quit_on_close_ = false; 90 | 91 | // window handle for top level window. 92 | HWND window_handle_ = nullptr; 93 | 94 | // window handle for hosted content. 95 | HWND child_content_ = nullptr; 96 | }; 97 | 98 | #endif // RUNNER_WIN32_WINDOW_H_ 99 | -------------------------------------------------------------------------------- /flutter_fimber/ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | /Flutter/ephemeral/ 38 | /Flutter/flutter_export_environment.sh -------------------------------------------------------------------------------- /flutter_fimber/ios/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magillus/flutter-fimber/e8158b1156ae9211970b5849d87fa2f3f84efa87/flutter_fimber/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /flutter_fimber/ios/Classes/FlutterFimberPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface FlutterFimberPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /flutter_fimber/ios/Classes/FlutterFimberPlugin.m: -------------------------------------------------------------------------------- 1 | #import "FlutterFimberPlugin.h" 2 | #import 3 | 4 | @implementation FlutterFimberPlugin 5 | + (void)registerWithRegistrar:(NSObject*)registrar { 6 | [SwiftFlutterFimberPlugin registerWithRegistrar:registrar]; 7 | } 8 | @end 9 | -------------------------------------------------------------------------------- /flutter_fimber/ios/Classes/SwiftFlutterFimberPlugin.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | public class SwiftFlutterFimberPlugin: NSObject, FlutterPlugin { 5 | public static func register(with registrar: FlutterPluginRegistrar) { 6 | let channel = FlutterMethodChannel(name: "flutter_fimber", binaryMessenger: registrar.messenger()) 7 | let instance = SwiftFlutterFimberPlugin() 8 | registrar.addMethodCallDelegate(instance, channel: channel) 9 | } 10 | 11 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 12 | switch call.method { 13 | case "log": 14 | let data = call.arguments as! NSDictionary 15 | let concatMessage = concatLogMessage(with: data) 16 | if (!concatMessage.isEmpty) { 17 | print(concatMessage) 18 | } 19 | result(0) 20 | default: 21 | result(FlutterMethodNotImplemented) 22 | } 23 | } 24 | 25 | private func concatLogMessage(with data: NSDictionary) -> String { 26 | var result: String = "" 27 | let message = (data["message"] as? String) ?? "" 28 | if (!message.isEmpty) { 29 | result += "\(Date())" 30 | 31 | let tag = (data["tag"] as? String) ?? "flutter" 32 | result += " \(tag)" 33 | 34 | let level = (data["level"] as? String) ?? "D" 35 | result += "/\(level)" 36 | 37 | // TODO: Disabled preFix since XCode doesn't support colorized console logging 38 | // let preFix = (data["preFix"] as? String) ?? "" 39 | // if (!preFix.isEmpty) { 40 | // result += "\(preFix)" 41 | // } 42 | result += " \(message)" 43 | 44 | // TODO: Disabled postFix since XCode doesn't support colorized console logging 45 | // let postFix = (data["postFix"] as? String) ?? "" 46 | // if (!postFix.isEmpty) { 47 | // result += "\(postFix)" 48 | // } 49 | 50 | let exDump = (data["ex"] as? String) ?? "" 51 | if (!exDump.isEmpty) { 52 | result += "\n\(exDump)" 53 | } 54 | } 55 | return result 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /flutter_fimber/ios/flutter_fimber.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. 3 | # Run `pod lib lint flutter_fimber.podspec` to validate before publishing. 4 | # 5 | Pod::Spec.new do |s| 6 | s.name = 'flutter_fimber' 7 | s.version = '0.0.1' 8 | s.summary = 'A new Flutter plugin project.' 9 | s.description = <<-DESC 10 | A new Flutter plugin project. 11 | DESC 12 | s.homepage = 'http://example.com' 13 | s.license = { :file => '../LICENSE' } 14 | s.author = { 'Your Company' => 'email@example.com' } 15 | s.source = { :path => '.' } 16 | s.source_files = 'Classes/**/*' 17 | s.dependency 'Flutter' 18 | s.platform = :ios, '11.0' 19 | 20 | # Flutter.framework does not contain a i386 slice. 21 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } 22 | s.swift_version = '5.0' 23 | end 24 | -------------------------------------------------------------------------------- /flutter_fimber/lib/flutter_fimber.dart: -------------------------------------------------------------------------------- 1 | export 'package:fimber/fimber.dart'; 2 | export 'src/flutter_fimber_base.dart'; 3 | -------------------------------------------------------------------------------- /flutter_fimber/lib/flutter_fimber_method_channel.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'flutter_fimber_platform_interface.dart'; 5 | 6 | /// An implementation of [FlutterFimberPlatform] that uses method channels. 7 | class MethodChannelFlutterFimber extends FlutterFimberPlatform { 8 | /// The method channel used to interact with the native platform. 9 | @visibleForTesting 10 | final methodChannel = const MethodChannel('flutter_fimber'); 11 | 12 | @override 13 | Future getPlatformVersion() async { 14 | final version = 15 | await methodChannel.invokeMethod('getPlatformVersion'); 16 | return version; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /flutter_fimber/lib/flutter_fimber_platform_interface.dart: -------------------------------------------------------------------------------- 1 | import 'package:plugin_platform_interface/plugin_platform_interface.dart'; 2 | 3 | import 'flutter_fimber_method_channel.dart'; 4 | 5 | abstract class FlutterFimberPlatform extends PlatformInterface { 6 | /// Constructs a FlutterFimberPlatform. 7 | FlutterFimberPlatform() : super(token: _token); 8 | 9 | static final Object _token = Object(); 10 | 11 | static FlutterFimberPlatform _instance = MethodChannelFlutterFimber(); 12 | 13 | /// The default instance of [FlutterFimberPlatform] to use. 14 | /// 15 | /// Defaults to [MethodChannelFlutterFimber]. 16 | static FlutterFimberPlatform get instance => _instance; 17 | 18 | /// Platform-specific implementations should set this with their own 19 | /// platform-specific class that extends [FlutterFimberPlatform] when 20 | /// they register themselves. 21 | static set instance(FlutterFimberPlatform instance) { 22 | PlatformInterface.verifyToken(instance, _token); 23 | _instance = instance; 24 | } 25 | 26 | Future getPlatformVersion() { 27 | throw UnimplementedError('platformVersion() has not been implemented.'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /flutter_fimber/lib/src/flutter_fimber_base.dart: -------------------------------------------------------------------------------- 1 | import 'package:fimber/fimber.dart'; 2 | import 'package:flutter/foundation.dart'; 3 | import 'package:flutter/services.dart'; 4 | 5 | /// Fimber logging tree for specific platform. 6 | /// For Android it uses Android Log with corresponding levels and formatting 7 | class FimberTree extends LogTree { 8 | /// Default log levels. 9 | static const List defaultLevels = ["D", "I", "W", "E"]; 10 | static final Map _defaultColorizeMap = { 11 | "V": ColorizeStyle([AnsiStyle.foreground(AnsiColor.blue)]), 12 | "D": ColorizeStyle([AnsiStyle.foreground(AnsiColor.green)]), 13 | "W": ColorizeStyle([ 14 | AnsiStyle.foreground(AnsiColor.yellow), 15 | AnsiStyle.background(AnsiColor.black) 16 | ]), 17 | "E": ColorizeStyle([ 18 | AnsiStyle.bright(AnsiColor.white), 19 | AnsiStyle.background(AnsiColor.red) 20 | ]) 21 | }; 22 | 23 | /// Log levels for this Log Tree 24 | List logLevels; 25 | 26 | /// Toggle to use colors scheme for ANSI style. 27 | bool useColors = false; 28 | 29 | /// Optional list of Color style per each level. 30 | Map colorizeMap = {}; 31 | 32 | /// Creates instance of FimberTree 33 | /// with optional allowed [logLevels] and [useColors] flag. 34 | FimberTree({this.logLevels = defaultLevels, this.useColors = false}) { 35 | if (useColors) { 36 | colorizeMap = _defaultColorizeMap; 37 | } 38 | } 39 | 40 | /// Logs [message] with log [level] 41 | /// and optional [tag], [ex] (exception) and [stacktrace] 42 | @override 43 | void log(String level, String message, 44 | {String? tag, dynamic ex, StackTrace? stacktrace}) { 45 | var logTag = tag ?? LogTree.getTag(); 46 | String? exDump; 47 | if (ex != null) { 48 | var tmpStacktrace = 49 | stacktrace?.toString().split('\n') ?? LogTree.getStacktrace(); 50 | var stackTraceMessage = 51 | tmpStacktrace.map((stackLine) => "\t$stackLine").join("\n"); 52 | exDump = "${ex.toString()} \n$stackTraceMessage"; 53 | } 54 | String? postFix, preFix; 55 | if (useColors) { 56 | var colorizeWrapper = _defaultColorizeMap[level]; 57 | if (colorizeWrapper != null) { 58 | var postPrefix = 59 | colorizeWrapper.wrap("PREFIX_SPLITTER").split("PREFIX_SPLITTER"); 60 | if (postPrefix.length == 2) { 61 | preFix = postPrefix[0]; 62 | postFix = postPrefix[1]; 63 | } 64 | } 65 | } 66 | var logLine = LogLine(level, logTag, message, 67 | exceptionDump: exDump, postFix: postFix, preFix: preFix); 68 | var invokeMsg = logLine.toMsg(); 69 | _channel.invokeMethod("log", invokeMsg); 70 | } 71 | 72 | @override 73 | List getLevels() { 74 | return logLevels; 75 | } 76 | 77 | /// Method channel to send log information to native OS to handle. 78 | static const MethodChannel _channel = MethodChannel('flutter_fimber'); 79 | } 80 | 81 | /// Transport object to native value 82 | class LogLine { 83 | /// Log level 84 | String level; 85 | 86 | /// Log tag 87 | String tag; 88 | 89 | /// Log message 90 | String message; 91 | 92 | /// Exception dump if attached to log line. 93 | String? exceptionDump; 94 | 95 | /// Log line prefix. 96 | String? preFix; 97 | 98 | /// Log line postfix. 99 | String? postFix; 100 | 101 | /// Creates instance of [LogLine] with optional fields. 102 | LogLine(this.level, this.tag, this.message, 103 | {this.exceptionDump, this.preFix, this.postFix}); 104 | 105 | /// Serializes the [LogLine] to Byte array 106 | ByteData serialize() { 107 | var buffer = WriteBuffer(); 108 | _putString(buffer, level); 109 | _putString(buffer, tag); 110 | _putString(buffer, message); 111 | _putString(buffer, exceptionDump ?? ""); 112 | _putString(buffer, preFix ?? ""); 113 | _putString(buffer, postFix ?? ""); 114 | return buffer.done(); 115 | } 116 | 117 | _putString(WriteBuffer buffer, String value) { 118 | buffer.putUint8(0xfe); 119 | buffer.putInt32(value.length); 120 | value.runes.map((rune) { 121 | buffer.putInt32(rune); 122 | }); 123 | } 124 | 125 | /// to use with method call 126 | dynamic toMsg() { 127 | return { 128 | "level": level, 129 | "tag": tag, 130 | "message": message, 131 | "ex": exceptionDump, 132 | "preFix": preFix, 133 | "postFix": postFix 134 | }; 135 | } 136 | } 137 | 138 | /// Logging tree that uses `debugPrint` 139 | /// which is not skipping log lines printed on Android 140 | /// https://flutter.io/docs/testing/debugging#print-and-debugprint-with-flutter-logs 141 | class DebugBufferTree extends DebugTree { 142 | /// Max limit that a log can reach to start dividing it into multiple chunks 143 | /// avoiding them to be cut by android log 144 | /// - when -1 will disable chunking of the logs 145 | final int maxLineSize; 146 | 147 | /// Creates Debug Tree compatible with Android. 148 | DebugBufferTree({ 149 | int printTimeType = DebugTree.timeClockType, 150 | List logLevels = DebugTree.defaultLevels, 151 | this.maxLineSize = 800, 152 | }) : super(printTimeType: printTimeType, logLevels: logLevels); 153 | 154 | /// Creates elapsed time Debug Tree compatible with Android. 155 | factory DebugBufferTree.elapsed( 156 | {List logLevels = DebugTree.defaultLevels}) { 157 | return DebugBufferTree( 158 | logLevels: logLevels, printTimeType: DebugTree.timeElapsedType); 159 | } 160 | 161 | /// prints log lines breaking them into multiple lines if its too long. 162 | /// src: https://github.com/flutter/flutter/issues/22665#issuecomment-458186456 163 | @override 164 | void printLog(String logLine, {String? level}) { 165 | if (maxLineSize == -1) { 166 | debugPrint(logLine); 167 | } else { 168 | final pattern = RegExp('.{1,$maxLineSize}'); 169 | 170 | pattern 171 | .allMatches(logLine) 172 | .forEach((match) => debugPrint(match.group(0))); 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /flutter_fimber/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The Flutter tooling requires that developers have CMake 3.10 or later 2 | # installed. You should not increase this version, as doing so will cause 3 | # the plugin to fail to compile for some customers of the plugin. 4 | cmake_minimum_required(VERSION 3.10) 5 | 6 | # Project-level configuration. 7 | set(PROJECT_NAME "flutter_fimber") 8 | project(${PROJECT_NAME} LANGUAGES CXX) 9 | 10 | # This value is used when generating builds using this plugin, so it must 11 | # not be changed. 12 | set(PLUGIN_NAME "flutter_fimber_plugin") 13 | 14 | # Define the plugin library target. Its name must not be changed (see comment 15 | # on PLUGIN_NAME above). 16 | # 17 | # Any new source files that you add to the plugin should be added here. 18 | add_library(${PLUGIN_NAME} SHARED 19 | "flutter_fimber_plugin.cc" 20 | ) 21 | 22 | # Apply a standard set of build settings that are configured in the 23 | # application-level CMakeLists.txt. This can be removed for plugins that want 24 | # full control over build settings. 25 | apply_standard_settings(${PLUGIN_NAME}) 26 | 27 | # Symbols are hidden by default to reduce the chance of accidental conflicts 28 | # between plugins. This should not be removed; any symbols that should be 29 | # exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro. 30 | set_target_properties(${PLUGIN_NAME} PROPERTIES 31 | CXX_VISIBILITY_PRESET hidden) 32 | target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) 33 | 34 | # Source include directories and library dependencies. Add any plugin-specific 35 | # dependencies here. 36 | target_include_directories(${PLUGIN_NAME} INTERFACE 37 | "${CMAKE_CURRENT_SOURCE_DIR}/include") 38 | target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) 39 | target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) 40 | 41 | # List of absolute paths to libraries that should be bundled with the plugin. 42 | # This list could contain prebuilt libraries, or libraries created by an 43 | # external build triggered from this build file. 44 | set(flutter_fimber_bundled_libraries 45 | "" 46 | PARENT_SCOPE 47 | ) 48 | -------------------------------------------------------------------------------- /flutter_fimber/linux/flutter_fimber_plugin.cc: -------------------------------------------------------------------------------- 1 | #include "include/flutter_fimber/flutter_fimber_plugin.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #define FLUTTER_FIMBER_PLUGIN(obj) \ 10 | (G_TYPE_CHECK_INSTANCE_CAST((obj), flutter_fimber_plugin_get_type(), \ 11 | FlutterFimberPlugin)) 12 | 13 | struct _FlutterFimberPlugin { 14 | GObject parent_instance; 15 | }; 16 | 17 | G_DEFINE_TYPE(FlutterFimberPlugin, flutter_fimber_plugin, g_object_get_type()) 18 | 19 | // Called when a method call is received from Flutter. 20 | static void flutter_fimber_plugin_handle_method_call( 21 | FlutterFimberPlugin* self, 22 | FlMethodCall* method_call) { 23 | g_autoptr(FlMethodResponse) response = nullptr; 24 | 25 | const gchar* method = fl_method_call_get_name(method_call); 26 | 27 | if (strcmp(method, "getPlatformVersion") == 0) { 28 | struct utsname uname_data = {}; 29 | uname(&uname_data); 30 | g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version); 31 | g_autoptr(FlValue) result = fl_value_new_string(version); 32 | response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); 33 | } else { 34 | response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); 35 | } 36 | 37 | fl_method_call_respond(method_call, response, nullptr); 38 | } 39 | 40 | static void flutter_fimber_plugin_dispose(GObject* object) { 41 | G_OBJECT_CLASS(flutter_fimber_plugin_parent_class)->dispose(object); 42 | } 43 | 44 | static void flutter_fimber_plugin_class_init(FlutterFimberPluginClass* klass) { 45 | G_OBJECT_CLASS(klass)->dispose = flutter_fimber_plugin_dispose; 46 | } 47 | 48 | static void flutter_fimber_plugin_init(FlutterFimberPlugin* self) {} 49 | 50 | static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call, 51 | gpointer user_data) { 52 | FlutterFimberPlugin* plugin = FLUTTER_FIMBER_PLUGIN(user_data); 53 | flutter_fimber_plugin_handle_method_call(plugin, method_call); 54 | } 55 | 56 | void flutter_fimber_plugin_register_with_registrar(FlPluginRegistrar* registrar) { 57 | FlutterFimberPlugin* plugin = FLUTTER_FIMBER_PLUGIN( 58 | g_object_new(flutter_fimber_plugin_get_type(), nullptr)); 59 | 60 | g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); 61 | g_autoptr(FlMethodChannel) channel = 62 | fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar), 63 | "flutter_fimber", 64 | FL_METHOD_CODEC(codec)); 65 | fl_method_channel_set_method_call_handler(channel, method_call_cb, 66 | g_object_ref(plugin), 67 | g_object_unref); 68 | 69 | g_object_unref(plugin); 70 | } 71 | -------------------------------------------------------------------------------- /flutter_fimber/linux/include/flutter_fimber/flutter_fimber_plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_PLUGIN_FLUTTER_FIMBER_PLUGIN_H_ 2 | #define FLUTTER_PLUGIN_FLUTTER_FIMBER_PLUGIN_H_ 3 | 4 | #include 5 | 6 | G_BEGIN_DECLS 7 | 8 | #ifdef FLUTTER_PLUGIN_IMPL 9 | #define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) 10 | #else 11 | #define FLUTTER_PLUGIN_EXPORT 12 | #endif 13 | 14 | typedef struct _FlutterFimberPlugin FlutterFimberPlugin; 15 | typedef struct { 16 | GObjectClass parent_class; 17 | } FlutterFimberPluginClass; 18 | 19 | FLUTTER_PLUGIN_EXPORT GType flutter_fimber_plugin_get_type(); 20 | 21 | FLUTTER_PLUGIN_EXPORT void flutter_fimber_plugin_register_with_registrar( 22 | FlPluginRegistrar* registrar); 23 | 24 | G_END_DECLS 25 | 26 | #endif // FLUTTER_PLUGIN_FLUTTER_FIMBER_PLUGIN_H_ 27 | -------------------------------------------------------------------------------- /flutter_fimber/macos/Classes/FlutterFimberPlugin.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | public class FlutterFimberPlugin: NSObject, FlutterPlugin { 5 | public static func register(with registrar: FlutterPluginRegistrar) { 6 | let channel = FlutterMethodChannel(name: "flutter_fimber", binaryMessenger: registrar.messenger) 7 | let instance = FlutterFimberPlugin() 8 | registrar.addMethodCallDelegate(instance, channel: channel) 9 | } 10 | 11 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 12 | switch call.method { 13 | case "getPlatformVersion": 14 | result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString) 15 | default: 16 | result(FlutterMethodNotImplemented) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /flutter_fimber/macos/flutter_fimber.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. 3 | # Run `pod lib lint flutter_fimber.podspec` to validate before publishing. 4 | # 5 | Pod::Spec.new do |s| 6 | s.name = 'flutter_fimber' 7 | s.version = '0.0.1' 8 | s.summary = 'A new Flutter plugin project.' 9 | s.description = <<-DESC 10 | A new Flutter plugin project. 11 | DESC 12 | s.homepage = 'http://example.com' 13 | s.license = { :file => '../LICENSE' } 14 | s.author = { 'Your Company' => 'email@example.com' } 15 | 16 | s.source = { :path => '.' } 17 | s.source_files = 'Classes/**/*' 18 | s.dependency 'FlutterMacOS' 19 | 20 | s.platform = :osx, '10.11' 21 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } 22 | s.swift_version = '5.0' 23 | end 24 | -------------------------------------------------------------------------------- /flutter_fimber/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_fimber 2 | description: Flutter extension for Fimber logging API, it will use native OS Logging statements via channel. 3 | version: 0.7.0 4 | homepage: https://github.com/magillus/flutter-fimber 5 | 6 | environment: 7 | sdk: ">=2.12.0 <4.0.0" 8 | flutter: '>=2.0.0' 9 | 10 | dependencies: 11 | plugin_platform_interface: ^2.1.4 12 | flutter: 13 | sdk: flutter 14 | fimber: ^0.7.0 15 | 16 | dev_dependencies: 17 | test: '^1.24.1' 18 | flutter_lints: '^2.0.0' 19 | flutter_test: 20 | sdk: flutter 21 | 22 | # The following section is specific to Flutter packages. 23 | flutter: 24 | # This section identifies this Flutter project as a plugin project. 25 | # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) 26 | # which should be registered in the plugin registry. This is required for 27 | # using method channels. 28 | # The Android 'package' specifies package in which the registered class is. 29 | # This is required for using method channels on Android. 30 | # The 'ffiPlugin' specifies that native code should be built and bundled. 31 | # This is required for using `dart:ffi`. 32 | # All these are used by the tooling to maintain consistency when 33 | # adding or updating assets for this project. 34 | plugin: 35 | platforms: 36 | android: 37 | package: com.magillus.flutter_fimber 38 | pluginClass: FlutterFimberPlugin 39 | ios: 40 | pluginClass: FlutterFimberPlugin 41 | -------------------------------------------------------------------------------- /flutter_fimber/test/flutter_fimber_method_channel_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:flutter/widgets.dart'; 3 | import 'package:flutter_fimber/flutter_fimber_method_channel.dart'; 4 | import 'package:test/test.dart'; 5 | 6 | void main() { 7 | MethodChannelFlutterFimber platform = MethodChannelFlutterFimber(); 8 | const MethodChannel channel = MethodChannel('flutter_fimber'); 9 | 10 | setUp(() { 11 | WidgetsFlutterBinding.ensureInitialized(); 12 | 13 | channel.setMethodCallHandler((MethodCall methodCall) async { 14 | return '42'; 15 | }); 16 | }); 17 | 18 | tearDown(() { 19 | channel.setMethodCallHandler(null); 20 | }); 21 | 22 | test('getPlatformVersion', () async { 23 | expect(await platform.getPlatformVersion(), '42'); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /flutter_fimber/test/flutter_fimber_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:test/test.dart'; 2 | import 'package:flutter_fimber/flutter_fimber_platform_interface.dart'; 3 | import 'package:flutter_fimber/flutter_fimber_method_channel.dart'; 4 | 5 | void main() { 6 | final FlutterFimberPlatform initialPlatform = FlutterFimberPlatform.instance; 7 | 8 | test('$MethodChannelFlutterFimber is the default instance', () { 9 | expect(initialPlatform, isInstanceOf()); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /flutter_fimber/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /flutter_fimber/windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The Flutter tooling requires that developers have a version of Visual Studio 2 | # installed that includes CMake 3.14 or later. You should not increase this 3 | # version, as doing so will cause the plugin to fail to compile for some 4 | # customers of the plugin. 5 | cmake_minimum_required(VERSION 3.14) 6 | 7 | # Project-level configuration. 8 | set(PROJECT_NAME "flutter_fimber") 9 | project(${PROJECT_NAME} LANGUAGES CXX) 10 | 11 | # This value is used when generating builds using this plugin, so it must 12 | # not be changed 13 | set(PLUGIN_NAME "flutter_fimber_plugin") 14 | 15 | # Any new source files that you add to the plugin should be added here. 16 | list(APPEND PLUGIN_SOURCES 17 | "flutter_fimber_plugin.cpp" 18 | "flutter_fimber_plugin.h" 19 | ) 20 | 21 | # Define the plugin library target. Its name must not be changed (see comment 22 | # on PLUGIN_NAME above). 23 | add_library(${PLUGIN_NAME} SHARED 24 | "include/flutter_fimber/flutter_fimber_plugin_c_api.h" 25 | "flutter_fimber_plugin_c_api.cpp" 26 | ${PLUGIN_SOURCES} 27 | ) 28 | 29 | # Apply a standard set of build settings that are configured in the 30 | # application-level CMakeLists.txt. This can be removed for plugins that want 31 | # full control over build settings. 32 | apply_standard_settings(${PLUGIN_NAME}) 33 | 34 | # Symbols are hidden by default to reduce the chance of accidental conflicts 35 | # between plugins. This should not be removed; any symbols that should be 36 | # exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro. 37 | set_target_properties(${PLUGIN_NAME} PROPERTIES 38 | CXX_VISIBILITY_PRESET hidden) 39 | target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) 40 | 41 | # Source include directories and library dependencies. Add any plugin-specific 42 | # dependencies here. 43 | target_include_directories(${PLUGIN_NAME} INTERFACE 44 | "${CMAKE_CURRENT_SOURCE_DIR}/include") 45 | target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) 46 | 47 | # List of absolute paths to libraries that should be bundled with the plugin. 48 | # This list could contain prebuilt libraries, or libraries created by an 49 | # external build triggered from this build file. 50 | set(flutter_fimber_bundled_libraries 51 | "" 52 | PARENT_SCOPE 53 | ) 54 | -------------------------------------------------------------------------------- /flutter_fimber/windows/flutter_fimber_plugin.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_fimber_plugin.h" 2 | 3 | // This must be included before many other Windows headers. 4 | #include 5 | 6 | // For getPlatformVersion; remove unless needed for your plugin implementation. 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | namespace flutter_fimber { 17 | 18 | // static 19 | void FlutterFimberPlugin::RegisterWithRegistrar( 20 | flutter::PluginRegistrarWindows *registrar) { 21 | auto channel = 22 | std::make_unique>( 23 | registrar->messenger(), "flutter_fimber", 24 | &flutter::StandardMethodCodec::GetInstance()); 25 | 26 | auto plugin = std::make_unique(); 27 | 28 | channel->SetMethodCallHandler( 29 | [plugin_pointer = plugin.get()](const auto &call, auto result) { 30 | plugin_pointer->HandleMethodCall(call, std::move(result)); 31 | }); 32 | 33 | registrar->AddPlugin(std::move(plugin)); 34 | } 35 | 36 | FlutterFimberPlugin::FlutterFimberPlugin() {} 37 | 38 | FlutterFimberPlugin::~FlutterFimberPlugin() {} 39 | 40 | void FlutterFimberPlugin::HandleMethodCall( 41 | const flutter::MethodCall &method_call, 42 | std::unique_ptr> result) { 43 | if (method_call.method_name().compare("getPlatformVersion") == 0) { 44 | std::ostringstream version_stream; 45 | version_stream << "Windows "; 46 | if (IsWindows10OrGreater()) { 47 | version_stream << "10+"; 48 | } else if (IsWindows8OrGreater()) { 49 | version_stream << "8"; 50 | } else if (IsWindows7OrGreater()) { 51 | version_stream << "7"; 52 | } 53 | result->Success(flutter::EncodableValue(version_stream.str())); 54 | } else { 55 | result->NotImplemented(); 56 | } 57 | } 58 | 59 | } // namespace flutter_fimber 60 | -------------------------------------------------------------------------------- /flutter_fimber/windows/flutter_fimber_plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_PLUGIN_FLUTTER_FIMBER_PLUGIN_H_ 2 | #define FLUTTER_PLUGIN_FLUTTER_FIMBER_PLUGIN_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace flutter_fimber { 10 | 11 | class FlutterFimberPlugin : public flutter::Plugin { 12 | public: 13 | static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); 14 | 15 | FlutterFimberPlugin(); 16 | 17 | virtual ~FlutterFimberPlugin(); 18 | 19 | // Disallow copy and assign. 20 | FlutterFimberPlugin(const FlutterFimberPlugin&) = delete; 21 | FlutterFimberPlugin& operator=(const FlutterFimberPlugin&) = delete; 22 | 23 | private: 24 | // Called when a method is called on this plugin's channel from Dart. 25 | void HandleMethodCall( 26 | const flutter::MethodCall &method_call, 27 | std::unique_ptr> result); 28 | }; 29 | 30 | } // namespace flutter_fimber 31 | 32 | #endif // FLUTTER_PLUGIN_FLUTTER_FIMBER_PLUGIN_H_ 33 | -------------------------------------------------------------------------------- /flutter_fimber/windows/flutter_fimber_plugin_c_api.cpp: -------------------------------------------------------------------------------- 1 | #include "include/flutter_fimber/flutter_fimber_plugin_c_api.h" 2 | 3 | #include 4 | 5 | #include "flutter_fimber_plugin.h" 6 | 7 | void FlutterFimberPluginCApiRegisterWithRegistrar( 8 | FlutterDesktopPluginRegistrarRef registrar) { 9 | flutter_fimber::FlutterFimberPlugin::RegisterWithRegistrar( 10 | flutter::PluginRegistrarManager::GetInstance() 11 | ->GetRegistrar(registrar)); 12 | } 13 | -------------------------------------------------------------------------------- /flutter_fimber/windows/include/flutter_fimber/flutter_fimber_plugin_c_api.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_PLUGIN_FLUTTER_FIMBER_PLUGIN_C_API_H_ 2 | #define FLUTTER_PLUGIN_FLUTTER_FIMBER_PLUGIN_C_API_H_ 3 | 4 | #include 5 | 6 | #ifdef FLUTTER_PLUGIN_IMPL 7 | #define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) 8 | #else 9 | #define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) 10 | #endif 11 | 12 | #if defined(__cplusplus) 13 | extern "C" { 14 | #endif 15 | 16 | FLUTTER_PLUGIN_EXPORT void FlutterFimberPluginCApiRegisterWithRegistrar( 17 | FlutterDesktopPluginRegistrarRef registrar); 18 | 19 | #if defined(__cplusplus) 20 | } // extern "C" 21 | #endif 22 | 23 | #endif // FLUTTER_PLUGIN_FLUTTER_FIMBER_PLUGIN_C_API_H_ 24 | --------------------------------------------------------------------------------