├── assets └── images │ └── README.md ├── ios ├── Runner │ ├── Runner-Bridging-Header.h │ ├── Assets.xcassets │ │ ├── LaunchImage.imageset │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ ├── README.md │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── 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-1024x1024@1x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ └── Info.plist ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── AppFrameworkInfo.plist ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── project.pbxproj ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist ├── RunnerTests │ └── RunnerTests.swift ├── .gitignore └── Podfile ├── analysis_options.yaml ├── android ├── gradle.properties ├── app │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ ├── 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 │ │ │ │ ├── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable-v21 │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── values │ │ │ │ │ └── styles.xml │ │ │ │ └── values-night │ │ │ │ │ └── styles.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── starterapp │ │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── profile │ │ │ └── AndroidManifest.xml │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── .gitignore ├── settings.gradle └── build.gradle ├── l10n.yaml ├── lib ├── l10n │ ├── l10n.dart │ └── translations │ │ └── app_en.arb ├── constants │ ├── repository_constants │ │ ├── api_constants │ │ │ ├── auth │ │ │ │ └── api_token_constants.dart │ │ │ └── routes │ │ │ │ └── api_route_constants.dart │ │ └── local_storage_constants │ │ │ ├── settings │ │ │ └── app_settings_keys.dart │ │ │ └── auth │ │ │ └── jwt_token_keys.dart │ └── style │ │ └── style_constants.dart ├── routes │ ├── routes_constants.dart │ └── router.dart ├── helper │ ├── api │ │ └── api_route_helper.dart │ ├── locale │ │ └── language_locale_helper.dart │ └── auth │ │ └── jwt_token_helper.dart ├── themes │ └── themes.dart ├── exceptions │ ├── auth │ │ └── auth_exception.dart │ └── api │ │ └── api_exceptions.dart ├── pages │ ├── undefinited_page.dart │ ├── landing_page.dart │ ├── error │ │ └── no_internet_page.dart │ └── splash_page.dart ├── main.dart ├── repository │ ├── local_storage │ │ ├── settings │ │ │ └── preferences_local_storage.dart │ │ ├── base │ │ │ └── local_storage_core.dart │ │ └── auth │ │ │ └── jwt_local_storage.dart │ └── api │ │ ├── auth │ │ └── api_login.dart │ │ └── base │ │ └── api_core.dart ├── starter_app.dart └── services │ └── locale_service_provider.dart ├── .github └── workflows │ ├── code_quality_flutter.yml │ └── flutter_ci.yml ├── pubspec.yaml ├── LICENSE ├── README.md └── .gitignore /assets/images/README.md: -------------------------------------------------------------------------------- 1 | ## Only for fill folder 2 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | linter: 3 | rules: -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /l10n.yaml: -------------------------------------------------------------------------------- 1 | arb-dir: lib/l10n/translations 2 | template-arb-file: app_en.arb 3 | output-localization-file: app_localizations.dart -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /lib/l10n/l10n.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | class L10n { 4 | static final allLanguagesSupported = [ 5 | const Locale('en'), 6 | ]; 7 | } 8 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliaTolin/flutter-template-starter-app/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliaTolin/flutter-template-starter-app/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /lib/l10n/translations/app_en.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "Hello Starter App!", 3 | "error_noInternet":"Check you internet connection and retry!", 4 | "retry": "Retry" 5 | } 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliaTolin/flutter-template-starter-app/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliaTolin/flutter-template-starter-app/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /lib/constants/repository_constants/api_constants/auth/api_token_constants.dart: -------------------------------------------------------------------------------- 1 | class JwtTokenConstants { 2 | static const String jwtSecretPhrase = 'token_secret_phrase'; 3 | } 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliaTolin/flutter-template-starter-app/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliaTolin/flutter-template-starter-app/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /lib/constants/repository_constants/local_storage_constants/settings/app_settings_keys.dart: -------------------------------------------------------------------------------- 1 | class AppSettingsKeys { 2 | static const String languagePreferencesKey = "languageCodePreferences"; 3 | } 4 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/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/EliaTolin/flutter-template-starter-app/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliaTolin/flutter-template-starter-app/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliaTolin/flutter-template-starter-app/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/starterapp/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.starterapp 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliaTolin/flutter-template-starter-app/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EliaTolin/flutter-template-starter-app/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/routes/routes_constants.dart: -------------------------------------------------------------------------------- 1 | class RoutesConstants { 2 | static const String splashScreenRoute = "/"; 3 | static const String landingRoute = "/landing"; 4 | static const String noInternetRoute = "/noInternet"; 5 | } 6 | -------------------------------------------------------------------------------- /lib/constants/repository_constants/local_storage_constants/auth/jwt_token_keys.dart: -------------------------------------------------------------------------------- 1 | class JwtTokenKeys { 2 | static const String accessTokenKey = "accessTokenKey"; 3 | static const String refreshTokenKey = "refreshTokenKey"; 4 | } 5 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip 6 | -------------------------------------------------------------------------------- /lib/helper/api/api_route_helper.dart: -------------------------------------------------------------------------------- 1 | import 'package:starterapp/constants/repository_constants/api_constants/routes/api_route_constants.dart'; 2 | 3 | class ApiRouteHelper { 4 | static String getBaseUrl() => 5 | "${ApiRouteConstants.getBaseUrl()}${ApiRouteConstants.basePath}/"; 6 | } 7 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/themes/themes.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:starterapp/constants/style/style_constants.dart'; 3 | 4 | ThemeData lightTheme = ThemeData( 5 | useMaterial3: true, 6 | primaryColor: StyleConstants.colorOfApp, 7 | scaffoldBackgroundColor: StyleConstants.scaffoldBackgroundColor, 8 | ); 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/constants/style/style_constants.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class StyleConstants { 4 | // Filled with example constants 5 | static const Color scaffoldBackgroundColor = Colors.white; 6 | static const Color colorOfApp = Color.fromRGBO(12, 98, 235, 1); 7 | static const Color colorTitle = Colors.black; 8 | } 9 | -------------------------------------------------------------------------------- /lib/exceptions/auth/auth_exception.dart: -------------------------------------------------------------------------------- 1 | // Unauthorized Exception 2 | class UnauthorizedException implements Exception { 3 | const UnauthorizedException() : super(); 4 | } 5 | 6 | // Refresh Token Expired Exception 7 | class RefreshTokenExpiredException implements Exception { 8 | const RefreshTokenExpiredException() : super(); 9 | } 10 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /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/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. -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lib/pages/undefinited_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class UndefinitedPage extends StatelessWidget { 4 | final String? name; 5 | const UndefinitedPage({Key? key, this.name = ""}) : super(key: key); 6 | 7 | @override 8 | Widget build(BuildContext context) { 9 | return Scaffold( 10 | appBar: AppBar(title: const Text("Undefinited View")), 11 | body: Center( 12 | child: Text("Route for $name is not defined"), 13 | ), 14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/constants/repository_constants/api_constants/routes/api_route_constants.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | 3 | class ApiRouteConstants { 4 | static String getBaseUrl() { 5 | if (kDebugMode) { 6 | return "https://route.it"; 7 | } else { 8 | throw Exception("Production mode is not supported yet"); 9 | } 10 | } 11 | 12 | // Add here the route constants 13 | static String basePath = "/api/v1"; 14 | 15 | static String tokenPath = "/token/"; 16 | 17 | static String refreshTokenPath = "${tokenPath}refresh/"; 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/code_quality_flutter.yml: -------------------------------------------------------------------------------- 1 | name: Code Quality 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | format-and-fix: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v2 11 | 12 | - name: Setup flutter 13 | uses: subosito/flutter-action@v2 14 | with: 15 | channel: stable 16 | 17 | - name: Get packages 18 | run: flutter pub get 19 | 20 | - name: Check format errors 21 | run: dart format --set-exit-if-changed . 22 | 23 | - name: Check lint errors 24 | run: flutter analyze . 25 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: starterapp 2 | description: A new Flutter project. 3 | publish_to: 'none' 4 | 5 | version: 1.0.0+1 6 | 7 | environment: 8 | sdk: '>=3.0.3 <4.0.0' 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | cupertino_icons: ^1.0.2 14 | dio: ^5.1.1 15 | flutter_localizations: 16 | sdk: flutter 17 | intl: any 18 | provider: ^6.0.5 19 | shared_preferences: ^2.1.2 20 | dart_jsonwebtoken: ^2.8.0 21 | internet_connection_checker: ^1.0.0+1 22 | 23 | dev_dependencies: 24 | flutter_test: 25 | sdk: flutter 26 | flutter_lints: ^2.0.0 27 | 28 | flutter: 29 | uses-material-design: true 30 | generate: true 31 | assets: 32 | - assets/ 33 | - assets/images/ -------------------------------------------------------------------------------- /lib/exceptions/api/api_exceptions.dart: -------------------------------------------------------------------------------- 1 | // No connection 2 | class NoInternetConnectionException implements Exception { 3 | const NoInternetConnectionException() : super(); 4 | } 5 | 6 | // Internal Server Error Exception 7 | class InternalServerErrorException implements Exception { 8 | String description; 9 | InternalServerErrorException({this.description = ""}) : super(); 10 | } 11 | 12 | // End Point not found Exception 13 | class NotFoundEndPointException implements Exception { 14 | const NotFoundEndPointException() : super(); 15 | } 16 | 17 | // Bad Request Exception 18 | class BadRequestException implements Exception { 19 | String description; 20 | BadRequestException(this.description) : super(); 21 | } 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.7.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.3.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | tasks.register("clean", Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:provider/provider.dart'; 3 | import 'package:starterapp/services/locale_service_provider.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:starterapp/starter_app.dart'; 6 | 7 | void main() async { 8 | WidgetsFlutterBinding.ensureInitialized(); 9 | // Set only portrait orientation 10 | await SystemChrome.setPreferredOrientations( 11 | [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown], 12 | ); 13 | 14 | runApp( 15 | MultiProvider( 16 | providers: [ 17 | //Add here the providers 18 | ChangeNotifierProvider( 19 | create: (context) => LocaleServiceProvider(), 20 | ), 21 | ], 22 | child: const StarterApp(), 23 | ), 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /lib/repository/local_storage/settings/preferences_local_storage.dart: -------------------------------------------------------------------------------- 1 | import 'package:starterapp/repository/local_storage/base/local_storage_core.dart'; 2 | import 'package:starterapp/constants/repository_constants/local_storage_constants/settings/app_settings_keys.dart'; 3 | 4 | class PreferenceLocalStorage { 5 | LocalStorageCore localStorageCore = LocalStorageCore(); 6 | 7 | Future isSetLanguagePreferences() async { 8 | return await localStorageCore.exist(AppSettingsKeys.languagePreferencesKey); 9 | } 10 | 11 | Future getLanguagePreferences() async { 12 | return await localStorageCore.read(AppSettingsKeys.languagePreferencesKey); 13 | } 14 | 15 | Future setLanguagePreferences(String code) async { 16 | await localStorageCore.save(AppSettingsKeys.languagePreferencesKey, code); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 11.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/pages/landing_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:starterapp/constants/style/style_constants.dart'; 3 | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; 4 | 5 | class LandingPage extends StatelessWidget { 6 | const LandingPage({super.key}); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | Size size = MediaQuery.of(context).size; 11 | return Scaffold( 12 | appBar: AppBar( 13 | backgroundColor: StyleConstants.scaffoldBackgroundColor, 14 | toolbarHeight: size.height * 0.1, 15 | elevation: 0, 16 | automaticallyImplyLeading: false, 17 | title: const Text( 18 | "StarterApp", 19 | style: TextStyle( 20 | fontSize: 40, 21 | color: StyleConstants.colorTitle, 22 | fontWeight: FontWeight.bold, 23 | ), 24 | ), 25 | ), 26 | body: Center( 27 | child: Text(AppLocalizations.of(context)!.helloWorld), 28 | ), 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/repository/local_storage/base/local_storage_core.dart: -------------------------------------------------------------------------------- 1 | import 'package:shared_preferences/shared_preferences.dart'; 2 | import 'dart:convert'; 3 | 4 | class LocalStorageCore { 5 | LocalStorageCore(); 6 | 7 | Future read(String key) async { 8 | final prefs = await SharedPreferences.getInstance(); 9 | var data = prefs.getString(key); 10 | return json.decode(data.toString()); 11 | } 12 | 13 | save(String key, value) async { 14 | final prefs = await SharedPreferences.getInstance(); 15 | prefs.setString(key, json.encode(value)); 16 | } 17 | 18 | remove(String key) async { 19 | final prefs = await SharedPreferences.getInstance(); 20 | prefs.remove(key); 21 | } 22 | 23 | Future clear() async { 24 | final prefs = await SharedPreferences.getInstance(); 25 | return await prefs.clear(); 26 | } 27 | 28 | Future exist(String key) async { 29 | final prefs = await SharedPreferences.getInstance(); 30 | bool exist = prefs.containsKey(key); 31 | return exist; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /lib/helper/locale/language_locale_helper.dart: -------------------------------------------------------------------------------- 1 | class LanguageLocalHelper { 2 | // Add other languages here 3 | static final Map> isoLangs = { 4 | "fr": {"name": "French", "nativeName": "Français"}, 5 | "it": {"name": "Italian", "nativeName": "Italiano"}, 6 | "en": {"name": "English", "nativeName": "English"}, 7 | "es": {"name": "Spanish", "nativeName": "Español"}, 8 | "pl": {"name": "Polish", "nativeName": "Polski"}, 9 | "pt": {"name": "Portuguese", "nativeName": "Português"}, 10 | "de": {"name": "German", "nativeName": "Deutsch"}, 11 | }; 12 | 13 | Map> getIsoLangs() => isoLangs; 14 | 15 | getDisplayLanguage(key) { 16 | if (isoLangs.containsKey(key)) { 17 | return isoLangs[key]; 18 | } else { 19 | throw Exception("Language key incorrect"); 20 | } 21 | } 22 | 23 | getNativeLanguageName(countryCode) { 24 | return getDisplayLanguage(countryCode)["nativeName"]; 25 | } 26 | 27 | getLanguageName(countryCode) { 28 | return getDisplayLanguage(countryCode)["name"]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Elia Tolin 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 | -------------------------------------------------------------------------------- /lib/starter_app.dart: -------------------------------------------------------------------------------- 1 | import 'package:provider/provider.dart'; 2 | import 'package:starterapp/l10n/l10n.dart'; 3 | import 'package:starterapp/routes/routes_constants.dart'; 4 | import 'package:starterapp/services/locale_service_provider.dart'; 5 | import 'package:starterapp/themes/themes.dart'; 6 | import 'routes/router.dart' as router; 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; 9 | 10 | class StarterApp extends StatelessWidget { 11 | const StarterApp({super.key}); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Consumer( 16 | builder: (context, provider, child) { 17 | return MaterialApp( 18 | debugShowCheckedModeBanner: false, 19 | title: 'StarterApp', 20 | theme: lightTheme, 21 | initialRoute: RoutesConstants.splashScreenRoute, 22 | localizationsDelegates: AppLocalizations.localizationsDelegates, 23 | supportedLocales: L10n.allLanguagesSupported, 24 | onGenerateRoute: router.generateRoute, 25 | ); 26 | }, 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/services/locale_service_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:starterapp/l10n/l10n.dart'; 3 | import 'package:starterapp/repository/local_storage/settings/preferences_local_storage.dart'; 4 | 5 | class LocaleServiceProvider with ChangeNotifier { 6 | Locale? _locale; 7 | Locale? get locale => _locale; 8 | PreferenceLocalStorage preferenceLocalStorage = PreferenceLocalStorage(); 9 | 10 | Future initLocale(String languageCode) async { 11 | if (await preferenceLocalStorage.isSetLanguagePreferences()) { 12 | String languageCode = 13 | await preferenceLocalStorage.getLanguagePreferences(); 14 | if (languageCode.isNotEmpty) { 15 | setLocale(Locale(languageCode)); 16 | } 17 | return; 18 | } 19 | _locale = Locale(languageCode); 20 | } 21 | 22 | void setLocale(Locale loc) async { 23 | await preferenceLocalStorage.setLanguagePreferences(loc.languageCode); 24 | if (!L10n.allLanguagesSupported.contains(loc)) return; 25 | _locale = loc; 26 | notifyListeners(); 27 | } 28 | 29 | void clearLocale() { 30 | _locale = null; 31 | notifyListeners(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/routes/router.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:starterapp/pages/error/no_internet_page.dart'; 3 | import 'package:starterapp/pages/landing_page.dart'; 4 | import 'package:starterapp/pages/splash_page.dart'; 5 | import 'package:starterapp/pages/undefinited_page.dart'; 6 | import 'package:starterapp/routes/routes_constants.dart'; 7 | 8 | Route generateRoute(RouteSettings settings) { 9 | switch (settings.name) { 10 | case RoutesConstants.splashScreenRoute: 11 | return MaterialPageRoute( 12 | settings: settings, 13 | builder: (context) => const SplashPage(), 14 | ); 15 | case RoutesConstants.landingRoute: 16 | return MaterialPageRoute( 17 | settings: settings, 18 | builder: (context) => const LandingPage(), 19 | ); 20 | case RoutesConstants.noInternetRoute: 21 | return MaterialPageRoute( 22 | settings: settings, 23 | builder: (context) => const NoInternetPage(), 24 | ); 25 | default: 26 | return MaterialPageRoute( 27 | settings: settings, 28 | builder: (context) => UndefinitedPage(name: settings.name), 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/repository/api/auth/api_login.dart: -------------------------------------------------------------------------------- 1 | /* 2 | ################################### 3 | Use this class for authentication api 4 | ################################### 5 | */ 6 | 7 | // import 'dart:developer'; 8 | // import 'package:dio/dio.dart'; 9 | // import 'package:starterapp/api/base/api_core.dart'; 10 | // import 'package:starterapp/helper/api/api_route_helper.dart'; 11 | // import 'package:starterapp/helper/api/jwt_token_helper.dart'; 12 | 13 | // class ApiAuth { 14 | // ApiBaseCore apiBaseCore = ApiBaseCore(); 15 | // Future login(String email, String password) async { 16 | // try { 17 | // Response? response = await apiBaseCore.postHTTP( 18 | // ApiRouteHelper.tokenPath, {"email": email, "password": password}); 19 | // if (response == null) { 20 | // return false; 21 | // } 22 | // String accessToken = response.data["access"]; 23 | // String refreshToken = response.data["refresh"]; 24 | // log("Access token: $accessToken"); 25 | // log("Refresh token: $refreshToken"); 26 | // await JwtTokenHelper().saveNewJwtTokens(accessToken, refreshToken); 27 | // return true; 28 | // } on Exception { 29 | // return false; 30 | // } 31 | // } 32 | // } 33 | -------------------------------------------------------------------------------- /.github/workflows/flutter_ci.yml: -------------------------------------------------------------------------------- 1 | name: Flutter CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build-android: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - name: Checkout repository 11 | uses: actions/checkout@v3 12 | 13 | - name: Setup Java 14 | uses: actions/setup-java@v2 15 | with: 16 | distribution: "zulu" 17 | java-version: "11" 18 | 19 | - name: Setup Flutter 20 | uses: subosito/flutter-action@v2 21 | with: 22 | channel: "stable" 23 | cache: true 24 | 25 | - name: Install dependencies 26 | run: flutter pub get 27 | 28 | - name: Build APK 29 | run: flutter build apk 30 | 31 | - name: Build App Bundle 32 | run: flutter build appbundle 33 | 34 | build-ios: 35 | runs-on: macos-latest 36 | 37 | steps: 38 | - name: Checkout repository 39 | uses: actions/checkout@v3 40 | 41 | - name: Setup Flutter 42 | uses: subosito/flutter-action@v2 43 | with: 44 | channel: "stable" 45 | cache: true 46 | architecture: x64 47 | 48 | - name: Install dependencies 49 | run: flutter pub get 50 | 51 | - name: Build iOS 52 | run: flutter build ios --release --no-codesign 53 | -------------------------------------------------------------------------------- /lib/repository/local_storage/auth/jwt_local_storage.dart: -------------------------------------------------------------------------------- 1 | import 'package:starterapp/constants/repository_constants/local_storage_constants/auth/jwt_token_keys.dart'; 2 | import 'package:starterapp/repository/local_storage/base/local_storage_core.dart'; 3 | 4 | class JwtLocalStorage { 5 | LocalStorageCore localStorageCore = LocalStorageCore(); 6 | 7 | Future existJwtToken() async { 8 | return await localStorageCore.exist(JwtTokenKeys.accessTokenKey); 9 | } 10 | 11 | Future existRefreshToken() async { 12 | return await localStorageCore.exist(JwtTokenKeys.refreshTokenKey); 13 | } 14 | 15 | Future saveAccessToken(String token) async { 16 | await localStorageCore.save(JwtTokenKeys.accessTokenKey, token); 17 | } 18 | 19 | Future saveRefreshToken(String token) async { 20 | await localStorageCore.save(JwtTokenKeys.refreshTokenKey, token); 21 | } 22 | 23 | Future getAccessToken() async { 24 | return await localStorageCore.read(JwtTokenKeys.accessTokenKey); 25 | } 26 | 27 | Future getRefreshToken() async { 28 | return await localStorageCore.read(JwtTokenKeys.refreshTokenKey); 29 | } 30 | 31 | Future clearJwtTokens() async { 32 | await localStorageCore.remove(JwtTokenKeys.accessTokenKey); 33 | await localStorageCore.remove(JwtTokenKeys.refreshTokenKey); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/pages/error/no_internet_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; 3 | import 'package:starterapp/routes/routes_constants.dart'; 4 | 5 | class NoInternetPage extends StatelessWidget { 6 | const NoInternetPage({super.key}); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Scaffold( 11 | body: Center( 12 | child: Column( 13 | mainAxisAlignment: MainAxisAlignment.center, 14 | children: [ 15 | Text( 16 | AppLocalizations.of(context)!.error_noInternet, 17 | style: const TextStyle( 18 | fontSize: 20, 19 | color: Colors.red, 20 | ), 21 | textAlign: TextAlign.center, 22 | ), 23 | const SizedBox( 24 | height: 20, 25 | ), 26 | const Icon( 27 | Icons.error, 28 | color: Colors.red, 29 | size: 40, 30 | ), 31 | const SizedBox( 32 | height: 20, 33 | ), 34 | ElevatedButton( 35 | child: Text( 36 | AppLocalizations.of(context)!.retry, 37 | ), 38 | onPressed: () { 39 | Navigator.of(context) 40 | .popAndPushNamed(RoutesConstants.splashScreenRoute); 41 | }, 42 | ), 43 | ], 44 | ), 45 | ), 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '11.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | target 'RunnerTests' do 36 | inherit! :search_paths 37 | end 38 | end 39 | 40 | post_install do |installer| 41 | installer.pods_project.targets.each do |target| 42 | flutter_additional_ios_build_settings(target) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /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 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Starterapp 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | starterapp 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | CADisableMinimumFrameDurationOnPhone 47 | 48 | UIApplicationSupportsIndirectInputEvents 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 14 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /lib/helper/auth/jwt_token_helper.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart'; 2 | import 'package:starterapp/constants/repository_constants/api_constants/auth/api_token_constants.dart'; 3 | import 'package:starterapp/repository/local_storage/auth/jwt_local_storage.dart'; 4 | 5 | class JwtTokenHelper { 6 | JwtLocalStorage jwtLocalStorage = JwtLocalStorage(); 7 | 8 | Future existJwtToken() => jwtLocalStorage.existJwtToken(); 9 | 10 | Future existRefreshToken() => jwtLocalStorage.existRefreshToken(); 11 | 12 | Future saveNewJwtTokens(String accessToken, String refreshToken) async { 13 | await jwtLocalStorage.saveAccessToken(accessToken); 14 | await jwtLocalStorage.saveRefreshToken(refreshToken); 15 | } 16 | 17 | Future getAccessToken() => jwtLocalStorage.getAccessToken(); 18 | 19 | Future getRefreshToken() => jwtLocalStorage.getRefreshToken(); 20 | 21 | Future isValidAccessToken() async { 22 | if (!await existJwtToken()) { 23 | return false; 24 | } 25 | try { 26 | String token = await getAccessToken(); 27 | _verifyToken(token); 28 | } on JWTExpiredException { 29 | await clearJwtTokens(); 30 | return false; 31 | } on JWTException { 32 | await clearJwtTokens(); 33 | return false; 34 | } 35 | return true; 36 | } 37 | 38 | Future isValidRefreshToken() async { 39 | if (!await existRefreshToken()) { 40 | return false; 41 | } 42 | try { 43 | String token = await getRefreshToken(); 44 | _verifyToken(token); 45 | } on JWTExpiredException { 46 | return false; 47 | } on JWTException { 48 | return false; 49 | } 50 | return true; 51 | } 52 | 53 | _verifyToken(String token) => 54 | JWT.verify(token, SecretKey(JwtTokenConstants.jwtSecretPhrase)); 55 | 56 | Future clearJwtTokens() => jwtLocalStorage.clearJwtTokens(); 57 | } 58 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | namespace "com.example.starterapp" 30 | compileSdkVersion flutter.compileSdkVersion 31 | ndkVersion flutter.ndkVersion 32 | 33 | compileOptions { 34 | sourceCompatibility JavaVersion.VERSION_1_8 35 | targetCompatibility JavaVersion.VERSION_1_8 36 | } 37 | 38 | kotlinOptions { 39 | jvmTarget = '1.8' 40 | } 41 | 42 | sourceSets { 43 | main.java.srcDirs += 'src/main/kotlin' 44 | } 45 | 46 | defaultConfig { 47 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 48 | applicationId "com.example.starterapp" 49 | // You can update the following values to match your application needs. 50 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 51 | minSdkVersion flutter.minSdkVersion 52 | targetSdkVersion flutter.targetSdkVersion 53 | versionCode flutterVersionCode.toInteger() 54 | versionName flutterVersionName 55 | } 56 | 57 | buildTypes { 58 | release { 59 | // TODO: Add your own signing config for the release build. 60 | // Signing with the debug keys for now, so `flutter run --release` works. 61 | signingConfig signingConfigs.debug 62 | } 63 | } 64 | } 65 | 66 | flutter { 67 | source '../..' 68 | } 69 | 70 | dependencies { 71 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 72 | } 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Flutter CI](https://github.com/EliaTolin/flutter-template-starter-app/actions/workflows/flutter_ci.yml/badge.svg)](https://github.com/EliaTolin/flutter-template-starter-app/actions/workflows/flutter_ci.yml) 2 | [![Code Quality](https://github.com/EliaTolin/flutter-template-starter-app/actions/workflows/code_quality_flutter.yml/badge.svg)](https://github.com/EliaTolin/flutter-template-starter-app/actions/workflows/code_quality_flutter.yml) 3 | 4 | ![Flutter Starter App](https://github.com/EliaTolin/flutter-template-starter-app/assets/60351315/df279758-867d-4265-a3fc-d637e5305819) 5 | 6 | ## Description 7 | 8 | This repository serves as a template Layer first for a Flutter app, providing a modular structure and integrating various packages and functionalities. The project aims to offer a solid foundation for building robust Flutter applications with the following features: 9 | 10 | - **Dio**: A powerful package for handling network requests, allowing seamless communication with APIs. 11 | - **l10n**: Enables multi-language support, making it easy to localize your app for different languages. 12 | - **Provider**: A state management solution that simplifies the management and sharing of application state. 13 | - **Shared Preferences**: Provides a simple way to persistently store key-value pairs, allowing for data persistence across app sessions. 14 | - **JWT**: Offers support for JSON Web Tokens, enabling secure authentication and authorization mechanisms. 15 | - **Various Helper Classes**: Includes a collection of utility classes that assist with common tasks, making development more efficient. 16 | - **Language Service**: A service that allows users to dynamically switch the language within the app, enhancing the user experience. 17 | - **Named Routing**: Implements a navigation system using named routes, making it easier to navigate between screens and manage app flow. 18 | 19 | ## Modularity 20 | 21 | The project has been designed with a strong focus on modularity. This modular architecture enables easy customization, extension, and maintenance of the app. Each package and functionality is independent, allowing developers to add, remove, or modify components as per their project requirements. 22 | 23 | ## Usage 24 | 25 | To use this project template, follow these steps: 26 | 27 | 1. Clone the repository to your local machine. 28 | 2. Open the project in your preferred Flutter development environment. 29 | 3. Customize the app's functionality, UI, and features according to your project requirements. 30 | 4. Build and run the app on your preferred platform or device. 31 | 32 | ## Contributions 33 | 34 | Contributions to this project are welcome. If you find any issues or have suggestions for improvements, please open an issue or submit a pull request. 35 | 36 | ## License 37 | 38 | This project is licensed under the [MIT License](https://chat.openai.com/link-to-license). Please refer to the LICENSE file for more information. 39 | 40 | ## Acknowledgements 41 | 42 | We would like to acknowledge the creators and contributors of the packages and functionalities integrated into this project template. Their work has made building Flutter apps more efficient and enjoyable. 43 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .classpath 21 | .project 22 | .settings/ 23 | .vscode/* 24 | 25 | # Flutter repo-specific 26 | /bin/cache/ 27 | /bin/internal/bootstrap.bat 28 | /bin/internal/bootstrap.sh 29 | /bin/mingit/ 30 | /dev/benchmarks/mega_gallery/ 31 | /dev/bots/.recipe_deps 32 | /dev/bots/android_tools/ 33 | /dev/devicelab/ABresults*.json 34 | /dev/docs/doc/ 35 | /dev/docs/flutter.docs.zip 36 | /dev/docs/lib/ 37 | /dev/docs/pubspec.yaml 38 | /dev/integration_tests/**/xcuserdata 39 | /dev/integration_tests/**/Pods 40 | /packages/flutter/coverage/ 41 | version 42 | analysis_benchmark.json 43 | 44 | # packages file containing multi-root paths 45 | .packages.generated 46 | 47 | # Flutter/Dart/Pub related 48 | **/doc/api/ 49 | .dart_tool/ 50 | .flutter-plugins 51 | .flutter-plugins-dependencies 52 | **/generated_plugin_registrant.dart 53 | .packages 54 | .pub-preload-cache/ 55 | .pub/ 56 | build/ 57 | flutter_*.png 58 | linked_*.ds 59 | unlinked.ds 60 | unlinked_spec.ds 61 | 62 | # Android related 63 | **/android/**/gradle-wrapper.jar 64 | .gradle/ 65 | **/android/captures/ 66 | **/android/gradlew 67 | **/android/gradlew.bat 68 | **/android/local.properties 69 | **/android/**/GeneratedPluginRegistrant.java 70 | **/android/key.properties 71 | *.jks 72 | 73 | # iOS/XCode related 74 | **/ios/**/*.mode1v3 75 | **/ios/**/*.mode2v3 76 | **/ios/**/*.moved-aside 77 | **/ios/**/*.pbxuser 78 | **/ios/**/*.perspectivev3 79 | **/ios/**/*sync/ 80 | **/ios/**/.sconsign.dblite 81 | **/ios/**/.tags* 82 | **/ios/**/.vagrant/ 83 | **/ios/**/DerivedData/ 84 | **/ios/**/Icon? 85 | **/ios/**/Pods/ 86 | **/ios/**/.symlinks/ 87 | **/ios/**/profile 88 | **/ios/**/xcuserdata 89 | **/ios/.generated/ 90 | **/ios/Flutter/.last_build_id 91 | **/ios/Flutter/App.framework 92 | **/ios/Flutter/Flutter.framework 93 | **/ios/Flutter/Flutter.podspec 94 | **/ios/Flutter/Generated.xcconfig 95 | **/ios/Flutter/ephemeral 96 | **/ios/Flutter/app.flx 97 | **/ios/Flutter/app.zip 98 | **/ios/Flutter/flutter_assets/ 99 | **/ios/Flutter/flutter_export_environment.sh 100 | **/ios/ServiceDefinitions.json 101 | **/ios/Runner/GeneratedPluginRegistrant.* 102 | 103 | # macOS 104 | **/Flutter/ephemeral/ 105 | **/Pods/ 106 | **/macos/Flutter/GeneratedPluginRegistrant.swift 107 | **/macos/Flutter/ephemeral 108 | **/xcuserdata/ 109 | 110 | # Windows 111 | **/windows/flutter/generated_plugin_registrant.cc 112 | **/windows/flutter/generated_plugin_registrant.h 113 | **/windows/flutter/generated_plugins.cmake 114 | 115 | # Linux 116 | **/linux/flutter/generated_plugin_registrant.cc 117 | **/linux/flutter/generated_plugin_registrant.h 118 | **/linux/flutter/generated_plugins.cmake 119 | 120 | # Coverage 121 | coverage/ 122 | 123 | # Symbols 124 | app.*.symbols 125 | 126 | # Exceptions to above rules. 127 | !**/ios/**/default.mode1v3 128 | !**/ios/**/default.mode2v3 129 | !**/ios/**/default.pbxuser 130 | !**/ios/**/default.perspectivev3 131 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 132 | !/dev/ci/**/Gemfile.lock 133 | !.vscode/settings.json -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/pages/splash_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:internet_connection_checker/internet_connection_checker.dart'; 4 | import 'package:provider/provider.dart'; 5 | import 'package:starterapp/constants/style/style_constants.dart'; 6 | import 'package:starterapp/routes/routes_constants.dart'; 7 | import 'package:starterapp/services/locale_service_provider.dart'; 8 | 9 | class SplashPage extends StatefulWidget { 10 | const SplashPage({super.key}); 11 | 12 | @override 13 | State createState() => _SplashPageState(); 14 | } 15 | 16 | class _SplashPageState extends State { 17 | Future loadCall() async { 18 | // Wait delay 19 | if (context.mounted) { 20 | await context 21 | .read() 22 | .initLocale(Localizations.localeOf(context).languageCode); 23 | } 24 | await Future.delayed(const Duration(seconds: 3), () {}); 25 | redirectPage(); 26 | } 27 | 28 | Future redirectPage() async { 29 | if (!await InternetConnectionChecker().hasConnection) { 30 | if (context.mounted) { 31 | Navigator.of(context).popAndPushNamed(RoutesConstants.noInternetRoute); 32 | } 33 | } else { 34 | if (context.mounted) { 35 | Navigator.of(context).popAndPushNamed(RoutesConstants.landingRoute); 36 | } 37 | } 38 | } 39 | 40 | @override 41 | void initState() { 42 | super.initState(); 43 | WidgetsBinding.instance.addPostFrameCallback((_) => loadCall()); 44 | } 45 | 46 | @override 47 | Widget build(BuildContext context) { 48 | Size size = MediaQuery.of(context).size; 49 | 50 | return Scaffold( 51 | appBar: AppBar( 52 | systemOverlayStyle: const SystemUiOverlayStyle( 53 | statusBarColor: Colors.transparent, 54 | ), 55 | backgroundColor: Colors.transparent, 56 | elevation: 0, 57 | toolbarHeight: 0, 58 | ), 59 | backgroundColor: Colors.white, 60 | body: Stack( 61 | alignment: Alignment.center, 62 | children: [ 63 | Positioned( 64 | top: 200, 65 | left: 0, 66 | child: CustomPaint( 67 | painter: Circle(size.width - size.width / 5, 0, size.width, 68 | StyleConstants.colorOfApp), 69 | ), 70 | ), 71 | Positioned( 72 | top: 0, 73 | right: 0, 74 | child: CustomPaint( 75 | painter: Circle(0, 0, size.width - 100, Colors.white), 76 | ), 77 | ), 78 | const Padding( 79 | padding: EdgeInsets.all(8.0), 80 | child: Column( 81 | mainAxisAlignment: MainAxisAlignment.center, 82 | mainAxisSize: MainAxisSize.max, 83 | children: [ 84 | FittedBox( 85 | child: Text( 86 | "StarterApp", 87 | style: TextStyle( 88 | fontSize: 50, 89 | color: Colors.white, 90 | ), 91 | textAlign: TextAlign.center, 92 | maxLines: 1, 93 | ), 94 | ), 95 | Text( 96 | "Your splashscreen!", 97 | style: TextStyle( 98 | color: Colors.white, 99 | ), 100 | textAlign: TextAlign.center, 101 | ), 102 | ], 103 | ), 104 | ), 105 | ], 106 | ), 107 | ); 108 | } 109 | } 110 | 111 | class Circle extends CustomPainter { 112 | final double offsetX; 113 | final double offsetY; 114 | final double radius; 115 | final Color color; 116 | Circle(this.offsetX, this.offsetY, this.radius, this.color); 117 | @override 118 | void paint(Canvas canvas, Size size) { 119 | var paint1 = Paint() 120 | ..color = color 121 | ..style = PaintingStyle.fill; 122 | //a circle 123 | canvas.drawCircle(Offset(offsetX, offsetY), radius, paint1); 124 | } 125 | 126 | @override 127 | bool shouldRepaint(CustomPainter oldDelegate) => true; 128 | } 129 | -------------------------------------------------------------------------------- /lib/repository/api/base/api_core.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | import 'package:dio/dio.dart'; 3 | import 'package:starterapp/constants/repository_constants/api_constants/routes/api_route_constants.dart'; 4 | import 'package:starterapp/exceptions/api/api_exceptions.dart'; 5 | import 'package:starterapp/exceptions/auth/auth_exception.dart'; 6 | import 'package:starterapp/helper/api/api_route_helper.dart'; 7 | import 'package:starterapp/helper/auth/jwt_token_helper.dart'; 8 | 9 | class ApiBaseCore { 10 | late Dio baseAPI; 11 | 12 | final BaseOptions opts = BaseOptions( 13 | baseUrl: ApiRouteHelper.getBaseUrl(), 14 | responseType: ResponseType.json, 15 | connectTimeout: const Duration(seconds: 10), 16 | receiveTimeout: const Duration(seconds: 10), 17 | ); 18 | 19 | Dio createDio() { 20 | return Dio(opts); 21 | } 22 | 23 | ApiBaseCore() { 24 | Dio dio = createDio(); 25 | baseAPI = addInterceptors(dio); 26 | } 27 | 28 | Dio addInterceptors(Dio dio) { 29 | return dio 30 | ..interceptors.add( 31 | InterceptorsWrapper( 32 | onRequest: 33 | (RequestOptions options, RequestInterceptorHandler handler) { 34 | requestInterceptor(options, handler); 35 | }, 36 | onError: (DioException e, ErrorInterceptorHandler handler) async { 37 | log("ERROR: $e"); 38 | handler.next(e); 39 | }, 40 | onResponse: (Response response, ResponseInterceptorHandler handler) { 41 | handler.next(response); 42 | }, 43 | ), 44 | ); 45 | } 46 | 47 | Future requestInterceptor( 48 | RequestOptions options, RequestInterceptorHandler handler) async { 49 | String token = ""; 50 | final jwtTokenHelper = JwtTokenHelper(); 51 | 52 | // If not exist, the user is not logged in the app, i not need add the token 53 | if (await jwtTokenHelper.existJwtToken()) { 54 | if (!await jwtTokenHelper.isValidAccessToken()) { 55 | if (!await jwtTokenHelper.isValidRefreshToken()) { 56 | throw const RefreshTokenExpiredException(); 57 | } 58 | Dio dio = Dio(opts); 59 | Response response = await dio.post( 60 | ApiRouteConstants.refreshTokenPath, 61 | data: { 62 | "refresh": await jwtTokenHelper.getRefreshToken(), 63 | }, 64 | ).onError( 65 | (DioException error, stackTrace) => handleError(error), 66 | ); 67 | await jwtTokenHelper.saveNewJwtTokens( 68 | response.data["access"], 69 | response.data["refresh"], 70 | ); 71 | log("New access token: ${response.data["access"]}"); 72 | log("New refresh token: ${response.data["refresh"]}"); 73 | token = response.data["access"]; 74 | } 75 | token = await jwtTokenHelper.getAccessToken(); 76 | options.headers.addAll({"Authorization": "Bearer $token"}); 77 | } 78 | log("____________________"); 79 | log("URL: ${options.baseUrl}${options.path}"); 80 | log("METHOD: ${options.method}"); 81 | log("Headers: ${options.headers}"); 82 | log("Data: ${options.data}"); 83 | log("QueryParams: ${options.queryParameters}"); 84 | log("____________________"); 85 | handler.next(options); 86 | } 87 | 88 | Future getHTTP(String path, 89 | {Map? queryParameters}) async { 90 | try { 91 | Response response = 92 | await baseAPI.get(path, queryParameters: queryParameters); 93 | return response; 94 | } on DioException catch (e) { 95 | handleError(e); 96 | } 97 | return null; 98 | } 99 | 100 | Future postHTTP(String path, dynamic data, 101 | {Map? queryParameters}) async { 102 | try { 103 | Response response = await baseAPI.post(path, 104 | data: data, queryParameters: queryParameters); 105 | return response; 106 | } on DioException catch (e) { 107 | handleError(e); 108 | } 109 | return null; 110 | } 111 | 112 | Future putHTTP(String path, dynamic data, 113 | {Map? queryParameters}) async { 114 | try { 115 | Response response = 116 | await baseAPI.put(path, data: data, queryParameters: queryParameters); 117 | return response; 118 | } on DioException catch (e) { 119 | handleError(e); 120 | } 121 | return null; 122 | } 123 | 124 | Future deleteHTTP(String path, 125 | {Map? queryParameters}) async { 126 | try { 127 | Response response = 128 | await baseAPI.delete(path, queryParameters: queryParameters); 129 | return response; 130 | } on DioException catch (e) { 131 | handleError(e); 132 | } 133 | return null; 134 | } 135 | 136 | handleError(DioException error) { 137 | switch (error.type) { 138 | case DioExceptionType.connectionTimeout: 139 | throw const NoInternetConnectionException(); 140 | case DioExceptionType.sendTimeout: 141 | throw const NoInternetConnectionException(); 142 | case DioExceptionType.receiveTimeout: 143 | throw const NoInternetConnectionException(); 144 | case DioExceptionType.badResponse: 145 | if (error.response == null) { 146 | throw BadRequestException(""); 147 | } 148 | switch (error.response?.statusCode) { 149 | case 401: 150 | throw const UnauthorizedException(); 151 | case 400: 152 | throw BadRequestException(""); 153 | case 404: 154 | throw const NotFoundEndPointException(); 155 | case 500: 156 | throw InternalServerErrorException(); 157 | } 158 | break; 159 | case DioExceptionType.cancel: 160 | break; 161 | default: 162 | throw BadRequestException("Unknown error"); 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 452B099C7EE0535DFCA0897E /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F16BF82A3A13F67CD96FB937 /* Pods_RunnerTests.framework */; }; 14 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 15 | 8F3F6D0EB64A57F3B706ADD5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D7BB5BB4379A9D8CC68DCD1 /* Pods_Runner.framework */; }; 16 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 17 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 18 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 97C146E61CF9000F007C117D /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = 97C146ED1CF9000F007C117D; 27 | remoteInfo = Runner; 28 | }; 29 | /* End PBXContainerItemProxy section */ 30 | 31 | /* Begin PBXCopyFilesBuildPhase section */ 32 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 33 | isa = PBXCopyFilesBuildPhase; 34 | buildActionMask = 2147483647; 35 | dstPath = ""; 36 | dstSubfolderSpec = 10; 37 | files = ( 38 | ); 39 | name = "Embed Frameworks"; 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXCopyFilesBuildPhase section */ 43 | 44 | /* Begin PBXFileReference section */ 45 | 0ADC41F6B57E9D27C7027872 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; 46 | 126ADC3F251A5AEE80A9B39F /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 47 | 1380D49C8CF11392C2DC4FFE /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 48 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 49 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 50 | 1C9063B17755F75EB663BA64 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 51 | 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 52 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 54 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 55 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 56 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 57 | 8D7BB5BB4379A9D8CC68DCD1 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 59 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 60 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 62 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 63 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 64 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 65 | A9042EA9257650CCC79814BB /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 66 | D531C994685255E5068EA8C6 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 67 | F16BF82A3A13F67CD96FB937 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | /* End PBXFileReference section */ 69 | 70 | /* Begin PBXFrameworksBuildPhase section */ 71 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | 8F3F6D0EB64A57F3B706ADD5 /* Pods_Runner.framework in Frameworks */, 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | DE272899AAC3F89DE403A521 /* Frameworks */ = { 80 | isa = PBXFrameworksBuildPhase; 81 | buildActionMask = 2147483647; 82 | files = ( 83 | 452B099C7EE0535DFCA0897E /* Pods_RunnerTests.framework in Frameworks */, 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | /* End PBXFrameworksBuildPhase section */ 88 | 89 | /* Begin PBXGroup section */ 90 | 2C901272B95D166C1C348251 /* Frameworks */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 8D7BB5BB4379A9D8CC68DCD1 /* Pods_Runner.framework */, 94 | F16BF82A3A13F67CD96FB937 /* Pods_RunnerTests.framework */, 95 | ); 96 | name = Frameworks; 97 | sourceTree = ""; 98 | }; 99 | 331C8082294A63A400263BE5 /* RunnerTests */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 331C807B294A618700263BE5 /* RunnerTests.swift */, 103 | ); 104 | path = RunnerTests; 105 | sourceTree = ""; 106 | }; 107 | 9740EEB11CF90186004384FC /* Flutter */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 111 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 112 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 113 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 114 | ); 115 | name = Flutter; 116 | sourceTree = ""; 117 | }; 118 | 97C146E51CF9000F007C117D = { 119 | isa = PBXGroup; 120 | children = ( 121 | 9740EEB11CF90186004384FC /* Flutter */, 122 | 97C146F01CF9000F007C117D /* Runner */, 123 | 97C146EF1CF9000F007C117D /* Products */, 124 | 331C8082294A63A400263BE5 /* RunnerTests */, 125 | EA4813D0780F1F56588A0826 /* Pods */, 126 | 2C901272B95D166C1C348251 /* Frameworks */, 127 | ); 128 | sourceTree = ""; 129 | }; 130 | 97C146EF1CF9000F007C117D /* Products */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 97C146EE1CF9000F007C117D /* Runner.app */, 134 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */, 135 | ); 136 | name = Products; 137 | sourceTree = ""; 138 | }; 139 | 97C146F01CF9000F007C117D /* Runner */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 143 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 144 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 145 | 97C147021CF9000F007C117D /* Info.plist */, 146 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 147 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 148 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 149 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 150 | ); 151 | path = Runner; 152 | sourceTree = ""; 153 | }; 154 | EA4813D0780F1F56588A0826 /* Pods */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | D531C994685255E5068EA8C6 /* Pods-Runner.debug.xcconfig */, 158 | 1380D49C8CF11392C2DC4FFE /* Pods-Runner.release.xcconfig */, 159 | 1C9063B17755F75EB663BA64 /* Pods-Runner.profile.xcconfig */, 160 | 0ADC41F6B57E9D27C7027872 /* Pods-RunnerTests.debug.xcconfig */, 161 | A9042EA9257650CCC79814BB /* Pods-RunnerTests.release.xcconfig */, 162 | 126ADC3F251A5AEE80A9B39F /* Pods-RunnerTests.profile.xcconfig */, 163 | ); 164 | name = Pods; 165 | path = Pods; 166 | sourceTree = ""; 167 | }; 168 | /* End PBXGroup section */ 169 | 170 | /* Begin PBXNativeTarget section */ 171 | 331C8080294A63A400263BE5 /* RunnerTests */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; 174 | buildPhases = ( 175 | 532FE390281E3B7F7EDF8D96 /* [CP] Check Pods Manifest.lock */, 176 | 331C807D294A63A400263BE5 /* Sources */, 177 | 331C807F294A63A400263BE5 /* Resources */, 178 | DE272899AAC3F89DE403A521 /* Frameworks */, 179 | ); 180 | buildRules = ( 181 | ); 182 | dependencies = ( 183 | 331C8086294A63A400263BE5 /* PBXTargetDependency */, 184 | ); 185 | name = RunnerTests; 186 | productName = RunnerTests; 187 | productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; 188 | productType = "com.apple.product-type.bundle.unit-test"; 189 | }; 190 | 97C146ED1CF9000F007C117D /* Runner */ = { 191 | isa = PBXNativeTarget; 192 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 193 | buildPhases = ( 194 | 8D7494FEAF3F3CF74C10E796 /* [CP] Check Pods Manifest.lock */, 195 | 9740EEB61CF901F6004384FC /* Run Script */, 196 | 97C146EA1CF9000F007C117D /* Sources */, 197 | 97C146EB1CF9000F007C117D /* Frameworks */, 198 | 97C146EC1CF9000F007C117D /* Resources */, 199 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 200 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 201 | 2393EB1265B3F8CF994C42BF /* [CP] Embed Pods Frameworks */, 202 | ); 203 | buildRules = ( 204 | ); 205 | dependencies = ( 206 | ); 207 | name = Runner; 208 | productName = Runner; 209 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 210 | productType = "com.apple.product-type.application"; 211 | }; 212 | /* End PBXNativeTarget section */ 213 | 214 | /* Begin PBXProject section */ 215 | 97C146E61CF9000F007C117D /* Project object */ = { 216 | isa = PBXProject; 217 | attributes = { 218 | LastUpgradeCheck = 1300; 219 | ORGANIZATIONNAME = ""; 220 | TargetAttributes = { 221 | 331C8080294A63A400263BE5 = { 222 | CreatedOnToolsVersion = 14.0; 223 | TestTargetID = 97C146ED1CF9000F007C117D; 224 | }; 225 | 97C146ED1CF9000F007C117D = { 226 | CreatedOnToolsVersion = 7.3.1; 227 | LastSwiftMigration = 1100; 228 | }; 229 | }; 230 | }; 231 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 232 | compatibilityVersion = "Xcode 9.3"; 233 | developmentRegion = en; 234 | hasScannedForEncodings = 0; 235 | knownRegions = ( 236 | en, 237 | Base, 238 | ); 239 | mainGroup = 97C146E51CF9000F007C117D; 240 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 241 | projectDirPath = ""; 242 | projectRoot = ""; 243 | targets = ( 244 | 97C146ED1CF9000F007C117D /* Runner */, 245 | 331C8080294A63A400263BE5 /* RunnerTests */, 246 | ); 247 | }; 248 | /* End PBXProject section */ 249 | 250 | /* Begin PBXResourcesBuildPhase section */ 251 | 331C807F294A63A400263BE5 /* Resources */ = { 252 | isa = PBXResourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | 97C146EC1CF9000F007C117D /* Resources */ = { 259 | isa = PBXResourcesBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 263 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 264 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 265 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 266 | ); 267 | runOnlyForDeploymentPostprocessing = 0; 268 | }; 269 | /* End PBXResourcesBuildPhase section */ 270 | 271 | /* Begin PBXShellScriptBuildPhase section */ 272 | 2393EB1265B3F8CF994C42BF /* [CP] Embed Pods Frameworks */ = { 273 | isa = PBXShellScriptBuildPhase; 274 | buildActionMask = 2147483647; 275 | files = ( 276 | ); 277 | inputFileListPaths = ( 278 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", 279 | ); 280 | name = "[CP] Embed Pods Frameworks"; 281 | outputFileListPaths = ( 282 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", 283 | ); 284 | runOnlyForDeploymentPostprocessing = 0; 285 | shellPath = /bin/sh; 286 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 287 | showEnvVarsInLog = 0; 288 | }; 289 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 290 | isa = PBXShellScriptBuildPhase; 291 | alwaysOutOfDate = 1; 292 | buildActionMask = 2147483647; 293 | files = ( 294 | ); 295 | inputPaths = ( 296 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", 297 | ); 298 | name = "Thin Binary"; 299 | outputPaths = ( 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | shellPath = /bin/sh; 303 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 304 | }; 305 | 532FE390281E3B7F7EDF8D96 /* [CP] Check Pods Manifest.lock */ = { 306 | isa = PBXShellScriptBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | ); 310 | inputFileListPaths = ( 311 | ); 312 | inputPaths = ( 313 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 314 | "${PODS_ROOT}/Manifest.lock", 315 | ); 316 | name = "[CP] Check Pods Manifest.lock"; 317 | outputFileListPaths = ( 318 | ); 319 | outputPaths = ( 320 | "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", 321 | ); 322 | runOnlyForDeploymentPostprocessing = 0; 323 | shellPath = /bin/sh; 324 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 325 | showEnvVarsInLog = 0; 326 | }; 327 | 8D7494FEAF3F3CF74C10E796 /* [CP] Check Pods Manifest.lock */ = { 328 | isa = PBXShellScriptBuildPhase; 329 | buildActionMask = 2147483647; 330 | files = ( 331 | ); 332 | inputFileListPaths = ( 333 | ); 334 | inputPaths = ( 335 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 336 | "${PODS_ROOT}/Manifest.lock", 337 | ); 338 | name = "[CP] Check Pods Manifest.lock"; 339 | outputFileListPaths = ( 340 | ); 341 | outputPaths = ( 342 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 343 | ); 344 | runOnlyForDeploymentPostprocessing = 0; 345 | shellPath = /bin/sh; 346 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 347 | showEnvVarsInLog = 0; 348 | }; 349 | 9740EEB61CF901F6004384FC /* Run Script */ = { 350 | isa = PBXShellScriptBuildPhase; 351 | alwaysOutOfDate = 1; 352 | buildActionMask = 2147483647; 353 | files = ( 354 | ); 355 | inputPaths = ( 356 | ); 357 | name = "Run Script"; 358 | outputPaths = ( 359 | ); 360 | runOnlyForDeploymentPostprocessing = 0; 361 | shellPath = /bin/sh; 362 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 363 | }; 364 | /* End PBXShellScriptBuildPhase section */ 365 | 366 | /* Begin PBXSourcesBuildPhase section */ 367 | 331C807D294A63A400263BE5 /* Sources */ = { 368 | isa = PBXSourcesBuildPhase; 369 | buildActionMask = 2147483647; 370 | files = ( 371 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, 372 | ); 373 | runOnlyForDeploymentPostprocessing = 0; 374 | }; 375 | 97C146EA1CF9000F007C117D /* Sources */ = { 376 | isa = PBXSourcesBuildPhase; 377 | buildActionMask = 2147483647; 378 | files = ( 379 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 380 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 381 | ); 382 | runOnlyForDeploymentPostprocessing = 0; 383 | }; 384 | /* End PBXSourcesBuildPhase section */ 385 | 386 | /* Begin PBXTargetDependency section */ 387 | 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { 388 | isa = PBXTargetDependency; 389 | target = 97C146ED1CF9000F007C117D /* Runner */; 390 | targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; 391 | }; 392 | /* End PBXTargetDependency section */ 393 | 394 | /* Begin PBXVariantGroup section */ 395 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 396 | isa = PBXVariantGroup; 397 | children = ( 398 | 97C146FB1CF9000F007C117D /* Base */, 399 | ); 400 | name = Main.storyboard; 401 | sourceTree = ""; 402 | }; 403 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 404 | isa = PBXVariantGroup; 405 | children = ( 406 | 97C147001CF9000F007C117D /* Base */, 407 | ); 408 | name = LaunchScreen.storyboard; 409 | sourceTree = ""; 410 | }; 411 | /* End PBXVariantGroup section */ 412 | 413 | /* Begin XCBuildConfiguration section */ 414 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 415 | isa = XCBuildConfiguration; 416 | buildSettings = { 417 | ALWAYS_SEARCH_USER_PATHS = NO; 418 | CLANG_ANALYZER_NONNULL = YES; 419 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 420 | CLANG_CXX_LIBRARY = "libc++"; 421 | CLANG_ENABLE_MODULES = YES; 422 | CLANG_ENABLE_OBJC_ARC = YES; 423 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 424 | CLANG_WARN_BOOL_CONVERSION = YES; 425 | CLANG_WARN_COMMA = YES; 426 | CLANG_WARN_CONSTANT_CONVERSION = YES; 427 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 428 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 429 | CLANG_WARN_EMPTY_BODY = YES; 430 | CLANG_WARN_ENUM_CONVERSION = YES; 431 | CLANG_WARN_INFINITE_RECURSION = YES; 432 | CLANG_WARN_INT_CONVERSION = YES; 433 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 434 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 435 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 436 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 437 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 438 | CLANG_WARN_STRICT_PROTOTYPES = YES; 439 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 440 | CLANG_WARN_UNREACHABLE_CODE = YES; 441 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 442 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 443 | COPY_PHASE_STRIP = NO; 444 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 445 | ENABLE_NS_ASSERTIONS = NO; 446 | ENABLE_STRICT_OBJC_MSGSEND = YES; 447 | GCC_C_LANGUAGE_STANDARD = gnu99; 448 | GCC_NO_COMMON_BLOCKS = YES; 449 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 450 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 451 | GCC_WARN_UNDECLARED_SELECTOR = YES; 452 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 453 | GCC_WARN_UNUSED_FUNCTION = YES; 454 | GCC_WARN_UNUSED_VARIABLE = YES; 455 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 456 | MTL_ENABLE_DEBUG_INFO = NO; 457 | SDKROOT = iphoneos; 458 | SUPPORTED_PLATFORMS = iphoneos; 459 | TARGETED_DEVICE_FAMILY = "1,2"; 460 | VALIDATE_PRODUCT = YES; 461 | }; 462 | name = Profile; 463 | }; 464 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 465 | isa = XCBuildConfiguration; 466 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 467 | buildSettings = { 468 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 469 | CLANG_ENABLE_MODULES = YES; 470 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 471 | DEVELOPMENT_TEAM = X6QYJ2NQ5M; 472 | ENABLE_BITCODE = NO; 473 | INFOPLIST_FILE = Runner/Info.plist; 474 | LD_RUNPATH_SEARCH_PATHS = ( 475 | "$(inherited)", 476 | "@executable_path/Frameworks", 477 | ); 478 | PRODUCT_BUNDLE_IDENTIFIER = com.example.starterapp; 479 | PRODUCT_NAME = "$(TARGET_NAME)"; 480 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 481 | SWIFT_VERSION = 5.0; 482 | VERSIONING_SYSTEM = "apple-generic"; 483 | }; 484 | name = Profile; 485 | }; 486 | 331C8088294A63A400263BE5 /* Debug */ = { 487 | isa = XCBuildConfiguration; 488 | baseConfigurationReference = 0ADC41F6B57E9D27C7027872 /* Pods-RunnerTests.debug.xcconfig */; 489 | buildSettings = { 490 | BUNDLE_LOADER = "$(TEST_HOST)"; 491 | CODE_SIGN_STYLE = Automatic; 492 | CURRENT_PROJECT_VERSION = 1; 493 | GENERATE_INFOPLIST_FILE = YES; 494 | MARKETING_VERSION = 1.0; 495 | PRODUCT_BUNDLE_IDENTIFIER = com.example.starterapp.RunnerTests; 496 | PRODUCT_NAME = "$(TARGET_NAME)"; 497 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 498 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 499 | SWIFT_VERSION = 5.0; 500 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 501 | }; 502 | name = Debug; 503 | }; 504 | 331C8089294A63A400263BE5 /* Release */ = { 505 | isa = XCBuildConfiguration; 506 | baseConfigurationReference = A9042EA9257650CCC79814BB /* Pods-RunnerTests.release.xcconfig */; 507 | buildSettings = { 508 | BUNDLE_LOADER = "$(TEST_HOST)"; 509 | CODE_SIGN_STYLE = Automatic; 510 | CURRENT_PROJECT_VERSION = 1; 511 | GENERATE_INFOPLIST_FILE = YES; 512 | MARKETING_VERSION = 1.0; 513 | PRODUCT_BUNDLE_IDENTIFIER = com.example.starterapp.RunnerTests; 514 | PRODUCT_NAME = "$(TARGET_NAME)"; 515 | SWIFT_VERSION = 5.0; 516 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 517 | }; 518 | name = Release; 519 | }; 520 | 331C808A294A63A400263BE5 /* Profile */ = { 521 | isa = XCBuildConfiguration; 522 | baseConfigurationReference = 126ADC3F251A5AEE80A9B39F /* Pods-RunnerTests.profile.xcconfig */; 523 | buildSettings = { 524 | BUNDLE_LOADER = "$(TEST_HOST)"; 525 | CODE_SIGN_STYLE = Automatic; 526 | CURRENT_PROJECT_VERSION = 1; 527 | GENERATE_INFOPLIST_FILE = YES; 528 | MARKETING_VERSION = 1.0; 529 | PRODUCT_BUNDLE_IDENTIFIER = com.example.starterapp.RunnerTests; 530 | PRODUCT_NAME = "$(TARGET_NAME)"; 531 | SWIFT_VERSION = 5.0; 532 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 533 | }; 534 | name = Profile; 535 | }; 536 | 97C147031CF9000F007C117D /* Debug */ = { 537 | isa = XCBuildConfiguration; 538 | buildSettings = { 539 | ALWAYS_SEARCH_USER_PATHS = NO; 540 | CLANG_ANALYZER_NONNULL = YES; 541 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 542 | CLANG_CXX_LIBRARY = "libc++"; 543 | CLANG_ENABLE_MODULES = YES; 544 | CLANG_ENABLE_OBJC_ARC = YES; 545 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 546 | CLANG_WARN_BOOL_CONVERSION = YES; 547 | CLANG_WARN_COMMA = YES; 548 | CLANG_WARN_CONSTANT_CONVERSION = YES; 549 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 550 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 551 | CLANG_WARN_EMPTY_BODY = YES; 552 | CLANG_WARN_ENUM_CONVERSION = YES; 553 | CLANG_WARN_INFINITE_RECURSION = YES; 554 | CLANG_WARN_INT_CONVERSION = YES; 555 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 556 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 557 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 558 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 559 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 560 | CLANG_WARN_STRICT_PROTOTYPES = YES; 561 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 562 | CLANG_WARN_UNREACHABLE_CODE = YES; 563 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 564 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 565 | COPY_PHASE_STRIP = NO; 566 | DEBUG_INFORMATION_FORMAT = dwarf; 567 | ENABLE_STRICT_OBJC_MSGSEND = YES; 568 | ENABLE_TESTABILITY = YES; 569 | GCC_C_LANGUAGE_STANDARD = gnu99; 570 | GCC_DYNAMIC_NO_PIC = NO; 571 | GCC_NO_COMMON_BLOCKS = YES; 572 | GCC_OPTIMIZATION_LEVEL = 0; 573 | GCC_PREPROCESSOR_DEFINITIONS = ( 574 | "DEBUG=1", 575 | "$(inherited)", 576 | ); 577 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 578 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 579 | GCC_WARN_UNDECLARED_SELECTOR = YES; 580 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 581 | GCC_WARN_UNUSED_FUNCTION = YES; 582 | GCC_WARN_UNUSED_VARIABLE = YES; 583 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 584 | MTL_ENABLE_DEBUG_INFO = YES; 585 | ONLY_ACTIVE_ARCH = YES; 586 | SDKROOT = iphoneos; 587 | TARGETED_DEVICE_FAMILY = "1,2"; 588 | }; 589 | name = Debug; 590 | }; 591 | 97C147041CF9000F007C117D /* Release */ = { 592 | isa = XCBuildConfiguration; 593 | buildSettings = { 594 | ALWAYS_SEARCH_USER_PATHS = NO; 595 | CLANG_ANALYZER_NONNULL = YES; 596 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 597 | CLANG_CXX_LIBRARY = "libc++"; 598 | CLANG_ENABLE_MODULES = YES; 599 | CLANG_ENABLE_OBJC_ARC = YES; 600 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 601 | CLANG_WARN_BOOL_CONVERSION = YES; 602 | CLANG_WARN_COMMA = YES; 603 | CLANG_WARN_CONSTANT_CONVERSION = YES; 604 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 605 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 606 | CLANG_WARN_EMPTY_BODY = YES; 607 | CLANG_WARN_ENUM_CONVERSION = YES; 608 | CLANG_WARN_INFINITE_RECURSION = YES; 609 | CLANG_WARN_INT_CONVERSION = YES; 610 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 611 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 612 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 613 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 614 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 615 | CLANG_WARN_STRICT_PROTOTYPES = YES; 616 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 617 | CLANG_WARN_UNREACHABLE_CODE = YES; 618 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 619 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 620 | COPY_PHASE_STRIP = NO; 621 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 622 | ENABLE_NS_ASSERTIONS = NO; 623 | ENABLE_STRICT_OBJC_MSGSEND = YES; 624 | GCC_C_LANGUAGE_STANDARD = gnu99; 625 | GCC_NO_COMMON_BLOCKS = YES; 626 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 627 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 628 | GCC_WARN_UNDECLARED_SELECTOR = YES; 629 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 630 | GCC_WARN_UNUSED_FUNCTION = YES; 631 | GCC_WARN_UNUSED_VARIABLE = YES; 632 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 633 | MTL_ENABLE_DEBUG_INFO = NO; 634 | SDKROOT = iphoneos; 635 | SUPPORTED_PLATFORMS = iphoneos; 636 | SWIFT_COMPILATION_MODE = wholemodule; 637 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 638 | TARGETED_DEVICE_FAMILY = "1,2"; 639 | VALIDATE_PRODUCT = YES; 640 | }; 641 | name = Release; 642 | }; 643 | 97C147061CF9000F007C117D /* Debug */ = { 644 | isa = XCBuildConfiguration; 645 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 646 | buildSettings = { 647 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 648 | CLANG_ENABLE_MODULES = YES; 649 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 650 | DEVELOPMENT_TEAM = X6QYJ2NQ5M; 651 | ENABLE_BITCODE = NO; 652 | INFOPLIST_FILE = Runner/Info.plist; 653 | LD_RUNPATH_SEARCH_PATHS = ( 654 | "$(inherited)", 655 | "@executable_path/Frameworks", 656 | ); 657 | PRODUCT_BUNDLE_IDENTIFIER = com.example.starterapp; 658 | PRODUCT_NAME = "$(TARGET_NAME)"; 659 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 660 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 661 | SWIFT_VERSION = 5.0; 662 | VERSIONING_SYSTEM = "apple-generic"; 663 | }; 664 | name = Debug; 665 | }; 666 | 97C147071CF9000F007C117D /* Release */ = { 667 | isa = XCBuildConfiguration; 668 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 669 | buildSettings = { 670 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 671 | CLANG_ENABLE_MODULES = YES; 672 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 673 | DEVELOPMENT_TEAM = X6QYJ2NQ5M; 674 | ENABLE_BITCODE = NO; 675 | INFOPLIST_FILE = Runner/Info.plist; 676 | LD_RUNPATH_SEARCH_PATHS = ( 677 | "$(inherited)", 678 | "@executable_path/Frameworks", 679 | ); 680 | PRODUCT_BUNDLE_IDENTIFIER = com.example.starterapp; 681 | PRODUCT_NAME = "$(TARGET_NAME)"; 682 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 683 | SWIFT_VERSION = 5.0; 684 | VERSIONING_SYSTEM = "apple-generic"; 685 | }; 686 | name = Release; 687 | }; 688 | /* End XCBuildConfiguration section */ 689 | 690 | /* Begin XCConfigurationList section */ 691 | 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { 692 | isa = XCConfigurationList; 693 | buildConfigurations = ( 694 | 331C8088294A63A400263BE5 /* Debug */, 695 | 331C8089294A63A400263BE5 /* Release */, 696 | 331C808A294A63A400263BE5 /* Profile */, 697 | ); 698 | defaultConfigurationIsVisible = 0; 699 | defaultConfigurationName = Release; 700 | }; 701 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 702 | isa = XCConfigurationList; 703 | buildConfigurations = ( 704 | 97C147031CF9000F007C117D /* Debug */, 705 | 97C147041CF9000F007C117D /* Release */, 706 | 249021D3217E4FDB00AE95B9 /* Profile */, 707 | ); 708 | defaultConfigurationIsVisible = 0; 709 | defaultConfigurationName = Release; 710 | }; 711 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 712 | isa = XCConfigurationList; 713 | buildConfigurations = ( 714 | 97C147061CF9000F007C117D /* Debug */, 715 | 97C147071CF9000F007C117D /* Release */, 716 | 249021D4217E4FDB00AE95B9 /* Profile */, 717 | ); 718 | defaultConfigurationIsVisible = 0; 719 | defaultConfigurationName = Release; 720 | }; 721 | /* End XCConfigurationList section */ 722 | }; 723 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 724 | } 725 | --------------------------------------------------------------------------------