├── .github
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── deploy-dev-android.yml
│ ├── deploy-dev-ios.yml
│ ├── deploy-prod-android.yml
│ ├── deploy-prod-ios.yml
│ ├── deploy-stage-android.yml
│ ├── deploy-stage-ios.yml
│ └── pr-check.yml
├── .gitignore
├── .metadata
├── .vscode
├── launch.json
└── settings.json
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
├── .gitignore
├── Gemfile
├── Gemfile.lock
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── development
│ │ └── 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
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── hadibucopy
│ │ │ │ └── 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
│ │ └── staging
│ │ └── 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
├── build.gradle
├── fastlane
│ ├── Appfile
│ ├── Fastfile
│ ├── Pluginfile
│ ├── README.md
│ └── report.xml
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── images
├── android
│ └── app-src.png
├── firebase
│ └── apps.png
├── github
│ ├── github-create-runner.png
│ ├── github-runners.png
│ └── github-settings.png
└── ios
│ ├── ios-bundle-id.png
│ ├── ios-create-new-scheme.png
│ ├── ios-display-name-2.png
│ ├── ios-display-name.png
│ ├── ios-runner-config.png
│ ├── ios-scheme.png
│ └── ios-schemes.png
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── Runner.xcscheme
│ │ ├── development.xcscheme
│ │ ├── production.xcscheme
│ │ └── staging.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
└── fastlane
│ └── Fastfile
├── lib
├── base
│ └── config
│ │ ├── flavor_config.dart
│ │ └── flavor_const.dart
├── bootstrap.dart
├── common
│ └── exception
│ │ └── unknown_device.dart
└── 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
├── 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
└── RunnerTests
│ └── RunnerTests.swift
├── pubspec.lock
├── pubspec.yaml
├── test
└── widget_test.dart
├── web
├── favicon.png
├── icons
│ ├── Icon-192.png
│ ├── Icon-512.png
│ ├── Icon-maskable-192.png
│ └── Icon-maskable-512.png
├── index.html
└── manifest.json
└── 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
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 |
4 |
5 | ## Type of Change
6 |
7 |
8 |
9 | - [ ] ✨ New feature (non-breaking change which adds functionality)
10 | - [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
11 | - [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change)
12 | - [ ] 🧹 Code refactor
13 | - [ ] ✅ Build configuration change
14 | - [ ] 📝 Documentation
15 | - [ ] 🗑️ Chore
16 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-dev-android.yml:
--------------------------------------------------------------------------------
1 | name: Android Release - Development
2 |
3 | on:
4 | pull_request:
5 | branches: [dev]
6 | types: [closed]
7 |
8 | jobs:
9 | build:
10 | if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'dev'
11 | runs-on: self-hosted
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v2
15 |
16 | - name: Fetch PR Description and set as env variable
17 | id: pr_description
18 | run: echo "${{ github.event.pull_request.body }}" > pr_description_android.txt
19 |
20 | - name: Build and Release
21 | run: |
22 | cd android
23 | fastlane deploy_firebase_dev
24 |
25 | - name: Cleanup
26 | run: |
27 | rm -f pr_description_android.txt
28 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-dev-ios.yml:
--------------------------------------------------------------------------------
1 | name: iOS Release - Development
2 |
3 | on:
4 | pull_request:
5 | branches: [dev]
6 | types: [closed]
7 |
8 | jobs:
9 | build:
10 | if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'dev'
11 | runs-on: self-hosted
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v2
15 |
16 | - name: Fetch PR Description and set as env variable
17 | id: pr_description
18 | run: echo "$" > pr_description_prod.txt
19 |
20 | - name: Build and Release
21 | run: |
22 | cd ios
23 | fastlane release_ios_dev
24 |
25 | - name: Cleanup
26 | run: |
27 | rm -f pr_description_prod.txt
28 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-prod-android.yml:
--------------------------------------------------------------------------------
1 | name: Android Release - Production
2 |
3 | on:
4 | pull_request:
5 | branches: [main]
6 | types: [closed]
7 |
8 | jobs:
9 | build:
10 | if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
11 | runs-on: self-hosted
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v2
15 |
16 | - name: Fetch PR Description and set as env variable
17 | id: pr_description
18 | run: echo "$" > pr_description_prod.txt
19 |
20 | - name: Build and Release
21 | run: |
22 | cd android
23 | fastlane deploy_firebase_prod
24 |
25 | - name: Cleanup
26 | run: |
27 | rm -f pr_description_prod.txt
28 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-prod-ios.yml:
--------------------------------------------------------------------------------
1 | name: iOS Release - Production
2 |
3 | on:
4 | pull_request:
5 | branches: [main]
6 | types: [closed]
7 |
8 | jobs:
9 | build:
10 | if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
11 | runs-on: self-hosted
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v2
15 |
16 | - name: Fetch PR Description and set as env variable
17 | id: pr_description
18 | run: echo "$" > pr_description_prod.txt
19 |
20 | - name: Build and Release
21 | run: |
22 | cd ios
23 | fastlane release_ios_prod
24 |
25 | - name: Cleanup
26 | run: |
27 | rm -f pr_description_prod.txt
28 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-stage-android.yml:
--------------------------------------------------------------------------------
1 | name: Android Release - Staging
2 |
3 | on:
4 | pull_request:
5 | branches: [stage]
6 | types: [closed]
7 |
8 | jobs:
9 | build:
10 | if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'stage'
11 | runs-on: self-hosted
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v2
15 |
16 | - name: Fetch PR Description and set as env variable
17 | id: pr_description
18 | run: echo "$" > pr_description.txt
19 |
20 | - name: Build and Release
21 | run: |
22 | cd android
23 | fastlane deploy_firebase_stage
24 |
25 | - name: Cleanup
26 | run: |
27 | rm -f pr_description.txt
28 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-stage-ios.yml:
--------------------------------------------------------------------------------
1 | name: iOS Release - Staging
2 |
3 | on:
4 | pull_request:
5 | branches: [stage]
6 | types: [closed]
7 |
8 | jobs:
9 | build:
10 | if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'stage'
11 | runs-on: self-hosted
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v2
15 |
16 | - name: Fetch PR Description and set as env variable
17 | id: pr_description
18 | run: echo "$" > pr_description.txt
19 |
20 | - name: Build and Release
21 | run: |
22 | cd ios
23 | fastlane release_ios_stg
24 |
25 | - name: Cleanup
26 | run: |
27 | rm -f pr_description.txt
28 |
--------------------------------------------------------------------------------
/.github/workflows/pr-check.yml:
--------------------------------------------------------------------------------
1 | name: PR Check
2 |
3 | on:
4 | pull_request:
5 | types: [opened, synchronize, reopened, edited]
6 |
7 | jobs:
8 | check:
9 | runs-on: self-hosted
10 | steps:
11 | - name: Checkout repository
12 | uses: actions/checkout@v3
13 |
14 | - name: Check Dart Issues
15 | id: check_dart_issues
16 | run: |
17 | # Install Dart and Flutter dependencies
18 | fvm flutter pub get
19 |
20 | # Check for Dart issues
21 | fvm flutter analyze > dart_issues.txt || true
22 |
23 | # Check if there are any issues
24 | if grep -q "No issues found." dart_issues.txt; then
25 | echo "No Dart issues found."
26 | else
27 | echo "Dart issues found. Exiting."
28 | cat dart_issues.txt
29 | exit 1
30 | fi
31 |
32 | - name: Cleanup PR description and analysis files
33 | run: |
34 | rm -f dart_issues.txt
35 |
--------------------------------------------------------------------------------
/.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 | actions-runner
13 |
14 | # IntelliJ related
15 | *.iml
16 | *.ipr
17 | *.iws
18 | .idea/
19 |
20 | # The .vscode folder contains launch configuration and tasks you configure in
21 | # VS Code which you may wish to be included in version control, so this line
22 | # is commented out by default.
23 | #.vscode/
24 |
25 | # Flutter/Dart/Pub related
26 | **/doc/api/
27 | **/ios/Flutter/.last_build_id
28 | .dart_tool/
29 | .flutter-plugins
30 | .flutter-plugins-dependencies
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 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: "5874a72aa4c779a02553007c47dacbefba2374dc"
8 | channel: "stable"
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
17 | base_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
18 | - platform: android
19 | create_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
20 | base_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
21 | - platform: ios
22 | create_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
23 | base_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
24 | - platform: linux
25 | create_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
26 | base_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
27 | - platform: macos
28 | create_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
29 | base_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
30 | - platform: web
31 | create_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
32 | base_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
33 | - platform: windows
34 | create_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
35 | base_revision: 5874a72aa4c779a02553007c47dacbefba2374dc
36 |
37 | # User provided section
38 |
39 | # List of Local paths (relative to this file) that should be
40 | # ignored by the migrate tool.
41 | #
42 | # Files that are not part of the templates will be ignored by default.
43 | unmanaged_files:
44 | - 'lib/main.dart'
45 | - 'ios/Runner.xcodeproj/project.pbxproj'
46 |
--------------------------------------------------------------------------------
/.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": "Launch development",
9 | "request": "launch",
10 | "type": "dart",
11 | "program": "lib/main.dart",
12 | "args": [
13 | "--flavor",
14 | "development",
15 | "--target",
16 | "lib/main.dart",
17 | "--dart-define",
18 | "ENVIRONMENT=dev"
19 | ]
20 | },
21 | {
22 | "name": "Launch staging",
23 | "request": "launch",
24 | "type": "dart",
25 | "program": "lib/main.dart",
26 | "args": [
27 | "--flavor",
28 | "staging",
29 | "--target",
30 | "lib/main.dart",
31 | "--dart-define",
32 | "ENVIRONMENT=stage"
33 | ]
34 | },
35 | {
36 | "name": "Launch production",
37 | "request": "launch",
38 | "type": "dart",
39 | "program": "lib/main.dart",
40 | "args": [
41 | "--flavor",
42 | "production",
43 | "--target",
44 | "lib/main.dart",
45 | "--dart-define",
46 | "ENVIRONMENT=prod"
47 | ]
48 | }
49 | ]
50 | }
51 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cSpell.words": [
3 | "DEVURL",
4 | "hadibucopy",
5 | "PRODURL",
6 | "STAGEURL"
7 | ]
8 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Mücahit Şimşek
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Flutter CI/CD Processes
2 |
3 | ## Presentation
4 | - The aim of our project is to show how CI/CD processes work in a real-time project.
5 | - The CI/CD process in Flutter is to automate what we do manually using Github Actions. In this way, you can quickly get builds, test and production versions.
6 |
7 | ## Requirements
8 | - I preferred to use [Firebase App Distribution](https://firebase.google.com/docs/app-distribution?hl=tr) instead of using any store for testing in the project.
9 | - We used Github Actions. We need to automate our work and use it from a virtual space. [This Project Actions](https://github.com/mucahitsimsek/Flutter-Flavor-Create/actions)
10 | - [Fastlane](https://docs.fastlane.tools/) It is a practical solution that automates the easy creation and release of new versions to test and production environments.
11 | - I used [Flavor](https://saileshdahal.com.np/flavor-setup-flutter) **(You can also learn about the flavor processes with the similarities I made here.)** in Flutter because I want to create development-stage-production environments to separate testing processes and features that are still in development.
12 |
13 |
Steps
14 |
15 | - [Firebase App Distribution](https://firebase.google.com/docs/app-distribution?hl=tr) Setup
16 | - [Flavor](https://docs.flutter.dev/deployment/flavors) Setup:
17 | - First of all, we have to define the environments we want to create. Here are the things we demand:
18 | - New features should not affect active users.
19 | - Features that have finished development need to be tested.
20 | - Successfully tested features should be ready to be presented to the user.
21 | In line with these steps, the following environment emerges:
22 | - Development
23 | - Staging
24 | - Production
25 | - Using these environments, let's first write our target code and then complete the installations on iOS and Android locally.
26 | - [Fastlane](https://docs.flutter.dev/deployment/cd#fastlane) Setup:
27 | - We will cover fastlane installations directly for [iOS](https://docs.fastlane.tools/getting-started/ios/setup/) and [Android](https://docs.fastlane.tools/getting-started/android/setup/). Therefore, if you want to proceed through the doc, please proceed through these tabs.
28 | - [Github Actions](https://docs.github.com/en/actions/writing-workflows/quickstart) Setup:
29 | - With the environments we used in Flavor, we will automate the codes we wrote in fastlane at this stage. To do this, we will create a 📂 **workflows** folder under the 📂 **.github/** folder in the main hierarchy of the project and ensure that our 📄 **.yml** files are triggered.
30 |
31 | ## Firebase App Distribution
32 | [iOS Distribution](https://firebase.google.com/docs/app-distribution/ios/distribute-fastlane?hl=tr)
33 | [Android Distribution](https://firebase.google.com/docs/app-distribution/android/distribute-fastlane?hl=tr)
34 | [My Android Distribution](/android/fastlane/Fastfile)
35 | [My iOS Distribution](/ios/fastlane/Fastfile). **I will add it soon.**
36 |
37 | ## Flavor - Dart
38 | - First we will use the --dart-define parameter. This is to prevent creating more than one main.dart file. In this way, we will be able to easily understand which env is being run on a single path. For this, let's update [.vscode/launch.json](/.vscode/launch.json) as below.
39 | ```json
40 | {
41 | "version": "0.2.0",
42 | "configurations": [
43 | {
44 | "name": "Launch development",
45 | "request": "launch",
46 | "type": "dart",
47 | "program": "lib/main.dart",
48 | "args": [
49 | "--flavor",
50 | "development",
51 | "--target",
52 | "lib/main.dart",
53 | "--dart-define",
54 | "ENVIRONMENT=dev"
55 | ]
56 | },
57 | ]
58 | }
59 |
60 | ```
61 | - This [dart-define](https://dartcode.org/docs/using-dart-define-in-flutter/) parameter provides us the value directly when the project starts.
62 | - If you want to run from the terminal:
63 | ```bash
64 | flutter run --flavor development --target=lib/main.dart --dart-define=ENVIRONMENT=dev
65 | ```
66 | - As we talked about in the posts above, we were creating 3 environments: production, staging and development.
67 | Accordingly, we code the following dart file for flutter installation.
68 | [flavor_config.dart](/lib/base/config/flavor_config.dart)
69 | ```dart
70 | final class FlavorConfiguration {
71 | final EnvironmentType environmentType;
72 | final String baseUrl;
73 |
74 | FlavorConfiguration._({required this.environmentType, required this.baseUrl});
75 |
76 | static final _env = EnvironmentType.currentEnv;
77 |
78 | static final FlavorConfiguration instance = FlavorConfiguration._(
79 | environmentType: _env,
80 | baseUrl: _env.baseUrl,
81 | );
82 | }
83 | ```
84 | - We need to define the environment type in the following way.
85 | ```dart
86 | enum EnvironmentType {
87 | dev(FlavorConst.dev),
88 | stage(FlavorConst.stage),
89 | prod(FlavorConst.prod);
90 |
91 | const EnvironmentType(this.environment);
92 |
93 | final String environment;
94 |
95 | static EnvironmentType get currentEnv => EnvironmentType.fromString(
96 | const String.fromEnvironment(FlavorConst.environment));
97 |
98 | String get baseUrl {
99 | return switch (currentEnv) {
100 | dev => FlavorConst.devUrl,
101 | stage => FlavorConst.stageUrl,
102 | prod => FlavorConst.prodUrl,
103 | };
104 | }
105 |
106 | static EnvironmentType fromString(String value) {
107 | return EnvironmentType.values.firstWhere(
108 | (e) => e.environment == value,
109 | orElse: () => throw UnknownDevice(value),
110 | );
111 | }
112 |
113 | bool get isDev => currentEnv == dev;
114 | bool get isStage => currentEnv == stage;
115 | bool get isProd => currentEnv == prod;
116 | }
117 | ```
118 |
119 | ## Flavor - iOS
120 | - Open your project in Xcode.
121 | - To add a new Schema, select Product > Schema > New Schema from the menu. Then let's name the schema as production, staging and development.
122 | - In order to separate existing configurations from other configurations, we must first add new configurations for the schemas we will create.
123 | - Under the Info tab at the end of the Configurations dropdown list, click the plus button and duplicate each configuration name (Debug, Release, and Profile). Duplicate the existing configurations, once for each environment.
124 |
125 | - **Then we create schemes to map the configurations we created. We map the schemes we created with configurations. You can examine the visuals:**
126 |
127 |
128 | - After these operations, we need to update the project bundle ids.
129 |
130 | - As a last step, we update the name of our application so that we can analyze the environment in which it works **(APP_DISPLAY_NAME ADDED ON INFO.PLIST)**.
131 |
132 |
133 |
134 | ## Flavor - Android
135 | - For Android configuration you need to add the following conditions in [android/app/build.gradle](/android/app/build.gradle#L78-L96):
136 | ```gradle
137 | flavorDimensions "default"
138 |
139 | productFlavors {
140 | production {
141 | dimension "default"
142 | applicationIdSuffix ""
143 | manifestPlaceholders = [appName: "YOUR APP NAME"]
144 | }
145 | staging {
146 | dimension "default"
147 | applicationIdSuffix ".stg"
148 | manifestPlaceholders = [appName: "[STG] YOUR APP NAME"]
149 | }
150 | development {
151 | dimension "default"
152 | applicationIdSuffix ".dev"
153 | manifestPlaceholders = [appName: "[DEV] YOUR APP NAME"]
154 | }
155 | }
156 | ```
157 | - Please update the [Android Manifest File](/android/app/src/main/AndroidManifest.xml) as follows.
158 | ```xml
159 |
163 | ```
164 | - If you want to update the icons in android, you need to update the [src](/android/app/src/) content as in the image.
165 |
166 |
167 | ## Fastlane
168 | - Please review the following folders:
169 | - [iOS](/ios/fastlane)
170 | - [Android](/android/fastlane)
171 |
172 | **For Details:**
173 |
174 |
175 | [Fastlane Docs](https://docs.fastlane.tools/)
176 |
177 | ## Github Actions
178 | - We need to automate the processes we have done so far. For this, we will use Github Actions.
179 | - We will create a new folder under the .github folder in the main hierarchy of the project and name it workflows.
180 | - In this folder we will create a new file and name it as you like. You can see my nomenclature here:
181 | - [.github/workflows](/.github/workflows)
182 | - When you examine the workflows we created, there are pr-check and deploys. Of these, [pr-check](/.github/workflows/pr-check.yml) will work when a pull request is created. The other workflows are set to run when merge to dev-stage-main branches.
183 | - Whichever branch pr is accepted, the deployment process will start as a result of the action triggered in this case. For example, [deploy-dev-android](/.github/workflows/deploy-dev-android.yml) requires merge to the “dev” branch.
184 |
185 | - I connected to github actions on my device, follow these steps to do it on yours:
186 | - Open Github repository
187 | - Click on the Settings tab, from there open the actions menu.
188 |
189 | - Click on runners and create a runner.
190 |
191 | - After creating the Runner, it will look like this.
192 |
193 |
194 | ## Conclusion
195 | By following this guide, you've set up a comprehensive CI/CD pipeline for your Flutter app, utilizing Firebase App Distribution, Flavor configurations, Fastlane, and GitHub Actions. This setup ensures a streamlined, automated approach to managing builds and deployments, allowing for efficient testing and production releases. With this pipeline, you can focus more on development and testing, confident that your CI/CD process will handle the repetitive, manual tasks.
196 |
197 | This CI/CD configuration not only boosts development productivity but also minimizes errors by automating each critical step, ensuring reliable, high-quality app versions reach your testers and users quickly.
198 |
199 | Happy coding, and enjoy the power of automation in your Flutter projects!
200 |
201 |
--------------------------------------------------------------------------------
/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 https://dart.dev/lints.
17 | #
18 | # Instead of disabling a lint rule for the entire project in the
19 | # section below, it can also be suppressed for a single line of code
20 | # or a specific dart file by using the `// ignore: name_of_lint` and
21 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
22 | # producing the lint.
23 | rules:
24 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
25 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
26 |
27 | # Additional information about this file can be found at
28 | # https://dart.dev/guides/language/analysis-options
29 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 | fastlane/firebase_login_credentials.json
9 |
10 | # Remember to never publicly share your keystore.
11 | # See https://flutter.dev/to/reference-keystore
12 | key.properties
13 | **/*.keystore
14 | **/*.jks
15 |
--------------------------------------------------------------------------------
/android/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | gem "fastlane"
4 |
--------------------------------------------------------------------------------
/android/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.7)
5 | base64
6 | nkf
7 | rexml
8 | addressable (2.8.7)
9 | public_suffix (>= 2.0.2, < 7.0)
10 | artifactory (3.0.17)
11 | atomos (0.1.3)
12 | aws-eventstream (1.3.0)
13 | aws-partitions (1.1003.0)
14 | aws-sdk-core (3.212.0)
15 | aws-eventstream (~> 1, >= 1.3.0)
16 | aws-partitions (~> 1, >= 1.992.0)
17 | aws-sigv4 (~> 1.9)
18 | jmespath (~> 1, >= 1.6.1)
19 | aws-sdk-kms (1.95.0)
20 | aws-sdk-core (~> 3, >= 3.210.0)
21 | aws-sigv4 (~> 1.5)
22 | aws-sdk-s3 (1.170.0)
23 | aws-sdk-core (~> 3, >= 3.210.0)
24 | aws-sdk-kms (~> 1)
25 | aws-sigv4 (~> 1.5)
26 | aws-sigv4 (1.10.1)
27 | aws-eventstream (~> 1, >= 1.0.2)
28 | babosa (1.0.4)
29 | base64 (0.2.0)
30 | claide (1.1.0)
31 | colored (1.2)
32 | colored2 (3.1.2)
33 | commander (4.6.0)
34 | highline (~> 2.0.0)
35 | declarative (0.0.20)
36 | digest-crc (0.6.5)
37 | rake (>= 12.0.0, < 14.0.0)
38 | domain_name (0.6.20240107)
39 | dotenv (2.8.1)
40 | emoji_regex (3.2.3)
41 | excon (0.112.0)
42 | faraday (1.10.4)
43 | faraday-em_http (~> 1.0)
44 | faraday-em_synchrony (~> 1.0)
45 | faraday-excon (~> 1.1)
46 | faraday-httpclient (~> 1.0)
47 | faraday-multipart (~> 1.0)
48 | faraday-net_http (~> 1.0)
49 | faraday-net_http_persistent (~> 1.0)
50 | faraday-patron (~> 1.0)
51 | faraday-rack (~> 1.0)
52 | faraday-retry (~> 1.0)
53 | ruby2_keywords (>= 0.0.4)
54 | faraday-cookie_jar (0.0.7)
55 | faraday (>= 0.8.0)
56 | http-cookie (~> 1.0.0)
57 | faraday-em_http (1.0.0)
58 | faraday-em_synchrony (1.0.0)
59 | faraday-excon (1.1.0)
60 | faraday-httpclient (1.0.1)
61 | faraday-multipart (1.0.4)
62 | multipart-post (~> 2)
63 | faraday-net_http (1.0.2)
64 | faraday-net_http_persistent (1.2.0)
65 | faraday-patron (1.0.0)
66 | faraday-rack (1.0.0)
67 | faraday-retry (1.0.3)
68 | faraday_middleware (1.2.1)
69 | faraday (~> 1.0)
70 | fastimage (2.3.1)
71 | fastlane (2.225.0)
72 | CFPropertyList (>= 2.3, < 4.0.0)
73 | addressable (>= 2.8, < 3.0.0)
74 | artifactory (~> 3.0)
75 | aws-sdk-s3 (~> 1.0)
76 | babosa (>= 1.0.3, < 2.0.0)
77 | bundler (>= 1.12.0, < 3.0.0)
78 | colored (~> 1.2)
79 | commander (~> 4.6)
80 | dotenv (>= 2.1.1, < 3.0.0)
81 | emoji_regex (>= 0.1, < 4.0)
82 | excon (>= 0.71.0, < 1.0.0)
83 | faraday (~> 1.0)
84 | faraday-cookie_jar (~> 0.0.6)
85 | faraday_middleware (~> 1.0)
86 | fastimage (>= 2.1.0, < 3.0.0)
87 | fastlane-sirp (>= 1.0.0)
88 | gh_inspector (>= 1.1.2, < 2.0.0)
89 | google-apis-androidpublisher_v3 (~> 0.3)
90 | google-apis-playcustomapp_v1 (~> 0.1)
91 | google-cloud-env (>= 1.6.0, < 2.0.0)
92 | google-cloud-storage (~> 1.31)
93 | highline (~> 2.0)
94 | http-cookie (~> 1.0.5)
95 | json (< 3.0.0)
96 | jwt (>= 2.1.0, < 3)
97 | mini_magick (>= 4.9.4, < 5.0.0)
98 | multipart-post (>= 2.0.0, < 3.0.0)
99 | naturally (~> 2.2)
100 | optparse (>= 0.1.1, < 1.0.0)
101 | plist (>= 3.1.0, < 4.0.0)
102 | rubyzip (>= 2.0.0, < 3.0.0)
103 | security (= 0.1.5)
104 | simctl (~> 1.6.3)
105 | terminal-notifier (>= 2.0.0, < 3.0.0)
106 | terminal-table (~> 3)
107 | tty-screen (>= 0.6.3, < 1.0.0)
108 | tty-spinner (>= 0.8.0, < 1.0.0)
109 | word_wrap (~> 1.0.0)
110 | xcodeproj (>= 1.13.0, < 2.0.0)
111 | xcpretty (~> 0.3.0)
112 | xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
113 | fastlane-sirp (1.0.0)
114 | sysrandom (~> 1.0)
115 | gh_inspector (1.1.3)
116 | google-apis-androidpublisher_v3 (0.54.0)
117 | google-apis-core (>= 0.11.0, < 2.a)
118 | google-apis-core (0.11.3)
119 | addressable (~> 2.5, >= 2.5.1)
120 | googleauth (>= 0.16.2, < 2.a)
121 | httpclient (>= 2.8.1, < 3.a)
122 | mini_mime (~> 1.0)
123 | representable (~> 3.0)
124 | retriable (>= 2.0, < 4.a)
125 | rexml
126 | google-apis-iamcredentials_v1 (0.17.0)
127 | google-apis-core (>= 0.11.0, < 2.a)
128 | google-apis-playcustomapp_v1 (0.13.0)
129 | google-apis-core (>= 0.11.0, < 2.a)
130 | google-apis-storage_v1 (0.31.0)
131 | google-apis-core (>= 0.11.0, < 2.a)
132 | google-cloud-core (1.7.1)
133 | google-cloud-env (>= 1.0, < 3.a)
134 | google-cloud-errors (~> 1.0)
135 | google-cloud-env (1.6.0)
136 | faraday (>= 0.17.3, < 3.0)
137 | google-cloud-errors (1.4.0)
138 | google-cloud-storage (1.47.0)
139 | addressable (~> 2.8)
140 | digest-crc (~> 0.4)
141 | google-apis-iamcredentials_v1 (~> 0.1)
142 | google-apis-storage_v1 (~> 0.31.0)
143 | google-cloud-core (~> 1.6)
144 | googleauth (>= 0.16.2, < 2.a)
145 | mini_mime (~> 1.0)
146 | googleauth (1.8.1)
147 | faraday (>= 0.17.3, < 3.a)
148 | jwt (>= 1.4, < 3.0)
149 | multi_json (~> 1.11)
150 | os (>= 0.9, < 2.0)
151 | signet (>= 0.16, < 2.a)
152 | highline (2.0.3)
153 | http-cookie (1.0.7)
154 | domain_name (~> 0.5)
155 | httpclient (2.8.3)
156 | jmespath (1.6.2)
157 | json (2.8.1)
158 | jwt (2.9.3)
159 | base64
160 | mini_magick (4.13.2)
161 | mini_mime (1.1.5)
162 | multi_json (1.15.0)
163 | multipart-post (2.4.1)
164 | nanaimo (0.4.0)
165 | naturally (2.2.1)
166 | nkf (0.2.0)
167 | optparse (0.6.0)
168 | os (1.1.4)
169 | plist (3.7.1)
170 | public_suffix (6.0.1)
171 | rake (13.2.1)
172 | representable (3.2.0)
173 | declarative (< 0.1.0)
174 | trailblazer-option (>= 0.1.1, < 0.2.0)
175 | uber (< 0.2.0)
176 | retriable (3.1.2)
177 | rexml (3.3.9)
178 | rouge (2.0.7)
179 | ruby2_keywords (0.0.5)
180 | rubyzip (2.3.2)
181 | security (0.1.5)
182 | signet (0.19.0)
183 | addressable (~> 2.8)
184 | faraday (>= 0.17.5, < 3.a)
185 | jwt (>= 1.5, < 3.0)
186 | multi_json (~> 1.10)
187 | simctl (1.6.10)
188 | CFPropertyList
189 | naturally
190 | sysrandom (1.0.5)
191 | terminal-notifier (2.0.0)
192 | terminal-table (3.0.2)
193 | unicode-display_width (>= 1.1.1, < 3)
194 | trailblazer-option (0.1.2)
195 | tty-cursor (0.7.1)
196 | tty-screen (0.8.2)
197 | tty-spinner (0.9.3)
198 | tty-cursor (~> 0.7)
199 | uber (0.1.0)
200 | unicode-display_width (2.6.0)
201 | word_wrap (1.0.0)
202 | xcodeproj (1.27.0)
203 | CFPropertyList (>= 2.3.3, < 4.0)
204 | atomos (~> 0.1.3)
205 | claide (>= 1.0.2, < 2.0)
206 | colored2 (~> 3.1)
207 | nanaimo (~> 0.4.0)
208 | rexml (>= 3.3.6, < 4.0)
209 | xcpretty (0.3.0)
210 | rouge (~> 2.0.7)
211 | xcpretty-travis-formatter (1.0.1)
212 | xcpretty (~> 0.2, >= 0.0.7)
213 |
214 | PLATFORMS
215 | arm64-darwin-23
216 | ruby
217 |
218 | DEPENDENCIES
219 | fastlane
220 |
221 | BUNDLED WITH
222 | 2.5.18
223 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
5 | id "dev.flutter.flutter-gradle-plugin"
6 | }
7 |
8 |
9 | def localProperties = new Properties()
10 | def localPropertiesFile = rootProject.file('local.properties')
11 | if (localPropertiesFile.exists()) {
12 | localPropertiesFile.withReader('UTF-8') { reader ->
13 | localProperties.load(reader)
14 | }
15 | }
16 |
17 | def keystoreProperties = new Properties()
18 | def keystorePropertiesFile = rootProject.file('key.properties')
19 | if (keystorePropertiesFile.exists()) {
20 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
21 | }
22 |
23 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
24 | if (flutterVersionCode == null) {
25 | flutterVersionCode = '1'
26 | }
27 |
28 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
29 | if (flutterVersionName == null) {
30 | flutterVersionName = '1.0'
31 | }
32 |
33 |
34 | android {
35 | namespace = "com.example.hadibucopy"
36 | compileSdk = flutter.compileSdkVersion
37 | ndkVersion = flutter.ndkVersion
38 |
39 | compileOptions {
40 | sourceCompatibility = JavaVersion.VERSION_1_8
41 | targetCompatibility = JavaVersion.VERSION_1_8
42 | }
43 |
44 | kotlinOptions {
45 | jvmTarget = JavaVersion.VERSION_1_8
46 | }
47 |
48 | defaultConfig {
49 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
50 | applicationId = "com.example.hadibucopy"
51 | // You can update the following values to match your application needs.
52 | // For more information, see: https://flutter.dev/to/review-gradle-config.
53 | minSdk = flutter.minSdkVersion
54 | targetSdk = flutter.targetSdkVersion
55 | versionCode = flutter.versionCode
56 | versionName = flutter.versionName
57 | }
58 |
59 | signingConfigs {
60 | if (System.getenv("ANDROID_KEYSTORE_PATH")) {
61 | release {
62 | storeFile file(System.getenv("ANDROID_KEYSTORE_PATH"))
63 | keyAlias System.getenv("ANDROID_KEYSTORE_ALIAS")
64 | keyPassword System.getenv("ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD")
65 | storePassword System.getenv("ANDROID_KEYSTORE_PASSWORD")
66 | }
67 | } else {
68 | release {
69 | keyAlias keystoreProperties['keyAlias']
70 | keyPassword keystoreProperties['keyPassword']
71 | storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
72 | storePassword keystoreProperties['storePassword']
73 | }
74 | }
75 | }
76 |
77 |
78 | flavorDimensions "default"
79 |
80 | productFlavors {
81 | production {
82 | dimension "default"
83 | applicationIdSuffix ""
84 | manifestPlaceholders = [appName: "Hadibu"]
85 | }
86 | staging {
87 | dimension "default"
88 | applicationIdSuffix ".stg"
89 | manifestPlaceholders = [appName: "[STG] Hadibu"]
90 | }
91 | development {
92 | dimension "default"
93 | applicationIdSuffix ".dev"
94 | manifestPlaceholders = [appName: "[DEV] Hadibu"]
95 | }
96 | }
97 |
98 | buildTypes {
99 | release {
100 | signingConfig signingConfigs.release
101 | minifyEnabled true
102 | proguardFiles getDefaultProguardFile('proguard-android.txt')
103 | }
104 | debug {
105 | signingConfig signingConfigs.debug
106 | }
107 | }
108 | }
109 |
110 | flutter {
111 | source = "../.."
112 | }
113 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/development/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/development/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/development/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/development/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/development/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/development/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/development/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/development/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/development/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/development/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/development/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/development/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/development/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/development/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/hadibucopy/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.hadibucopy
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity()
6 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/staging/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/staging/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/staging/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/staging/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/staging/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/staging/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/staging/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/staging/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/staging/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/staging/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/staging/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/android/app/src/staging/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/staging/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/staging/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | rootProject.buildDir = "../build"
9 | subprojects {
10 | project.buildDir = "${rootProject.buildDir}/${project.name}"
11 | }
12 | subprojects {
13 | project.evaluationDependsOn(":app")
14 | }
15 |
16 | tasks.register("clean", Delete) {
17 | delete rootProject.buildDir
18 | }
19 |
--------------------------------------------------------------------------------
/android/fastlane/Appfile:
--------------------------------------------------------------------------------
1 | json_key_file("") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one
2 | package_name("com.covenlabs.hadibu") # e.g. com.krausefx.app
--------------------------------------------------------------------------------
/android/fastlane/Fastfile:
--------------------------------------------------------------------------------
1 | # This file contains the fastlane.tools configuration
2 | # You can find the documentation at https://docs.fastlane.tools
3 | #
4 | # For a list of all available actions, check out
5 | # https://docs.fastlane.tools/actions
6 | #
7 | # For a list of all available plugins, check out
8 | # https://docs.fastlane.tools/plugins/available-plugins
9 | #
10 |
11 | # Uncomment the line if you want fastlane to automatically update itself
12 | # update_fastlane
13 |
14 | default_platform(:android)
15 |
16 | version_number = "1.0.0" # Update this with the version number of the app
17 | SLACK_CHANNEL = "#deployhan-gossip" # Update this with the Slack channel
18 | SLACK_URL = "SLACK URL" # Update this with the Slack URL
19 | SLACK_BOT_NAME = "deployhan" # Update this with the Slack bot name
20 | ENV["FIREBASE_LOGIN_CREDENTIALS"] = "fastlane/firebase_login_credentials.json" # Update this with the path to the Firebase login credentials
21 | ENV["GOOGLE_SERVICE_CREDENTIALS"] = "fastlane/google_service_credentials.json" # Update this with the path to the Google service credentials
22 | FIREBASE_TESTER_GROUP_ID = "testers" # Update this with the Firebase tester group ID
23 | BOT_MOOD_TEXT = SLACK_BOT_NAME + "'s Mood"
24 | BOT_MOOD = ["💪 Pumped", "😎 Chill", "🔥 On Fire", "🧠 Genius"]
25 |
26 | platform :android do
27 | desc "Flutter Pub Get"
28 | lane :flutter_get_pubs do
29 | Dir.chdir("../../") do
30 | sh("fvm flutter pub get")
31 | end
32 | end
33 |
34 | desc "Build Android APK or AAB for the specified environment"
35 | lane :build_android do |options|
36 | appEnv = options[:appEnv]
37 | flavor = options[:flavor]
38 |
39 | begin
40 | latest_release = firebase_app_distribution_get_latest_release(
41 | app: options[:appId],
42 | service_credentials_file: ENV["FIREBASE_LOGIN_CREDENTIALS"]
43 | )
44 | build_number = latest_release[:buildVersion].to_i + 1
45 | rescue => error
46 | UI.message("No previous release found or an error occurred: #{error}. Setting build number to 1.")
47 | build_number = 1
48 | end
49 |
50 | Dir.chdir("../../") do
51 | if appEnv == "prod"
52 | sh("fvm flutter build appbundle --flavor #{flavor} --dart-define=APP_ENV=#{appEnv} --release --build-name=#{version_number} --build-number=#{build_number}")
53 | else
54 | sh("fvm flutter build apk --flavor #{flavor} --dart-define=APP_ENV=#{appEnv} --release --build-name=#{version_number} --build-number=#{build_number}")
55 | end
56 | end
57 | end
58 |
59 | desc "Upload Android APK or AAB to Firebase App Distribution"
60 | lane :upload_android do |options|
61 | appId = options[:appId]
62 | flavor = options[:flavor]
63 |
64 | pr_description_file = File.expand_path("../../../pr_description_android.txt", __FILE__)
65 | pr_description = if File.exist?(pr_description_file)
66 | File.read(pr_description_file).strip
67 | else
68 | "No PR description provided"
69 | end
70 |
71 | if flavor == "production"
72 | aab_dir = File.expand_path("../../../build/app/outputs/bundle/#{flavor}Release/", __FILE__)
73 | aab_files = Dir.glob("#{aab_dir}/app-#{flavor}-release.aab").sort_by { |f| File.mtime(f) }
74 | latest_aab = aab_files.last
75 | else
76 | apk_dir = File.expand_path("../../../build/app/outputs/flutter-apk/", __FILE__)
77 | apk_files = Dir.glob("#{apk_dir}/app-#{flavor}-release.apk").sort_by { |f| File.mtime(f) }
78 | latest_apk = apk_files.last
79 | end
80 |
81 | release = firebase_app_distribution(
82 | app: appId,
83 | groups: FIREBASE_TESTER_GROUP_ID,
84 | release_notes: pr_description,
85 | android_artifact_path: latest_aab,
86 | apk_path: latest_apk,
87 | service_credentials_file: ENV["FIREBASE_LOGIN_CREDENTIALS"]
88 | )
89 | UI.message("Firebase App Distribution release URL: #{release}")
90 | end
91 |
92 | def send_slack_notification(success:, message:, additional_payload: {})
93 | # slack(
94 | # message: message,
95 | # success: success,
96 | # channel: SLACK_CHANNEL,
97 | # slack_url: SLACK_URL,
98 | # payload: {
99 | # "Build Date" => Time.now.to_s,
100 | # "Built by" => SLACK_BOT_NAME,
101 | # }.merge(additional_payload),
102 | # default_payloads: [:git_branch]
103 | # )
104 | end
105 |
106 | desc "Release Android Deployment"
107 | lane :release_android do |options|
108 | appId = options[:appId]
109 | flavor = options[:flavor]
110 | appEnv = options[:appEnv]
111 |
112 | begin
113 | flutter_get_pubs
114 | build_android(appEnv: appEnv, flavor: flavor, appId: appId)
115 | upload_android(appId: appId, flavor: flavor)
116 |
117 | latest_release = firebase_app_distribution_get_latest_release(app: options[:appId], service_credentials_file: ENV["FIREBASE_LOGIN_CREDENTIALS"])
118 |
119 | send_slack_notification(
120 | success: true,
121 | message: "New Android build is ready to be tested!",
122 | additional_payload: {
123 | "Version" => "V #{version_number} (#{latest_release[:buildVersion]})",
124 | BOT_MOOD_TEXT => BOT_MOOD.sample
125 | }
126 | )
127 | rescue => error
128 | UI.error("Error during release: #{error}")
129 | send_slack_notification(
130 | success: false,
131 | message: "Android build failed with error: #{error.message}",
132 | additional_payload: {
133 | "Error Message" => error.message,
134 | "App ID" => appId
135 | }
136 | )
137 | exit unless error.message.include?("Some error occurred or No APK files found #error")
138 | end
139 | end
140 |
141 | desc "Release Android Prod"
142 | lane :release_android_prod do
143 | release_android(appId: "FIREBASE APP ID FOR PRODUCTION", flavor: "production", appEnv: "prod")
144 | end
145 |
146 | desc "Release Android Staging"
147 | lane :release_android_stg do
148 | release_android(appId: "FIREBASE APP ID FOR STAGE", flavor: "staging", appEnv: "stage")
149 | deploy_play_store(flavor: PublishType::STAGE)
150 | end
151 |
152 | desc "Release Android Dev"
153 | lane :release_android_dev do
154 | release_android(appId: "FIREBASE APP ID FOR DEVELOPMENT", flavor: "development", appEnv: "dev")
155 | end
156 |
157 | ## ------------------------- Google Play Console Deployment -------------------------
158 |
159 | desc "Release Android Prod Play Store"
160 | lane :release_android_prod_playStore do
161 | deploy_play_store(flavor: PublishType::PRODUCTION)
162 | end
163 |
164 | desc "Release Android Dev Play Store"
165 | lane :release_android_dev_playStore do
166 | deploy_play_store(flavor: PublishType::DEVELOPMENT)
167 | end
168 |
169 | desc "Deploy a new version to the Google Play"
170 | lane :deploy_play_store do |options|
171 | flavor = options[:flavor]
172 | package_name = "com.blabla.blabla" # Update this with your actual package name
173 |
174 | case flavor
175 | when PublishType::PRODUCTION
176 | releaseType = "internal"
177 | package_name = package_name
178 | appEnv = "prod"
179 | folderPath = "release"
180 | when PublishType::STAGE
181 | releaseType = "internal"
182 | package_name = "#{package_name}.stg"
183 | appEnv = "stage"
184 | folderPath = "staging"
185 | when PublishType::DEVELOPMENT
186 | releaseType = "internal"
187 | package_name = "#{package_name}.dev"
188 | appEnv = "dev"
189 | folderPath = "development"
190 | else
191 | UI.error("Unknown flavor given")
192 | return
193 | end
194 |
195 | UI.message("#{appEnv} PLAY STORE SÜRÜM HAZIRLANIYOR")
196 |
197 | version = get_version_name(releaseType: releaseType, package_name: package_name)
198 | versionNumber = version_number
199 | buildCode = version.nil? ? 1 : version[:buildCode].to_i + 1
200 |
201 | buildBundle(flavor: flavor, appEnv: appEnv, versionNumber: versionNumber, buildCode: buildCode)
202 |
203 | UI.message("Deploying version #{versionNumber} with build code #{buildCode} to Play Store")
204 | uploadPlayStore(flavor: flavor, folderPath: folderPath, package_name: package_name, releaseType: releaseType, buildCode: buildCode, versionNumber: versionNumber)
205 | end
206 |
207 | def buildBundle(flavor:, appEnv:, versionNumber:, buildCode:)
208 | Dir.chdir("../../") do
209 | sh("fvm flutter build appbundle --flavor=#{flavor} --dart-define=APP_ENV=#{appEnv} --target=lib/main.dart --release --build-name=#{versionNumber} --build-number=#{buildCode}")
210 | end
211 | end
212 |
213 | def uploadPlayStore(folderPath:, flavor:, package_name:, releaseType:, buildCode:, versionNumber:)
214 | aab_dir = File.expand_path("../../../build/app/outputs/bundle/#{folderPath}Release/", __FILE__)
215 | aab_files = Dir.glob("#{aab_dir}/app-#{flavor}-release.aab").sort_by { |f| File.mtime(f) }
216 | latest_aab = aab_files.last
217 |
218 | if latest_aab.nil?
219 | UI.user_error!("No AAB files found in '#{aab_dir}'")
220 | end
221 |
222 | begin
223 | release = supply(
224 | track: releaseType,
225 | aab: latest_aab,
226 | package_name: package_name,
227 | release_status: "draft",
228 | timeout: "0",
229 | json_key: ENV["GOOGLE_SERVICE_CREDENTIALS"]
230 | )
231 |
232 | send_slack_notification(
233 | success: true,
234 | message: "New Android build is ready to be tested on Play Store 🚀",
235 | additional_payload: {
236 | "Version" => "V #{versionNumber} (#{buildCode})",
237 | BOT_MOOD_TEXT => BOT_MOOD.sample
238 | }
239 | )
240 | rescue => error
241 | UI.error("Error during release: #{error}")
242 | send_slack_notification(
243 | success: false,
244 | message: "Play Store upload failed with error: #{error.message}",
245 | additional_payload: {
246 | "Error Message" => error.message,
247 | "Flavor" => flavor,
248 | "Version" => "V #{versionNumber} (#{buildCode})"
249 | }
250 | )
251 | end
252 |
253 | UI.message("Google Play Store Release Status: #{release}")
254 | end
255 |
256 | def get_version_name(releaseType:, package_name:)
257 | begin
258 | versionCodes = google_play_track_version_codes(
259 | track: releaseType,
260 | package_name: package_name,
261 | json_key: ENV["GOOGLE_SERVICE_CREDENTIALS"]
262 | )
263 | return {
264 | buildCode: versionCodes.max
265 | }
266 | rescue => error
267 | UI.error("Could not fetch version name: #{error}")
268 | return nil
269 | end
270 | end
271 |
272 | end
273 |
--------------------------------------------------------------------------------
/android/fastlane/Pluginfile:
--------------------------------------------------------------------------------
1 | # Autogenerated by fastlane
2 | #
3 | # Ensure this file is checked in to source control!
4 |
5 | gem 'fastlane-plugin-firebase_app_distribution'
6 |
--------------------------------------------------------------------------------
/android/fastlane/README.md:
--------------------------------------------------------------------------------
1 | fastlane documentation
2 | ----
3 |
4 | # Installation
5 |
6 | Make sure you have the latest version of the Xcode command line tools installed:
7 |
8 | ```sh
9 | xcode-select --install
10 | ```
11 |
12 | For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane)
13 |
14 | # Available Actions
15 |
16 | ## Android
17 |
18 | ### android flutter_pub_get
19 |
20 | ```sh
21 | [bundle exec] fastlane android flutter_pub_get
22 | ```
23 |
24 | flutter Pub Get
25 |
26 | ### android release_android
27 |
28 | ```sh
29 | [bundle exec] fastlane android release_android
30 | ```
31 |
32 | Release Android Deployment
33 |
34 | ### android build_apk
35 |
36 | ```sh
37 | [bundle exec] fastlane android build_apk
38 | ```
39 |
40 | Build APK
41 |
42 | ### android upload_android
43 |
44 | ```sh
45 | [bundle exec] fastlane android upload_android
46 | ```
47 |
48 | Upload Android APK to Firebase App Distribution for the specified environment
49 |
50 | ### android deploy_firebase_dev
51 |
52 | ```sh
53 | [bundle exec] fastlane android deploy_firebase_dev
54 | ```
55 |
56 | Deploy Dev Apk to Firebase
57 |
58 | ### android deploy_firebase_stage
59 |
60 | ```sh
61 | [bundle exec] fastlane android deploy_firebase_stage
62 | ```
63 |
64 | Deploy Stage Apk to Firebase
65 |
66 | ### android deploy_firebase_prod
67 |
68 | ```sh
69 | [bundle exec] fastlane android deploy_firebase_prod
70 | ```
71 |
72 | Deploy Prod Apk to Firebase
73 |
74 | ----
75 |
76 | This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
77 |
78 | More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).
79 |
80 | The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
81 |
--------------------------------------------------------------------------------
/android/fastlane/report.xml:
--------------------------------------------------------------------------------
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 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/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.6.3-all.zip
6 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }()
9 |
10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 |
12 | repositories {
13 | google()
14 | mavenCentral()
15 | gradlePluginPortal()
16 | }
17 | }
18 |
19 | plugins {
20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0"
21 | id "com.android.application" version "7.3.0" apply false
22 | id "org.jetbrains.kotlin.android" version "1.7.10" apply false
23 | }
24 |
25 | include ":app"
26 |
--------------------------------------------------------------------------------
/images/android/app-src.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/android/app-src.png
--------------------------------------------------------------------------------
/images/firebase/apps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/firebase/apps.png
--------------------------------------------------------------------------------
/images/github/github-create-runner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/github/github-create-runner.png
--------------------------------------------------------------------------------
/images/github/github-runners.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/github/github-runners.png
--------------------------------------------------------------------------------
/images/github/github-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/github/github-settings.png
--------------------------------------------------------------------------------
/images/ios/ios-bundle-id.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/ios/ios-bundle-id.png
--------------------------------------------------------------------------------
/images/ios/ios-create-new-scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/ios/ios-create-new-scheme.png
--------------------------------------------------------------------------------
/images/ios/ios-display-name-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/ios/ios-display-name-2.png
--------------------------------------------------------------------------------
/images/ios/ios-display-name.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/ios/ios-display-name.png
--------------------------------------------------------------------------------
/images/ios/ios-runner-config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/ios/ios-runner-config.png
--------------------------------------------------------------------------------
/images/ios/ios-scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/ios/ios-scheme.png
--------------------------------------------------------------------------------
/images/ios/ios-schemes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/images/ios/ios-schemes.png
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | 12.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/development.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
16 |
22 |
23 |
24 |
25 |
26 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/production.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
16 |
22 |
23 |
24 |
25 |
26 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/staging.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
16 |
22 |
23 |
24 |
25 |
26 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 |
4 | @main
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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CADisableMinimumFrameDurationOnPhone
6 |
7 | CFBundleDevelopmentRegion
8 | $(DEVELOPMENT_LANGUAGE)
9 | CFBundleName
10 | ${APP_DISPLAY_NAME)
11 | CFBundleDisplayName
12 | $(APP_DISPLAY_NAME)
13 | CFBundleExecutable
14 | $(EXECUTABLE_NAME)
15 | CFBundleIdentifier
16 | $(PRODUCT_BUNDLE_IDENTIFIER)
17 | CFBundleInfoDictionaryVersion
18 | 6.0
19 | CFBundlePackageType
20 | APPL
21 | CFBundleShortVersionString
22 | $(FLUTTER_BUILD_NAME)
23 | CFBundleSignature
24 | ????
25 | CFBundleVersion
26 | $(FLUTTER_BUILD_NUMBER)
27 | LSRequiresIPhoneOS
28 |
29 | UIApplicationSupportsIndirectInputEvents
30 |
31 | UILaunchStoryboardName
32 | LaunchScreen
33 | UIMainStoryboardFile
34 | Main
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationLandscapeLeft
39 | UIInterfaceOrientationLandscapeRight
40 |
41 | UISupportedInterfaceOrientations~ipad
42 |
43 | UIInterfaceOrientationPortrait
44 | UIInterfaceOrientationPortraitUpsideDown
45 | UIInterfaceOrientationLandscapeLeft
46 | UIInterfaceOrientationLandscapeRight
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/fastlane/Fastfile:
--------------------------------------------------------------------------------
1 | default_platform(:ios)
2 |
3 | # --- Constants ---
4 | APP_VERSION = "1.0.0" # App version
5 | ENV['FASTLANE_APP_IDENTIFIER'] ||= "com.blabla.blabla" # Default App Identifier
6 |
7 | platform :ios do
8 | # Optional: Define environment variables if needed
9 | # ENV['FASTLANE_USER'] = "" # Apple ID
10 | # ENV['FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD'] = "" # App-Specific Password
11 | # ENV['FASTLANE_ITC_TEAM_ID'] = "" # App Store Connect Team ID
12 |
13 | # --- Helper Methods ---
14 |
15 | def increment_build_number_based_on_testflight(version:)
16 | latest_build = latest_testflight_build_number(version: version)
17 | new_build = latest_build ? latest_build + 1 : 1
18 | UI.success("📈 Build number incremented to #{new_build}")
19 | new_build
20 | end
21 |
22 | def find_latest_ipa(build_environment)
23 | ipa_dir = File.expand_path("../../../build/ios/archive/ipa/#{build_environment}", __FILE__)
24 | ipa_files = Dir.glob("#{ipa_dir}/*.ipa").sort_by { |f| File.mtime(f) }
25 | UI.user_error!("No IPA files found in '#{ipa_dir}'") if ipa_files.empty?
26 | ipa_files.last
27 | end
28 |
29 | def read_pr_description
30 | pr_file = File.expand_path("../../../pr_description.txt", __FILE__)
31 | File.exist?(pr_file) ? File.read(pr_file).strip : "No PR description provided"
32 | end
33 |
34 | # --- Lanes ---
35 |
36 | desc "Authenticate with App Store Connect"
37 | lane :login_to_app_store_connect do
38 | app_store_connect_api_key(
39 | key_id: "", # Your API Key ID
40 | issuer_id: "", # Your Issuer ID
41 | key_filepath: "", # Path to your .p8 key
42 | duration: 1200,
43 | in_house: false
44 | )
45 | end
46 |
47 | desc "Flutter pub get and iOS pod install"
48 | lane :flutter_get_pubs do
49 | Dir.chdir("../../") do
50 | sh("fvm flutter pub get")
51 | sh("cd ios && pod install")
52 | end
53 | end
54 |
55 | desc "Build iOS IPA"
56 | lane :build_ios_ipa do |options|
57 | build_environment = options[:env] || "development"
58 | app_identifier = options[:app_identifier] || ENV['FASTLANE_APP_IDENTIFIER']
59 | flutter_flavor = options[:flutter_flavor] || "development"
60 | app_env_var = options[:app_env] || "dev"
61 | app_version = APP_VERSION
62 |
63 | ENV['FASTLANE_APP_IDENTIFIER'] = app_identifier
64 |
65 | new_build_number = increment_build_number_based_on_testflight(version: app_version)
66 |
67 | obfuscation = build_environment == "prod" ? "--obfuscate --split-debug-info=./symbols/#{build_environment}/ios" : ""
68 |
69 | Dir.chdir("../../") do
70 | sh("fvm flutter build ipa --flavor=#{flutter_flavor} --dart-define=APP_ENV=#{app_env_var} --release #{obfuscation} --build-name=#{app_version} --build-number=#{new_build_number}")
71 | end
72 |
73 | UI.success("✅ iOS IPA build completed")
74 | end
75 |
76 | desc "Export IPA from archive"
77 | lane :export_ios_ipa do |options|
78 | build_environment = options[:env]
79 |
80 | Dir.chdir("../../") do
81 | sh("xcodebuild -exportArchive -archivePath ./build/ios/archive/Runner.xcarchive -exportOptionsPlist ./ios/exportOptions.plist -exportPath ./build/ios/archive/ipa/#{build_environment} -allowProvisioningUpdates ENABLE_BITCODE=NO")
82 | end
83 | end
84 |
85 | desc "Upload IPA to TestFlight"
86 | lane :upload_ios_to_testflight do |options|
87 | build_environment = options[:env]
88 |
89 | latest_ipa = find_latest_ipa(build_environment)
90 | changelog = read_pr_description
91 |
92 | upload_to_testflight(
93 | skip_waiting_for_build_processing: true,
94 | ipa: latest_ipa,
95 | changelog: "Changelog: #{changelog}",
96 | localized_build_info: {
97 | "default" => { whats_new: changelog }
98 | }
99 | )
100 | end
101 |
102 | desc "Upload dSYM to Crashlytics"
103 | lane :upload_dsyms_to_crashlytics do |options|
104 | firebase_app_id = options[:firebase_app_id]
105 | firebase_api_key = options[:firebase_api_key]
106 |
107 | Dir.chdir("../../build/ios/archive/Runner.xcarchive/") do
108 | sh("zip -r dsyms.zip dSYMs")
109 | end
110 |
111 | upload_symbols_to_crashlytics(
112 | dsym_path: "../build/ios/archive/Runner.xcarchive/dsyms.zip",
113 | app_id: firebase_app_id,
114 | api_token: firebase_api_key
115 | )
116 | end
117 |
118 | desc "Complete iOS release process"
119 | lane :release_ios_app do |options|
120 | begin
121 | login_to_app_store_connect
122 |
123 | build_environment = options[:env]
124 | app_identifier = options[:app_identifier]
125 | flutter_flavor = options[:flutter_flavor]
126 | app_env_var = options[:app_env]
127 | firebase_app_id = options[:firebase_app_id]
128 | firebase_api_key = "YOUR_FIREBASE_API_KEY"
129 |
130 | flutter_get_pubs
131 | build_ios_ipa(env: build_environment, app_identifier: app_identifier, flutter_flavor: flutter_flavor, app_env: app_env_var)
132 | export_ios_ipa(env: build_environment)
133 | upload_ios_to_testflight(env: build_environment)
134 | upload_dsyms_to_crashlytics(firebase_app_id: firebase_app_id, firebase_api_key: firebase_api_key)
135 |
136 | UI.success("🚀 Release completed successfully!")
137 | rescue => error
138 | UI.error("❌ Release failed: #{error}")
139 | exit 1
140 | end
141 | end
142 |
143 | # --- Environment Specific Lanes ---
144 |
145 | desc "Release iOS Production"
146 | lane :release_ios_prod do
147 | release_ios_app(
148 | env: "prod",
149 | app_identifier: "com.example.production",
150 | flutter_flavor: "production",
151 | app_env: "prod",
152 | firebase_app_id: "YOUR_PRODUCTION_FIREBASE_APP_ID"
153 | )
154 | end
155 |
156 | desc "Release iOS Development"
157 | lane :release_ios_dev do
158 | release_ios_app(
159 | env: "dev",
160 | app_identifier: "com.example.dev",
161 | flutter_flavor: "development",
162 | app_env: "dev",
163 | firebase_app_id: "YOUR_DEV_FIREBASE_APP_ID"
164 | )
165 | end
166 |
167 | desc "Release iOS Staging"
168 | lane :release_ios_stg do
169 | release_ios_app(
170 | env: "stage",
171 | app_identifier: "com.example.stg",
172 | flutter_flavor: "staging",
173 | app_env: "stage",
174 | firebase_app_id: "YOUR_STAGE_FIREBASE_APP_ID"
175 | )
176 | end
177 | end
178 |
--------------------------------------------------------------------------------
/lib/base/config/flavor_config.dart:
--------------------------------------------------------------------------------
1 | import 'package:hadibucopy/common/exception/unknown_device.dart';
2 |
3 | part 'flavor_const.dart';
4 |
5 | final class FlavorConfiguration {
6 | final EnvironmentType environmentType;
7 | final String baseUrl;
8 |
9 | FlavorConfiguration._({required this.environmentType, required this.baseUrl});
10 |
11 | static final _env = EnvironmentType.currentEnv;
12 |
13 | static final FlavorConfiguration instance = FlavorConfiguration._(
14 | environmentType: _env,
15 | baseUrl: _env.baseUrl,
16 | );
17 | }
18 |
19 | enum EnvironmentType {
20 | dev(FlavorConst.dev),
21 | stage(FlavorConst.stage),
22 | prod(FlavorConst.prod);
23 |
24 | const EnvironmentType(this.environment);
25 |
26 | final String environment;
27 |
28 | static EnvironmentType get currentEnv => EnvironmentType.fromString(
29 | const String.fromEnvironment(FlavorConst.environment));
30 |
31 | String get baseUrl {
32 | return switch (currentEnv) {
33 | dev => FlavorConst.devUrl,
34 | stage => FlavorConst.stageUrl,
35 | prod => FlavorConst.prodUrl,
36 | };
37 | }
38 |
39 | static EnvironmentType fromString(String value) {
40 | return EnvironmentType.values.firstWhere(
41 | (e) => e.environment == value,
42 | orElse: () => throw UnknownDevice(value),
43 | );
44 | }
45 |
46 | bool get isDev => currentEnv == dev;
47 | bool get isStage => currentEnv == stage;
48 | bool get isProd => currentEnv == prod;
49 | }
50 |
--------------------------------------------------------------------------------
/lib/base/config/flavor_const.dart:
--------------------------------------------------------------------------------
1 | part of 'flavor_config.dart';
2 |
3 | mixin FlavorConst {
4 | static const String environment = 'ENVIRONMENT';
5 | static const String devUrl = 'https://dev.example.com';
6 | static const String stageUrl = 'https://stage.example.com';
7 | static const String prodUrl = 'https://prod.example.com';
8 | static const String dev = 'dev';
9 | static const String stage = 'stage';
10 | static const String prod = 'prod';
11 | }
12 |
--------------------------------------------------------------------------------
/lib/bootstrap.dart:
--------------------------------------------------------------------------------
1 | import 'dart:developer';
2 |
3 | import 'package:hadibucopy/base/config/flavor_config.dart';
4 |
5 | void bootstrap() {
6 | final flavorConfig = FlavorConfiguration.instance;
7 | final baseUrl = flavorConfig.baseUrl;
8 | final environment = flavorConfig.environmentType.environment;
9 | log('baseUrl: $baseUrl | environment: $environment');
10 |
11 | /// Add your bootstrap code here
12 | }
13 |
--------------------------------------------------------------------------------
/lib/common/exception/unknown_device.dart:
--------------------------------------------------------------------------------
1 | final class UnknownDevice implements Exception {
2 | final String unsupportedFlavor;
3 | UnknownDevice(this.unsupportedFlavor);
4 |
5 | String get message => 'Unsupported Device: $unsupportedFlavor';
6 | }
7 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:hadibucopy/bootstrap.dart';
3 |
4 | void main() {
5 | bootstrap();
6 | runApp(const MyApp());
7 | }
8 |
9 | class MyApp extends StatelessWidget {
10 | const MyApp({super.key});
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return MaterialApp(
15 | title: 'Material App',
16 | home: Scaffold(
17 | appBar: AppBar(
18 | title: const Text('Material App Bar'),
19 | ),
20 | body: const Center(
21 | child: Text('Hello World'),
22 | ),
23 | ),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/linux/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral
2 |
--------------------------------------------------------------------------------
/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 "hadibucopy")
8 | # The unique GTK application identifier for this application. See:
9 | # https://wiki.gnome.org/HowDoI/ChooseApplicationID
10 | set(APPLICATION_ID "com.example.hadibucopy")
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 |
90 | # Generated plugin build rules, which manage building the plugins and adding
91 | # them to the application.
92 | include(flutter/generated_plugins.cmake)
93 |
94 |
95 | # === Installation ===
96 | # By default, "installing" just makes a relocatable bundle in the build
97 | # directory.
98 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
99 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
100 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
101 | endif()
102 |
103 | # Start with a clean build bundle directory every time.
104 | install(CODE "
105 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
106 | " COMPONENT Runtime)
107 |
108 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
109 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
110 |
111 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
112 | COMPONENT Runtime)
113 |
114 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
115 | COMPONENT Runtime)
116 |
117 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
118 | COMPONENT Runtime)
119 |
120 | foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
121 | install(FILES "${bundled_library}"
122 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
123 | COMPONENT Runtime)
124 | endforeach(bundled_library)
125 |
126 | # Copy the native assets provided by the build.dart from all packages.
127 | set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
128 | install(DIRECTORY "${NATIVE_ASSETS_DIR}"
129 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
130 | COMPONENT Runtime)
131 |
132 | # Fully re-copy the assets directory on each build to avoid having stale files
133 | # from a previous install.
134 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
135 | install(CODE "
136 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
137 | " COMPONENT Runtime)
138 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
139 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
140 |
141 | # Install the AOT library on non-Debug builds only.
142 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
143 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
144 | COMPONENT Runtime)
145 | endif()
146 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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, "hadibucopy");
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, "hadibucopy");
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 GApplication::startup.
85 | static void my_application_startup(GApplication* application) {
86 | //MyApplication* self = MY_APPLICATION(object);
87 |
88 | // Perform any actions required at application startup.
89 |
90 | G_APPLICATION_CLASS(my_application_parent_class)->startup(application);
91 | }
92 |
93 | // Implements GApplication::shutdown.
94 | static void my_application_shutdown(GApplication* application) {
95 | //MyApplication* self = MY_APPLICATION(object);
96 |
97 | // Perform any actions required at application shutdown.
98 |
99 | G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);
100 | }
101 |
102 | // Implements GObject::dispose.
103 | static void my_application_dispose(GObject* object) {
104 | MyApplication* self = MY_APPLICATION(object);
105 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
106 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
107 | }
108 |
109 | static void my_application_class_init(MyApplicationClass* klass) {
110 | G_APPLICATION_CLASS(klass)->activate = my_application_activate;
111 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
112 | G_APPLICATION_CLASS(klass)->startup = my_application_startup;
113 | G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;
114 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
115 | }
116 |
117 | static void my_application_init(MyApplication* self) {}
118 |
119 | MyApplication* my_application_new() {
120 | return MY_APPLICATION(g_object_new(my_application_get_type(),
121 | "application-id", APPLICATION_ID,
122 | "flags", G_APPLICATION_NON_UNIQUE,
123 | nullptr));
124 | }
125 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/macos/.gitignore:
--------------------------------------------------------------------------------
1 | # Flutter-related
2 | **/Flutter/ephemeral/
3 | **/Pods/
4 |
5 | # Xcode-related
6 | **/dgph
7 | **/xcuserdata/
8 |
--------------------------------------------------------------------------------
/macos/Flutter/Flutter-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "ephemeral/Flutter-Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/macos/Flutter/Flutter-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "ephemeral/Flutter-Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/macos/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 |
--------------------------------------------------------------------------------
/macos/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/macos/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | @main
5 | class AppDelegate: FlutterAppDelegate {
6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
7 | return true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
--------------------------------------------------------------------------------
/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 = hadibucopy
9 |
10 | // The application's bundle identifier
11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.hadibucopy
12 |
13 | // The copyright displayed in application information
14 | PRODUCT_COPYRIGHT = Copyright © 2024 com.example. All rights reserved.
15 |
--------------------------------------------------------------------------------
/macos/Runner/Configs/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Debug.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/macos/Runner/Configs/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Release.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/macos/Runner/MainFlutterWindow.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | class MainFlutterWindow: NSWindow {
5 | override func awakeFromNib() {
6 | let flutterViewController = FlutterViewController()
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 |
--------------------------------------------------------------------------------
/macos/Runner/Release.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/macos/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
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 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.11.0"
12 | boolean_selector:
13 | dependency: transitive
14 | description:
15 | name: boolean_selector
16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
17 | url: "https://pub.dev"
18 | source: hosted
19 | version: "2.1.1"
20 | characters:
21 | dependency: transitive
22 | description:
23 | name: characters
24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
25 | url: "https://pub.dev"
26 | source: hosted
27 | version: "1.3.0"
28 | clock:
29 | dependency: transitive
30 | description:
31 | name: clock
32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
33 | url: "https://pub.dev"
34 | source: hosted
35 | version: "1.1.1"
36 | collection:
37 | dependency: transitive
38 | description:
39 | name: collection
40 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
41 | url: "https://pub.dev"
42 | source: hosted
43 | version: "1.18.0"
44 | cupertino_icons:
45 | dependency: "direct main"
46 | description:
47 | name: cupertino_icons
48 | sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
49 | url: "https://pub.dev"
50 | source: hosted
51 | version: "1.0.8"
52 | fake_async:
53 | dependency: transitive
54 | description:
55 | name: fake_async
56 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
57 | url: "https://pub.dev"
58 | source: hosted
59 | version: "1.3.1"
60 | flutter:
61 | dependency: "direct main"
62 | description: flutter
63 | source: sdk
64 | version: "0.0.0"
65 | flutter_lints:
66 | dependency: "direct dev"
67 | description:
68 | name: flutter_lints
69 | sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
70 | url: "https://pub.dev"
71 | source: hosted
72 | version: "4.0.0"
73 | flutter_test:
74 | dependency: "direct dev"
75 | description: flutter
76 | source: sdk
77 | version: "0.0.0"
78 | leak_tracker:
79 | dependency: transitive
80 | description:
81 | name: leak_tracker
82 | sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
83 | url: "https://pub.dev"
84 | source: hosted
85 | version: "10.0.5"
86 | leak_tracker_flutter_testing:
87 | dependency: transitive
88 | description:
89 | name: leak_tracker_flutter_testing
90 | sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
91 | url: "https://pub.dev"
92 | source: hosted
93 | version: "3.0.5"
94 | leak_tracker_testing:
95 | dependency: transitive
96 | description:
97 | name: leak_tracker_testing
98 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
99 | url: "https://pub.dev"
100 | source: hosted
101 | version: "3.0.1"
102 | lints:
103 | dependency: transitive
104 | description:
105 | name: lints
106 | sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
107 | url: "https://pub.dev"
108 | source: hosted
109 | version: "4.0.0"
110 | matcher:
111 | dependency: transitive
112 | description:
113 | name: matcher
114 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
115 | url: "https://pub.dev"
116 | source: hosted
117 | version: "0.12.16+1"
118 | material_color_utilities:
119 | dependency: transitive
120 | description:
121 | name: material_color_utilities
122 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
123 | url: "https://pub.dev"
124 | source: hosted
125 | version: "0.11.1"
126 | meta:
127 | dependency: transitive
128 | description:
129 | name: meta
130 | sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
131 | url: "https://pub.dev"
132 | source: hosted
133 | version: "1.15.0"
134 | path:
135 | dependency: transitive
136 | description:
137 | name: path
138 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
139 | url: "https://pub.dev"
140 | source: hosted
141 | version: "1.9.0"
142 | sky_engine:
143 | dependency: transitive
144 | description: flutter
145 | source: sdk
146 | version: "0.0.99"
147 | source_span:
148 | dependency: transitive
149 | description:
150 | name: source_span
151 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
152 | url: "https://pub.dev"
153 | source: hosted
154 | version: "1.10.0"
155 | stack_trace:
156 | dependency: transitive
157 | description:
158 | name: stack_trace
159 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
160 | url: "https://pub.dev"
161 | source: hosted
162 | version: "1.11.1"
163 | stream_channel:
164 | dependency: transitive
165 | description:
166 | name: stream_channel
167 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
168 | url: "https://pub.dev"
169 | source: hosted
170 | version: "2.1.2"
171 | string_scanner:
172 | dependency: transitive
173 | description:
174 | name: string_scanner
175 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
176 | url: "https://pub.dev"
177 | source: hosted
178 | version: "1.2.0"
179 | term_glyph:
180 | dependency: transitive
181 | description:
182 | name: term_glyph
183 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
184 | url: "https://pub.dev"
185 | source: hosted
186 | version: "1.2.1"
187 | test_api:
188 | dependency: transitive
189 | description:
190 | name: test_api
191 | sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
192 | url: "https://pub.dev"
193 | source: hosted
194 | version: "0.7.2"
195 | vector_math:
196 | dependency: transitive
197 | description:
198 | name: vector_math
199 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
200 | url: "https://pub.dev"
201 | source: hosted
202 | version: "2.1.4"
203 | vm_service:
204 | dependency: transitive
205 | description:
206 | name: vm_service
207 | sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
208 | url: "https://pub.dev"
209 | source: hosted
210 | version: "14.2.5"
211 | sdks:
212 | dart: ">=3.5.1 <4.0.0"
213 | flutter: ">=3.18.0-18.0.pre.54"
214 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: hadibucopy
2 | description: "A new Flutter project."
3 | # The following line prevents the package from being accidentally published to
4 | # pub.dev using `flutter pub publish`. This is preferred for private packages.
5 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
6 |
7 | # The following defines the version and build number for your application.
8 | # A version number is three numbers separated by dots, like 1.2.43
9 | # followed by an optional build number separated by a +.
10 | # Both the version and the builder number may be overridden in flutter
11 | # build by specifying --build-name and --build-number, respectively.
12 | # In Android, build-name is used as versionName while build-number used as versionCode.
13 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
14 | # In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
15 | # Read more about iOS versioning at
16 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17 | # In Windows, build-name is used as the major, minor, and patch parts
18 | # of the product and file versions while build-number is used as the build suffix.
19 | version: 1.0.0+1
20 |
21 | environment:
22 | sdk: ^3.5.1
23 |
24 | # Dependencies specify other packages that your package needs in order to work.
25 | # To automatically upgrade your package dependencies to the latest versions
26 | # consider running `flutter pub upgrade --major-versions`. Alternatively,
27 | # dependencies can be manually updated by changing the version numbers below to
28 | # the latest version available on pub.dev. To see which dependencies have newer
29 | # versions available, run `flutter pub outdated`.
30 | dependencies:
31 | flutter:
32 | sdk: flutter
33 |
34 |
35 | # The following adds the Cupertino Icons font to your application.
36 | # Use with the CupertinoIcons class for iOS style icons.
37 | cupertino_icons: ^1.0.8
38 |
39 | dev_dependencies:
40 | flutter_test:
41 | sdk: flutter
42 |
43 | # The "flutter_lints" package below contains a set of recommended lints to
44 | # encourage good coding practices. The lint set provided by the package is
45 | # activated in the `analysis_options.yaml` file located at the root of your
46 | # package. See that file for information about deactivating specific lint
47 | # rules and activating additional ones.
48 | flutter_lints: ^4.0.0
49 |
50 | # For information on the generic Dart part of this file, see the
51 | # following page: https://dart.dev/tools/pub/pubspec
52 |
53 | # The following section is specific to Flutter packages.
54 | flutter:
55 |
56 | # The following line ensures that the Material Icons font is
57 | # included with your application, so that you can use the icons in
58 | # the material Icons class.
59 | uses-material-design: true
60 |
61 | # To add assets to your application, add an assets section, like this:
62 | # assets:
63 | # - images/a_dot_burr.jpeg
64 | # - images/a_dot_ham.jpeg
65 |
66 | # An image asset can refer to one or more resolution-specific "variants", see
67 | # https://flutter.dev/to/resolution-aware-images
68 |
69 | # For details regarding adding assets from package dependencies, see
70 | # https://flutter.dev/to/asset-from-package
71 |
72 | # To add custom fonts to your application, add a fonts section here,
73 | # in this "flutter" section. Each entry in this list should have a
74 | # "family" key with the font family name, and a "fonts" key with a
75 | # list giving the asset and other descriptors for the font. For
76 | # example:
77 | # fonts:
78 | # - family: Schyler
79 | # fonts:
80 | # - asset: fonts/Schyler-Regular.ttf
81 | # - asset: fonts/Schyler-Italic.ttf
82 | # style: italic
83 | # - family: Trajan Pro
84 | # fonts:
85 | # - asset: fonts/TrajanPro.ttf
86 | # - asset: fonts/TrajanPro_Bold.ttf
87 | # weight: 700
88 | #
89 | # For details regarding fonts from package dependencies,
90 | # see https://flutter.dev/to/font-from-package
91 |
--------------------------------------------------------------------------------
/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:hadibucopy/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(const MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/web/favicon.png
--------------------------------------------------------------------------------
/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/web/icons/Icon-maskable-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/web/icons/Icon-maskable-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-maskable-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/web/icons/Icon-maskable-512.png
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | hadibucopy
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hadibucopy",
3 | "short_name": "hadibucopy",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | },
22 | {
23 | "src": "icons/Icon-maskable-192.png",
24 | "sizes": "192x192",
25 | "type": "image/png",
26 | "purpose": "maskable"
27 | },
28 | {
29 | "src": "icons/Icon-maskable-512.png",
30 | "sizes": "512x512",
31 | "type": "image/png",
32 | "purpose": "maskable"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/windows/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Project-level configuration.
2 | cmake_minimum_required(VERSION 3.14)
3 | project(hadibucopy 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 "hadibucopy")
8 |
9 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
10 | # versions of CMake.
11 | cmake_policy(VERSION 3.14...3.25)
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 |
56 | # Generated plugin build rules, which manage building the plugins and adding
57 | # them to the application.
58 | include(flutter/generated_plugins.cmake)
59 |
60 |
61 | # === Installation ===
62 | # Support files are copied into place next to the executable, so that it can
63 | # run in place. This is done instead of making a separate bundle (as on Linux)
64 | # so that building and running from within Visual Studio will work.
65 | set(BUILD_BUNDLE_DIR "$")
66 | # Make the "install" step default, as it's required to run.
67 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
68 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
69 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
70 | endif()
71 |
72 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
73 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
74 |
75 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
76 | COMPONENT Runtime)
77 |
78 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
79 | COMPONENT Runtime)
80 |
81 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
82 | COMPONENT Runtime)
83 |
84 | if(PLUGIN_BUNDLED_LIBRARIES)
85 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
86 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
87 | COMPONENT Runtime)
88 | endif()
89 |
90 | # Copy the native assets provided by the build.dart from all packages.
91 | set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/")
92 | install(DIRECTORY "${NATIVE_ASSETS_DIR}"
93 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
94 | COMPONENT Runtime)
95 |
96 | # Fully re-copy the assets directory on each build to avoid having stale files
97 | # from a previous install.
98 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
99 | install(CODE "
100 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
101 | " COMPONENT Runtime)
102 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
103 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
104 |
105 | # Install the AOT library on non-Debug builds only.
106 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
107 | CONFIGURATIONS Profile;Release
108 | COMPONENT Runtime)
109 |
--------------------------------------------------------------------------------
/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 | # Set fallback configurations for older versions of the flutter tool.
14 | if (NOT DEFINED FLUTTER_TARGET_PLATFORM)
15 | set(FLUTTER_TARGET_PLATFORM "windows-x64")
16 | endif()
17 |
18 | # === Flutter Library ===
19 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
20 |
21 | # Published to parent scope for install step.
22 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
23 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
24 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
25 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
26 |
27 | list(APPEND FLUTTER_LIBRARY_HEADERS
28 | "flutter_export.h"
29 | "flutter_windows.h"
30 | "flutter_messenger.h"
31 | "flutter_plugin_registrar.h"
32 | "flutter_texture_registrar.h"
33 | )
34 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
35 | add_library(flutter INTERFACE)
36 | target_include_directories(flutter INTERFACE
37 | "${EPHEMERAL_DIR}"
38 | )
39 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
40 | add_dependencies(flutter flutter_assemble)
41 |
42 | # === Wrapper ===
43 | list(APPEND CPP_WRAPPER_SOURCES_CORE
44 | "core_implementations.cc"
45 | "standard_codec.cc"
46 | )
47 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
48 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
49 | "plugin_registrar.cc"
50 | )
51 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
52 | list(APPEND CPP_WRAPPER_SOURCES_APP
53 | "flutter_engine.cc"
54 | "flutter_view_controller.cc"
55 | )
56 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
57 |
58 | # Wrapper sources needed for a plugin.
59 | add_library(flutter_wrapper_plugin STATIC
60 | ${CPP_WRAPPER_SOURCES_CORE}
61 | ${CPP_WRAPPER_SOURCES_PLUGIN}
62 | )
63 | apply_standard_settings(flutter_wrapper_plugin)
64 | set_target_properties(flutter_wrapper_plugin PROPERTIES
65 | POSITION_INDEPENDENT_CODE ON)
66 | set_target_properties(flutter_wrapper_plugin PROPERTIES
67 | CXX_VISIBILITY_PRESET hidden)
68 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
69 | target_include_directories(flutter_wrapper_plugin PUBLIC
70 | "${WRAPPER_ROOT}/include"
71 | )
72 | add_dependencies(flutter_wrapper_plugin flutter_assemble)
73 |
74 | # Wrapper sources needed for the runner.
75 | add_library(flutter_wrapper_app STATIC
76 | ${CPP_WRAPPER_SOURCES_CORE}
77 | ${CPP_WRAPPER_SOURCES_APP}
78 | )
79 | apply_standard_settings(flutter_wrapper_app)
80 | target_link_libraries(flutter_wrapper_app PUBLIC flutter)
81 | target_include_directories(flutter_wrapper_app PUBLIC
82 | "${WRAPPER_ROOT}/include"
83 | )
84 | add_dependencies(flutter_wrapper_app flutter_assemble)
85 |
86 | # === Flutter tool backend ===
87 | # _phony_ is a non-existent file to force this command to run every time,
88 | # since currently there's no way to get a full input/output list from the
89 | # flutter tool.
90 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
91 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
92 | add_custom_command(
93 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
94 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
95 | ${CPP_WRAPPER_SOURCES_APP}
96 | ${PHONY_OUTPUT}
97 | COMMAND ${CMAKE_COMMAND} -E env
98 | ${FLUTTER_TOOL_ENVIRONMENT}
99 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
100 | ${FLUTTER_TARGET_PLATFORM} $
101 | VERBATIM
102 | )
103 | add_custom_target(flutter_assemble DEPENDS
104 | "${FLUTTER_LIBRARY}"
105 | ${FLUTTER_LIBRARY_HEADERS}
106 | ${CPP_WRAPPER_SOURCES_CORE}
107 | ${CPP_WRAPPER_SOURCES_PLUGIN}
108 | ${CPP_WRAPPER_SOURCES_APP}
109 | )
110 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
37 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
38 |
39 | # Run the Flutter tool portions of the build. This must not be removed.
40 | add_dependencies(${BINARY_NAME} flutter_assemble)
41 |
--------------------------------------------------------------------------------
/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.example" "\0"
93 | VALUE "FileDescription", "hadibucopy" "\0"
94 | VALUE "FileVersion", VERSION_AS_STRING "\0"
95 | VALUE "InternalName", "hadibucopy" "\0"
96 | VALUE "LegalCopyright", "Copyright (C) 2024 com.example. All rights reserved." "\0"
97 | VALUE "OriginalFilename", "hadibucopy.exe" "\0"
98 | VALUE "ProductName", "hadibucopy" "\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 |
--------------------------------------------------------------------------------
/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 |
30 | flutter_controller_->engine()->SetNextFrameCallback([&]() {
31 | this->Show();
32 | });
33 |
34 | // Flutter can complete the first frame before the "show window" callback is
35 | // registered. The following call ensures a frame is pending to ensure the
36 | // window is shown. It is a no-op if the first frame hasn't completed yet.
37 | flutter_controller_->ForceRedraw();
38 |
39 | return true;
40 | }
41 |
42 | void FlutterWindow::OnDestroy() {
43 | if (flutter_controller_) {
44 | flutter_controller_ = nullptr;
45 | }
46 |
47 | Win32Window::OnDestroy();
48 | }
49 |
50 | LRESULT
51 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
52 | WPARAM const wparam,
53 | LPARAM const lparam) noexcept {
54 | // Give Flutter, including plugins, an opportunity to handle window messages.
55 | if (flutter_controller_) {
56 | std::optional result =
57 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
58 | lparam);
59 | if (result) {
60 | return *result;
61 | }
62 | }
63 |
64 | switch (message) {
65 | case WM_FONTCHANGE:
66 | flutter_controller_->engine()->ReloadSystemFonts();
67 | break;
68 | }
69 |
70 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
71 | }
72 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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.Create(L"hadibucopy", 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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/windows/runner/resources/app_icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mucahitsimsek/Flutter-CI-CD/1d363d80c6af7ebe568d607affed823060d1f1e1/windows/runner/resources/app_icon.ico
--------------------------------------------------------------------------------
/windows/runner/runner.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PerMonitorV2
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/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 | unsigned int target_length = ::WideCharToMultiByte(
49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
50 | -1, nullptr, 0, nullptr, nullptr)
51 | -1; // remove the trailing null character
52 | int input_length = (int)wcslen(utf16_string);
53 | std::string utf8_string;
54 | if (target_length == 0 || target_length > utf8_string.max_size()) {
55 | return utf8_string;
56 | }
57 | utf8_string.resize(target_length);
58 | int converted_length = ::WideCharToMultiByte(
59 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
60 | input_length, utf8_string.data(), target_length, nullptr, nullptr);
61 | if (converted_length == 0) {
62 | return std::string();
63 | }
64 | return utf8_string;
65 | }
66 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/windows/runner/win32_window.cpp:
--------------------------------------------------------------------------------
1 | #include "win32_window.h"
2 |
3 | #include
4 | #include
5 |
6 | #include "resource.h"
7 |
8 | namespace {
9 |
10 | /// Window attribute that enables dark mode window decorations.
11 | ///
12 | /// Redefined in case the developer's machine has a Windows SDK older than
13 | /// version 10.0.22000.0.
14 | /// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
15 | #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
16 | #define DWMWA_USE_IMMERSIVE_DARK_MODE 20
17 | #endif
18 |
19 | constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
20 |
21 | /// Registry key for app theme preference.
22 | ///
23 | /// A value of 0 indicates apps should use dark mode. A non-zero or missing
24 | /// value indicates apps should use light mode.
25 | constexpr const wchar_t kGetPreferredBrightnessRegKey[] =
26 | L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
27 | constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme";
28 |
29 | // The number of Win32Window objects that currently exist.
30 | static int g_active_window_count = 0;
31 |
32 | using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
33 |
34 | // Scale helper to convert logical scaler values to physical using passed in
35 | // scale factor
36 | int Scale(int source, double scale_factor) {
37 | return static_cast(source * scale_factor);
38 | }
39 |
40 | // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
41 | // This API is only needed for PerMonitor V1 awareness mode.
42 | void EnableFullDpiSupportIfAvailable(HWND hwnd) {
43 | HMODULE user32_module = LoadLibraryA("User32.dll");
44 | if (!user32_module) {
45 | return;
46 | }
47 | auto enable_non_client_dpi_scaling =
48 | reinterpret_cast(
49 | GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
50 | if (enable_non_client_dpi_scaling != nullptr) {
51 | enable_non_client_dpi_scaling(hwnd);
52 | }
53 | FreeLibrary(user32_module);
54 | }
55 |
56 | } // namespace
57 |
58 | // Manages the Win32Window's window class registration.
59 | class WindowClassRegistrar {
60 | public:
61 | ~WindowClassRegistrar() = default;
62 |
63 | // Returns the singleton registrar instance.
64 | static WindowClassRegistrar* GetInstance() {
65 | if (!instance_) {
66 | instance_ = new WindowClassRegistrar();
67 | }
68 | return instance_;
69 | }
70 |
71 | // Returns the name of the window class, registering the class if it hasn't
72 | // previously been registered.
73 | const wchar_t* GetWindowClass();
74 |
75 | // Unregisters the window class. Should only be called if there are no
76 | // instances of the window.
77 | void UnregisterWindowClass();
78 |
79 | private:
80 | WindowClassRegistrar() = default;
81 |
82 | static WindowClassRegistrar* instance_;
83 |
84 | bool class_registered_ = false;
85 | };
86 |
87 | WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
88 |
89 | const wchar_t* WindowClassRegistrar::GetWindowClass() {
90 | if (!class_registered_) {
91 | WNDCLASS window_class{};
92 | window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
93 | window_class.lpszClassName = kWindowClassName;
94 | window_class.style = CS_HREDRAW | CS_VREDRAW;
95 | window_class.cbClsExtra = 0;
96 | window_class.cbWndExtra = 0;
97 | window_class.hInstance = GetModuleHandle(nullptr);
98 | window_class.hIcon =
99 | LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
100 | window_class.hbrBackground = 0;
101 | window_class.lpszMenuName = nullptr;
102 | window_class.lpfnWndProc = Win32Window::WndProc;
103 | RegisterClass(&window_class);
104 | class_registered_ = true;
105 | }
106 | return kWindowClassName;
107 | }
108 |
109 | void WindowClassRegistrar::UnregisterWindowClass() {
110 | UnregisterClass(kWindowClassName, nullptr);
111 | class_registered_ = false;
112 | }
113 |
114 | Win32Window::Win32Window() {
115 | ++g_active_window_count;
116 | }
117 |
118 | Win32Window::~Win32Window() {
119 | --g_active_window_count;
120 | Destroy();
121 | }
122 |
123 | bool Win32Window::Create(const std::wstring& title,
124 | const Point& origin,
125 | const Size& size) {
126 | Destroy();
127 |
128 | const wchar_t* window_class =
129 | WindowClassRegistrar::GetInstance()->GetWindowClass();
130 |
131 | const POINT target_point = {static_cast(origin.x),
132 | static_cast(origin.y)};
133 | HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
134 | UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
135 | double scale_factor = dpi / 96.0;
136 |
137 | HWND window = CreateWindow(
138 | window_class, title.c_str(), WS_OVERLAPPEDWINDOW,
139 | Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
140 | Scale(size.width, scale_factor), Scale(size.height, scale_factor),
141 | nullptr, nullptr, GetModuleHandle(nullptr), this);
142 |
143 | if (!window) {
144 | return false;
145 | }
146 |
147 | UpdateTheme(window);
148 |
149 | return OnCreate();
150 | }
151 |
152 | bool Win32Window::Show() {
153 | return ShowWindow(window_handle_, SW_SHOWNORMAL);
154 | }
155 |
156 | // static
157 | LRESULT CALLBACK Win32Window::WndProc(HWND const window,
158 | UINT const message,
159 | WPARAM const wparam,
160 | LPARAM const lparam) noexcept {
161 | if (message == WM_NCCREATE) {
162 | auto window_struct = reinterpret_cast(lparam);
163 | SetWindowLongPtr(window, GWLP_USERDATA,
164 | reinterpret_cast(window_struct->lpCreateParams));
165 |
166 | auto that = static_cast(window_struct->lpCreateParams);
167 | EnableFullDpiSupportIfAvailable(window);
168 | that->window_handle_ = window;
169 | } else if (Win32Window* that = GetThisFromHandle(window)) {
170 | return that->MessageHandler(window, message, wparam, lparam);
171 | }
172 |
173 | return DefWindowProc(window, message, wparam, lparam);
174 | }
175 |
176 | LRESULT
177 | Win32Window::MessageHandler(HWND hwnd,
178 | UINT const message,
179 | WPARAM const wparam,
180 | LPARAM const lparam) noexcept {
181 | switch (message) {
182 | case WM_DESTROY:
183 | window_handle_ = nullptr;
184 | Destroy();
185 | if (quit_on_close_) {
186 | PostQuitMessage(0);
187 | }
188 | return 0;
189 |
190 | case WM_DPICHANGED: {
191 | auto newRectSize = reinterpret_cast(lparam);
192 | LONG newWidth = newRectSize->right - newRectSize->left;
193 | LONG newHeight = newRectSize->bottom - newRectSize->top;
194 |
195 | SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
196 | newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
197 |
198 | return 0;
199 | }
200 | case WM_SIZE: {
201 | RECT rect = GetClientArea();
202 | if (child_content_ != nullptr) {
203 | // Size and position the child window.
204 | MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
205 | rect.bottom - rect.top, TRUE);
206 | }
207 | return 0;
208 | }
209 |
210 | case WM_ACTIVATE:
211 | if (child_content_ != nullptr) {
212 | SetFocus(child_content_);
213 | }
214 | return 0;
215 |
216 | case WM_DWMCOLORIZATIONCOLORCHANGED:
217 | UpdateTheme(hwnd);
218 | return 0;
219 | }
220 |
221 | return DefWindowProc(window_handle_, message, wparam, lparam);
222 | }
223 |
224 | void Win32Window::Destroy() {
225 | OnDestroy();
226 |
227 | if (window_handle_) {
228 | DestroyWindow(window_handle_);
229 | window_handle_ = nullptr;
230 | }
231 | if (g_active_window_count == 0) {
232 | WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
233 | }
234 | }
235 |
236 | Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
237 | return reinterpret_cast(
238 | GetWindowLongPtr(window, GWLP_USERDATA));
239 | }
240 |
241 | void Win32Window::SetChildContent(HWND content) {
242 | child_content_ = content;
243 | SetParent(content, window_handle_);
244 | RECT frame = GetClientArea();
245 |
246 | MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
247 | frame.bottom - frame.top, true);
248 |
249 | SetFocus(child_content_);
250 | }
251 |
252 | RECT Win32Window::GetClientArea() {
253 | RECT frame;
254 | GetClientRect(window_handle_, &frame);
255 | return frame;
256 | }
257 |
258 | HWND Win32Window::GetHandle() {
259 | return window_handle_;
260 | }
261 |
262 | void Win32Window::SetQuitOnClose(bool quit_on_close) {
263 | quit_on_close_ = quit_on_close;
264 | }
265 |
266 | bool Win32Window::OnCreate() {
267 | // No-op; provided for subclasses.
268 | return true;
269 | }
270 |
271 | void Win32Window::OnDestroy() {
272 | // No-op; provided for subclasses.
273 | }
274 |
275 | void Win32Window::UpdateTheme(HWND const window) {
276 | DWORD light_mode;
277 | DWORD light_mode_size = sizeof(light_mode);
278 | LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey,
279 | kGetPreferredBrightnessRegValue,
280 | RRF_RT_REG_DWORD, nullptr, &light_mode,
281 | &light_mode_size);
282 |
283 | if (result == ERROR_SUCCESS) {
284 | BOOL enable_dark_mode = light_mode == 0;
285 | DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE,
286 | &enable_dark_mode, sizeof(enable_dark_mode));
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/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 a win32 window with |title| that is positioned and sized 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 this function will scale the inputted width and height as
35 | // as appropriate for the default monitor. The window is invisible until
36 | // |Show| is called. Returns true if the window was created successfully.
37 | bool Create(const std::wstring& title, const Point& origin, const Size& size);
38 |
39 | // Show the current window. Returns true if the window was successfully shown.
40 | bool Show();
41 |
42 | // Release OS resources associated with window.
43 | void Destroy();
44 |
45 | // Inserts |content| into the window tree.
46 | void SetChildContent(HWND content);
47 |
48 | // Returns the backing Window handle to enable clients to set icon and other
49 | // window properties. Returns nullptr if the window has been destroyed.
50 | HWND GetHandle();
51 |
52 | // If true, closing this window will quit the application.
53 | void SetQuitOnClose(bool quit_on_close);
54 |
55 | // Return a RECT representing the bounds of the current client area.
56 | RECT GetClientArea();
57 |
58 | protected:
59 | // Processes and route salient window messages for mouse handling,
60 | // size change and DPI. Delegates handling of these to member overloads that
61 | // inheriting classes can handle.
62 | virtual LRESULT MessageHandler(HWND window,
63 | UINT const message,
64 | WPARAM const wparam,
65 | LPARAM const lparam) noexcept;
66 |
67 | // Called when CreateAndShow is called, allowing subclass window-related
68 | // setup. Subclasses should return false if setup fails.
69 | virtual bool OnCreate();
70 |
71 | // Called when Destroy is called.
72 | virtual void OnDestroy();
73 |
74 | private:
75 | friend class WindowClassRegistrar;
76 |
77 | // OS callback called by message pump. Handles the WM_NCCREATE message which
78 | // is passed when the non-client area is being created and enables automatic
79 | // non-client DPI scaling so that the non-client area automatically
80 | // responds to changes in DPI. All other messages are handled by
81 | // MessageHandler.
82 | static LRESULT CALLBACK WndProc(HWND const window,
83 | UINT const message,
84 | WPARAM const wparam,
85 | LPARAM const lparam) noexcept;
86 |
87 | // Retrieves a class instance pointer for |window|
88 | static Win32Window* GetThisFromHandle(HWND const window) noexcept;
89 |
90 | // Update the window frame's theme to match the system theme.
91 | static void UpdateTheme(HWND const window);
92 |
93 | bool quit_on_close_ = false;
94 |
95 | // window handle for top level window.
96 | HWND window_handle_ = nullptr;
97 |
98 | // window handle for hosted content.
99 | HWND child_content_ = nullptr;
100 | };
101 |
102 | #endif // RUNNER_WIN32_WINDOW_H_
103 |
--------------------------------------------------------------------------------