├── 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 │ ├── Info.plist │ └── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── AppFrameworkInfo.plist ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── project.pbxproj ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings ├── GoogleService-Info.plist └── Podfile ├── lib ├── const │ └── route.dart ├── models │ ├── Constants.dart │ ├── schedule_service.dart │ └── track_schedule.dart ├── util │ └── animation.dart ├── main.dart ├── bloc │ ├── schedule_like_bloc.dart │ └── bloc_provider.dart ├── droidknightsapp_home.dart ├── pages │ ├── splash_screen.dart │ ├── session_detail_dialog.dart │ ├── schedule_page.dart │ ├── info_ios_page.dart │ └── info_page.dart └── res │ └── strings.dart ├── 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 │ │ │ ├── values │ │ │ │ └── styles.xml │ │ │ └── drawable │ │ │ │ └── launch_background.xml │ │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── droidknights │ │ │ │ └── flutterdroidknights │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ ├── proguard-rules.pro │ ├── google-services.json │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── build.gradle ├── assets ├── fonts │ └── DungGeunMo.ttf ├── images │ ├── dk_title.png │ ├── ic_close.png │ ├── dk19_appicon.jpg │ ├── dk_profile.png │ ├── dk_program.png │ ├── dk19_appicon_star.png │ ├── dk19_ios_appicon.png │ ├── dk_appbar_title.png │ ├── dk_main_graphic.png │ └── dk19_appicon_transparent.png └── json │ ├── schedule_track3.json │ ├── schedule_track2.json │ └── schedule_track1.json ├── .metadata ├── test └── widget_test.dart ├── .gitignore ├── pubspec.yaml └── README.md /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /lib/const/route.dart: -------------------------------------------------------------------------------- 1 | 2 | class Routes { 3 | static const SPLASH = '/'; 4 | static const HOME = '/home'; 5 | } -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true -------------------------------------------------------------------------------- /assets/fonts/DungGeunMo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/assets/fonts/DungGeunMo.ttf -------------------------------------------------------------------------------- /assets/images/dk_title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/assets/images/dk_title.png -------------------------------------------------------------------------------- /assets/images/ic_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/assets/images/ic_close.png -------------------------------------------------------------------------------- /assets/images/dk19_appicon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/assets/images/dk19_appicon.jpg -------------------------------------------------------------------------------- /assets/images/dk_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/assets/images/dk_profile.png -------------------------------------------------------------------------------- /assets/images/dk_program.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/assets/images/dk_program.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /assets/images/dk19_appicon_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/assets/images/dk19_appicon_star.png -------------------------------------------------------------------------------- /assets/images/dk19_ios_appicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/assets/images/dk19_ios_appicon.png -------------------------------------------------------------------------------- /assets/images/dk_appbar_title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/assets/images/dk_appbar_title.png -------------------------------------------------------------------------------- /assets/images/dk_main_graphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/assets/images/dk_main_graphic.png -------------------------------------------------------------------------------- /assets/images/dk19_appicon_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/assets/images/dk19_appicon_transparent.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/droidknights/DroidKnights-Festival-2019-flutter/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/droidknights/DroidKnights-Festival-2019-flutter/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 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | #Flutter Wrapper 2 | -keep class io.flutter.app.** { *; } 3 | -keep class io.flutter.plugin.** { *; } 4 | -keep class io.flutter.util.** { *; } 5 | -keep class io.flutter.view.** { *; } 6 | -keep class io.flutter.** { *; } 7 | -keep class io.flutter.plugins.** { *; } -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip 7 | -------------------------------------------------------------------------------- /lib/models/Constants.dart: -------------------------------------------------------------------------------- 1 | class Constants { 2 | static const String Setting = 'Setting'; 3 | static const String MakeQR = 'Make QR'; 4 | static const String ReadQR = 'Read QR'; 5 | 6 | static const List choices = [ 7 | Setting, 8 | //MakeQR, 9 | //ReadQR 10 | ]; 11 | } -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /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/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/droidknights/flutterdroidknights/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.droidknights.flutterdroidknights 2 | 3 | import android.os.Bundle 4 | 5 | import io.flutter.app.FlutterActivity 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity: FlutterActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | GeneratedPluginRegistrant.registerWith(this) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/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 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | import GoogleMaps 4 | import Firebase 5 | 6 | @UIApplicationMain 7 | @objc class AppDelegate: FlutterAppDelegate { 8 | override func application( 9 | _ application: UIApplication, 10 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? 11 | ) -> Bool { 12 | GMSServices.provideAPIKey("AIzaSyD5W3yb4jxvq7fjVl-QUOc_f2zSSZ9SWwU") 13 | GeneratedPluginRegistrant.register(with: self) 14 | FirebaseApp.configure() 15 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/models/schedule_service.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async' show Future; 2 | import 'package:flutter/services.dart' show rootBundle; 3 | import 'dart:convert'; 4 | import 'package:droidknights/models/track_schedule.dart'; 5 | 6 | 7 | Future _loadAScheduleAsset(String path) async { 8 | return await rootBundle.loadString(path); 9 | } 10 | 11 | 12 | Future> loadSchedule(String path) async { 13 | String jsonString = await _loadAScheduleAsset(path); 14 | final jsonResponse = json.decode(jsonString); 15 | ScheduleListModel schedule = new ScheduleListModel.fromJson(jsonResponse); 16 | return schedule.list; 17 | } -------------------------------------------------------------------------------- /lib/util/animation.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | Animation makeTweenAnimation({ 4 | @required Animation controller, 5 | @required double begin, 6 | @required double end, 7 | Curve curve = Curves.ease, 8 | }) => 9 | Tween(begin: 0.0, end: 1.0).animate( 10 | CurvedAnimation( 11 | parent: controller, 12 | curve: Interval(begin, end, curve: curve), 13 | ), 14 | ); 15 | 16 | double calculateAnimationValue(Animation animation, double begin, double end) => 17 | (begin * (1 - animation.value)) + (end * animation.value); 18 | 19 | double calculateTweenValue(double value, double begin, double end) => 20 | (begin * (1 - value)) + (end * value); 21 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.2.71' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.2.1' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | classpath 'com.google.gms:google-services:4.0.1' 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | rootProject.buildDir = '../build' 23 | subprojects { 24 | project.buildDir = "${rootProject.buildDir}/${project.name}" 25 | } 26 | subprojects { 27 | project.evaluationDependsOn(':app') 28 | } 29 | 30 | task clean(type: Delete) { 31 | delete rootProject.buildDir 32 | } 33 | -------------------------------------------------------------------------------- /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 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:droidknights/const/route.dart'; 2 | import 'package:droidknights/pages/splash_screen.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:droidknights/droidknightsapp_home.dart'; 5 | import 'package:droidknights/res/strings.dart'; 6 | 7 | void main() => runApp(MyApp()); 8 | 9 | class MyApp extends StatelessWidget { 10 | @override 11 | Widget build(BuildContext context) { 12 | return MaterialApp( 13 | title: Strings.DROID_KNIGHTS, 14 | theme: ThemeData( 15 | primaryColor: Color(0xff000000), 16 | accentColor: Color(0xff40d225), 17 | indicatorColor: Color(0xff40d225), 18 | primaryColorLight: Color(0xff96ce7e), 19 | fontFamily: 'DungGeunMo', 20 | ), 21 | debugShowCheckedModeBanner: false, 22 | routes: { 23 | Routes.SPLASH: (_) => new SplashScreen(), 24 | Routes.HOME: (_) => new DroidknightsAppHome(), 25 | } 26 | /*initialRoute: "/splash", 27 | home: DroidknightsAppHome(), 28 | routes: { 29 | "/splash": (BuildContext context) => SplashScreen(), 30 | },*/ 31 | ); 32 | } 33 | } -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:droidknights/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "753974315512", 4 | "firebase_url": "https://my-flutter-proje-1551617458833.firebaseio.com", 5 | "project_id": "my-flutter-proje-1551617458833", 6 | "storage_bucket": "my-flutter-proje-1551617458833.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:753974315512:android:ba7ed9fa3035b04f", 12 | "android_client_info": { 13 | "package_name": "com.droidknights.flutterdroidknights" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "753974315512-22p6t7a2iqd042j4rd2492tns6h55vd1.apps.googleusercontent.com", 19 | "client_type": 3 20 | } 21 | ], 22 | "api_key": [ 23 | { 24 | "current_key": "AIzaSyCQmQde_-xSfWAs2vnyGgam2KaUC-E88-o" 25 | } 26 | ], 27 | "services": { 28 | "analytics_service": { 29 | "status": 1 30 | }, 31 | "appinvite_service": { 32 | "status": 1, 33 | "other_platform_oauth_client": [] 34 | }, 35 | "ads_service": { 36 | "status": 2 37 | } 38 | } 39 | } 40 | ], 41 | "configuration_version": "1" 42 | } -------------------------------------------------------------------------------- /lib/bloc/schedule_like_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:rxdart/rxdart.dart'; 4 | import 'package:shared_preferences/shared_preferences.dart'; 5 | 6 | import './bloc_provider.dart'; 7 | 8 | class ScheduleLikeBloc implements BlocBase { 9 | final _likeMap = BehaviorSubject>(); 10 | Observable> get $likeMap => _likeMap.stream; 11 | Base64Codec _base64 = Base64Codec(); 12 | Utf8Codec _utf8 = Utf8Codec(); 13 | Map _map = {}; 14 | SharedPreferences prefs; 15 | 16 | ScheduleLikeBloc() { 17 | init(); 18 | } 19 | 20 | void init() async { 21 | prefs = await SharedPreferences.getInstance(); 22 | _map = json.decode(prefs.getString('dkf_schedule_like_map') ?? "{}"); 23 | _likeMap.add(_map); 24 | } 25 | 26 | Future addLike(String id) { 27 | _map[toBase64(id)] = true; 28 | _likeMap.add(_map); 29 | prefs.setString('dkf_schedule_like_map', json.encode(_map)); 30 | return prefs.commit(); 31 | } 32 | 33 | Future removeLike(String id) { 34 | _map.remove(toBase64(id)); 35 | _likeMap.add(_map); 36 | prefs.setString('dkf_schedule_like_map', json.encode(_map)); 37 | return prefs.commit(); 38 | } 39 | 40 | @override 41 | void dispose() { 42 | _likeMap.close(); 43 | } 44 | 45 | String toBase64(String str) { 46 | return _base64.encode(_utf8.encode(str)); 47 | } 48 | 49 | String fromBase64(String str) { 50 | return _base64.decode(str).toString(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/bloc/bloc_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | Type _typeOf() => T; 4 | 5 | abstract class BlocBase { 6 | void dispose(); 7 | } 8 | 9 | class BlocProvider extends StatefulWidget { 10 | BlocProvider({ 11 | Key key, 12 | @required this.child, 13 | @required this.bloc, 14 | }): super(key: key); 15 | 16 | final Widget child; 17 | final T bloc; 18 | 19 | @override 20 | _BlocProviderState createState() => _BlocProviderState(); 21 | 22 | static T of(BuildContext context){ 23 | final type = _typeOf<_BlocProviderInherited>(); 24 | _BlocProviderInherited provider = 25 | context.ancestorInheritedElementForWidgetOfExactType(type)?.widget; 26 | return provider?.bloc; 27 | } 28 | } 29 | 30 | class _BlocProviderState extends State>{ 31 | @override 32 | void dispose(){ 33 | widget.bloc?.dispose(); 34 | super.dispose(); 35 | } 36 | 37 | @override 38 | Widget build(BuildContext context){ 39 | return new _BlocProviderInherited( 40 | bloc: widget.bloc, 41 | child: widget.child, 42 | ); 43 | } 44 | } 45 | 46 | class _BlocProviderInherited extends InheritedWidget { 47 | _BlocProviderInherited({ 48 | Key key, 49 | @required Widget child, 50 | @required this.bloc, 51 | }) : super(key: key, child: child); 52 | 53 | final T bloc; 54 | 55 | @override 56 | bool updateShouldNotify(_BlocProviderInherited oldWidget) => false; 57 | } -------------------------------------------------------------------------------- /ios/GoogleService-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AD_UNIT_ID_FOR_BANNER_TEST 6 | ca-app-pub-3940256099942544/2934735716 7 | AD_UNIT_ID_FOR_INTERSTITIAL_TEST 8 | ca-app-pub-3940256099942544/4411468910 9 | CLIENT_ID 10 | 753974315512-0c4p0dd0d97rkd22uilum4e398hrljfn.apps.googleusercontent.com 11 | REVERSED_CLIENT_ID 12 | com.googleusercontent.apps.753974315512-0c4p0dd0d97rkd22uilum4e398hrljfn 13 | API_KEY 14 | AIzaSyDXIeZMvr-2x_f_tOWf_X86z0jp2V_ACD0 15 | GCM_SENDER_ID 16 | 753974315512 17 | PLIST_VERSION 18 | 1 19 | BUNDLE_ID 20 | com.droidknights.flutterdroidknights 21 | PROJECT_ID 22 | my-flutter-proje-1551617458833 23 | STORAGE_BUCKET 24 | my-flutter-proje-1551617458833.appspot.com 25 | IS_ADS_ENABLED 26 | 27 | IS_ANALYTICS_ENABLED 28 | 29 | IS_APPINVITE_ENABLED 30 | 31 | IS_GCM_ENABLED 32 | 33 | IS_SIGNIN_ENABLED 34 | 35 | GOOGLE_APP_ID 36 | 1:753974315512:ios:ba7ed9fa3035b04f 37 | DATABASE_URL 38 | https://my-flutter-proje-1551617458833.firebaseio.com 39 | 40 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | droidknights 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | 33 | UISupportedInterfaceOrientations~ipad 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationPortraitUpsideDown 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | UIViewControllerBasedStatusBarAppearance 41 | 42 | io.flutter.embedded_views_preview 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/models/track_schedule.dart: -------------------------------------------------------------------------------- 1 | class ScheduleListModel { 2 | final List list; 3 | 4 | ScheduleListModel({this.list}); 5 | 6 | factory ScheduleListModel.fromJson(List parsedJson) { 7 | List lists = new List(); 8 | lists = parsedJson.map((i) => ScheduleModel.fromJson(i)).toList(); 9 | 10 | return ScheduleListModel(list: lists); 11 | } 12 | } 13 | 14 | class ScheduleModel { 15 | final int type; 16 | final bool tag; 17 | final String title; 18 | final String time; 19 | final List speakers; 20 | final String contents; 21 | 22 | List get names => speakers.map((speaker) => speaker.name).toList(); 23 | List get avatarUrls => 24 | speakers.map((speaker) => speaker.avatarUrl).toList(); 25 | 26 | ScheduleModel( 27 | {this.type, this.tag, this.title, this.time, this.speakers, this.contents}); 28 | 29 | factory ScheduleModel.fromJson(Map parsedJson) { 30 | final List speakers = (parsedJson['speakers'] as List) 31 | ?.map((e) => e == null 32 | ? null 33 | : SpeakerModel.fromJson(e as Map)) 34 | ?.toList() ?? 35 | []; 36 | return ScheduleModel( 37 | type: parsedJson['type'], 38 | tag: parsedJson['tag'], 39 | title: parsedJson['title'], 40 | time: parsedJson['time'], 41 | speakers: speakers, 42 | contents: parsedJson['contents']); 43 | } 44 | } 45 | 46 | class SpeakerModel { 47 | final String name; 48 | final String avatarUrl; 49 | 50 | SpeakerModel({this.name, this.avatarUrl}); 51 | 52 | factory SpeakerModel.fromJson(Map parsedJson) { 53 | return SpeakerModel( 54 | name: parsedJson['name'], 55 | avatarUrl: parsedJson['avatarUrl'], 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /.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 | .vscode/ 21 | 22 | # Flutter repo-specific 23 | /bin/cache/ 24 | /bin/mingit/ 25 | /dev/benchmarks/mega_gallery/ 26 | /dev/bots/.recipe_deps 27 | /dev/bots/android_tools/ 28 | /dev/docs/doc/ 29 | /dev/docs/flutter.docs.zip 30 | /dev/docs/lib/ 31 | /dev/docs/pubspec.yaml 32 | /packages/flutter/coverage/ 33 | version 34 | 35 | # Flutter/Dart/Pub related 36 | **/doc/api/ 37 | .dart_tool/ 38 | .flutter-plugins 39 | .packages 40 | .pub-cache/ 41 | .pub/ 42 | build/ 43 | flutter_*.png 44 | linked_*.ds 45 | unlinked.ds 46 | unlinked_spec.ds 47 | 48 | # Android related 49 | **/android/**/gradle-wrapper.jar 50 | **/android/.gradle 51 | **/android/captures/ 52 | **/android/gradlew 53 | **/android/gradlew.bat 54 | **/android/local.properties 55 | **/android/**/GeneratedPluginRegistrant.java 56 | **/android/key.properties 57 | *.jks 58 | 59 | # iOS/XCode related 60 | **/ios/**/*.mode1v3 61 | **/ios/**/*.mode2v3 62 | **/ios/**/*.moved-aside 63 | **/ios/**/*.pbxuser 64 | **/ios/**/*.perspectivev3 65 | **/ios/**/*sync/ 66 | **/ios/**/.sconsign.dblite 67 | **/ios/**/.tags* 68 | **/ios/**/.vagrant/ 69 | **/ios/**/DerivedData/ 70 | **/ios/**/Icon? 71 | **/ios/**/Pods/ 72 | **/ios/**/.symlinks/ 73 | **/ios/**/profile 74 | **/ios/**/xcuserdata 75 | **/ios/.generated/ 76 | **/ios/Flutter/App.framework 77 | **/ios/Flutter/Flutter.framework 78 | **/ios/Flutter/Generated.xcconfig 79 | **/ios/Flutter/app.flx 80 | **/ios/Flutter/app.zip 81 | **/ios/Flutter/flutter_assets/ 82 | **/ios/ServiceDefinitions.json 83 | **/ios/Runner/GeneratedPluginRegistrant.* 84 | 85 | # Exceptions to above rules. 86 | !**/ios/**/default.mode1v3 87 | !**/ios/**/default.mode2v3 88 | !**/ios/**/default.pbxuser 89 | !**/ios/**/default.perspectivev3 90 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 20 | 23 | 30 | 34 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.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 parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | pods_ary = [] 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) { |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | pods_ary.push({:name => podname, :path => podpath}); 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | } 32 | return pods_ary 33 | end 34 | 35 | target 'Runner' do 36 | use_frameworks! 37 | pod 'Firebase/Core' 38 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 39 | # referring to absolute paths on developers' machines. 40 | system('rm -rf .symlinks') 41 | system('mkdir -p .symlinks/plugins') 42 | 43 | # Flutter Pods 44 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') 45 | if generated_xcode_build_settings.empty? 46 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." 47 | end 48 | generated_xcode_build_settings.map { |p| 49 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR' 50 | symlink = File.join('.symlinks', 'flutter') 51 | File.symlink(File.dirname(p[:path]), symlink) 52 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) 53 | end 54 | } 55 | 56 | # Plugin Pods 57 | plugin_pods = parse_KV_file('../.flutter-plugins') 58 | plugin_pods.map { |p| 59 | symlink = File.join('.symlinks', 'plugins', p[:name]) 60 | File.symlink(p[:path], symlink) 61 | pod p[:name], :path => File.join(symlink, 'ios') 62 | } 63 | end 64 | 65 | post_install do |installer| 66 | installer.pods_project.targets.each do |target| 67 | target.build_configurations.each do |config| 68 | config.build_settings['ENABLE_BITCODE'] = 'NO' 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: droidknights 2 | description: A new Flutter application for DroidKnights Festival 2019. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # Read more about versioning at semver.org. 10 | version: 1.3.0+6 11 | 12 | environment: 13 | sdk: ">=2.1.0 <3.0.0" 14 | 15 | dependencies: 16 | google_maps_flutter: ^0.3.0+2 17 | path_provider: 0.4.1 18 | flutter: 19 | sdk: flutter 20 | url_launcher: ^5.0.1 21 | 22 | # The following adds the Cupertino Icons font to your application. 23 | # Use with the CupertinoIcons class for iOS style icons. 24 | cupertino_icons: ^0.1.2 25 | rxdart: ^0.20.0 26 | shared_preferences: 0.4.0 27 | cached_network_image: 0.5.0 28 | 29 | dev_dependencies: 30 | flutter_test: 31 | sdk: flutter 32 | 33 | flutter_launcher_icons: "^0.7.0" 34 | 35 | flutter_icons: 36 | image_path_android: "assets/images/dk19_appicon.jpg" 37 | image_path_ios: "assets/images/dk19_ios_appicon.png" 38 | android: true 39 | ios: true 40 | 41 | 42 | # For information on the generic Dart part of this file, see the 43 | # following page: https://www.dartlang.org/tools/pub/pubspec 44 | 45 | # The following section is specific to Flutter. 46 | flutter: 47 | 48 | # The following line ensures that the Material Icons font is 49 | # included with your application, so that you can use the icons in 50 | # the material Icons class. 51 | uses-material-design: true 52 | 53 | # To add assets to your application, add an assets section, like this: 54 | assets: 55 | - assets/images/ 56 | - assets/json/ 57 | # - images/a_dot_burr.jpeg 58 | # - images/a_dot_ham.jpeg 59 | 60 | # An image asset can refer to one or more resolution-specific "variants", see 61 | # https://flutter.io/assets-and-images/#resolution-aware. 62 | 63 | # For details regarding adding assets from package dependencies, see 64 | # https://flutter.io/assets-and-images/#from-packages 65 | 66 | # To add custom fonts to your application, add a fonts section here, 67 | # in this "flutter" section. Each entry in this list should have a 68 | # "family" key with the font family name, and a "fonts" key with a 69 | # list giving the asset and other descriptors for the font. For 70 | # example: 71 | fonts: 72 | - family: DungGeunMo 73 | fonts: 74 | - asset: assets/fonts/DungGeunMo.ttf 75 | 76 | # - family: Trajan Pro 77 | # fonts: 78 | # - asset: fonts/TrajanPro.ttf 79 | # - asset: fonts/TrajanPro_Bold.ttf 80 | # weight: 700 81 | # 82 | # For details regarding fonts from package dependencies, 83 | # see https://flutter.io/custom-fonts/#from-packages 84 | -------------------------------------------------------------------------------- /lib/droidknightsapp_home.dart: -------------------------------------------------------------------------------- 1 | import 'package:droidknights/pages/info_ios_page.dart'; 2 | import 'package:droidknights/pages/info_page.dart'; 3 | import 'package:droidknights/pages/schedule_page.dart'; 4 | import 'package:droidknights/res/strings.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter/cupertino.dart'; 7 | import 'dart:io' show Platform; 8 | 9 | 10 | class DroidknightsAppHome extends StatefulWidget { 11 | @override 12 | _DroidknightsAppHomeState createState() => _DroidknightsAppHomeState(); 13 | } 14 | 15 | class _DroidknightsAppHomeState extends State { 16 | 17 | int _index = 0; 18 | List _pages = [Platform.isAndroid ? InfoPage() : InfoIosPage(), SchedulePage()]; 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return Platform.isAndroid ? createAndroidWidget() : createIosWidget(); 23 | } 24 | 25 | Widget createAndroidWidget() { 26 | 27 | return Scaffold( 28 | body: bodyPages(), 29 | bottomNavigationBar: BottomNavigationBar( 30 | onTap: (int index) => { 31 | setState(() { 32 | _index = index; 33 | }) 34 | }, 35 | currentIndex: _index, 36 | items: [ 37 | BottomNavigationBarItem( 38 | icon: Icon(Icons.info), 39 | title: Text(Strings.INFO_TAB), 40 | ), 41 | BottomNavigationBarItem( 42 | icon: Icon(Icons.schedule), 43 | title: Text(Strings.SCHEDULE_TAB), 44 | ), 45 | ], 46 | )); 47 | } 48 | 49 | Widget bodyPages() { 50 | return new Stack( 51 | children: [ 52 | new Offstage( 53 | offstage: _index != 0, 54 | child: new TickerMode( 55 | enabled: _index == 0, 56 | child: _pages[0], 57 | ), 58 | ), 59 | new Offstage( 60 | offstage: _index != 1, 61 | child: new TickerMode( 62 | enabled: _index == 1, 63 | child: _pages[1], 64 | ), 65 | ), 66 | ], 67 | ); 68 | } 69 | 70 | Widget createIosWidget() { 71 | return CupertinoTabScaffold( 72 | backgroundColor: const Color(0xFF112030), 73 | tabBar: CupertinoTabBar( 74 | onTap: (int index) => { 75 | setState(() { 76 | _index = index; 77 | }) 78 | }, 79 | backgroundColor: CupertinoColors.lightBackgroundGray, 80 | items: [ 81 | BottomNavigationBarItem( 82 | icon: Icon(CupertinoIcons.info), 83 | title: Text(Strings.INFO_TAB), 84 | ), 85 | BottomNavigationBarItem( 86 | icon: Icon(CupertinoIcons.clock), 87 | title: Text(Strings.SCHEDULE_TAB), 88 | ), 89 | ], 90 | ), 91 | tabBuilder: (context, index) { 92 | return CupertinoTabView( 93 | builder: (context) { 94 | return bodyPages(); 95 | }, 96 | ); 97 | }, 98 | ); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DroidKnights 2019 공식 App 2 | 3 | [드로이드 나이츠](https://droidknights.github.io/2019/)는 4월 5일 코엑스E홀에서 열리는 안드로이드 개발자를 위한 컨퍼런스입니다. 4 | 5 | 본 앱은 마켓에서 다운받으실 수 있습니다. 6 | 7 | - [안드로이드](https://play.google.com/store/apps/details?id=com.droidknights.flutterdroidknights) 8 | - Apple - [오픈 베타](https://testflight.apple.com/join/AMkdVFws) 9 | 10 | ## Feature 11 | 12 | | info | timetable | detail | 13 | |---|---|---| 14 | |![device-2019-04-03-235832](https://user-images.githubusercontent.com/7722921/55495192-55acdd80-5677-11e9-9e93-0fe7dacdffc1.png)|![device-2019-04-03-235917](https://user-images.githubusercontent.com/7722921/55495261-75440600-5677-11e9-8912-ed3f7efb193d.png)|![device-2019-04-04-000108](https://user-images.githubusercontent.com/7722921/55495300-8a209980-5677-11e9-88ea-01ad072e03b5.png)| 15 | 16 | - 크게 두 개의 하단 메뉴로 구성 (info/schedule) 17 | - 서버는 사용하지 않고, 로컬에 있는 데이터로 표시합니다. 18 | - [flutter](https://flutter.dev/) 프레임워크로 개발. 19 | 20 | ## Join 21 | 22 | 함께 앱을 develop 시킬 여러분들을 기다립니다. 23 | - flutter가 익숙하신 숙련자 24 | - 아직 flutter를 경험해보지 못한 초보자 25 | - DroidKnights App에 기여하고 싶으신 모든 분들 26 | 27 | 누구나 참여하실 수 있습니다. 28 | 29 | 본 앱은 행사 당일(4월 5일) 전까지 지속적으로 마켓에 업데이트 할 예정입니다. 30 | 31 | ### 참여 방법 32 | 33 | **Issues** 를 참고하여 이슈를 수정하시거나, 이슈를 발견하면 자유롭게 등록하여 주세요. 34 | 35 | 코드를 수정하여 Pull requests를 날려주시고 Contributor가 되어보세요. 36 | 37 | ## Getting Started 38 | 39 | This project is a starting point for a Flutter application. 40 | 41 | A few resources to get you started if this is your first Flutter project: 42 | 43 | - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) 44 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) 45 | 46 | For help getting started with Flutter, view our 47 | [online documentation](https://flutter.io/docs), which offers tutorials, 48 | samples, guidance on mobile development, and a full API reference. 49 | 50 | # Contributors 51 | 52 | 참여해주신 모든 분들 감사합니다. 53 | 54 | [![](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/images/0)](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/links/0)[![](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/images/1)](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/links/1)[![](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/images/2)](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/links/2)[![](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/images/3)](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/links/3)[![](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/images/4)](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/links/4)[![](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/images/5)](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/links/5)[![](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/images/6)](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/links/6)[![](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/images/7)](https://sourcerer.io/fame/Jiyoung9310/droidknights/DroidKnights-Festival-2019-flutter/links/7) 55 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def keystoreProperties = new Properties() 2 | def keystorePropertiesFile = rootProject.file('key.properties') 3 | if (keystorePropertiesFile.exists()) { 4 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterRoot = localProperties.getProperty('flutter.sdk') 16 | if (flutterRoot == null) { 17 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 18 | } 19 | 20 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 21 | if (flutterVersionCode == null) { 22 | flutterVersionCode = '1' 23 | } 24 | 25 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 26 | if (flutterVersionName == null) { 27 | flutterVersionName = '1.0' 28 | } 29 | 30 | def mapApiKey = localProperties.getProperty('mapApiKey') 31 | if (mapApiKey == null) { 32 | mapApiKey = '' 33 | } 34 | 35 | apply plugin: 'com.android.application' 36 | apply plugin: 'kotlin-android' 37 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 38 | 39 | android { 40 | compileSdkVersion 28 41 | 42 | useLibrary 'org.apache.http.legacy' 43 | 44 | 45 | sourceSets { 46 | main.java.srcDirs += 'src/main/kotlin' 47 | } 48 | 49 | lintOptions { 50 | disable 'InvalidPackage' 51 | } 52 | 53 | defaultConfig { 54 | applicationId "com.droidknights.flutterdroidknights" 55 | minSdkVersion 23 56 | targetSdkVersion 28 57 | versionCode flutterVersionCode.toInteger() 58 | versionName flutterVersionName 59 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 60 | } 61 | 62 | defaultConfig { 63 | manifestPlaceholders = [mapApiKey: "$mapApiKey"] 64 | } 65 | 66 | signingConfigs { 67 | debug { 68 | 69 | } 70 | release { 71 | /*keyAlias keystoreProperties['keyAlias'] 72 | keyPassword keystoreProperties['keyPassword'] 73 | storeFile file(keystoreProperties['storeFile']) 74 | storePassword keystoreProperties['storePassword']*/ 75 | } 76 | } 77 | 78 | buildTypes { 79 | debug { 80 | 81 | } 82 | release { 83 | /*minifyEnabled true 84 | useProguard true 85 | 86 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 87 | signingConfig signingConfigs.release*/ 88 | } 89 | } 90 | } 91 | 92 | flutter { 93 | source '../..' 94 | } 95 | 96 | dependencies { 97 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 98 | implementation 'com.google.firebase:firebase-core:16.0.1' 99 | 100 | compileOnly 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2' 101 | testImplementation 'junit:junit:4.12' 102 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 103 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 104 | } 105 | apply plugin: 'com.google.gms.google-services' -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /assets/json/schedule_track3.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": 0, 4 | "tag": false, 5 | "title": "E6", 6 | "time": "장소", 7 | "speakers": [], 8 | "contents": "" 9 | }, 10 | { 11 | "type": 0, 12 | "tag": false, 13 | "title": "키노트", 14 | "time": "9:50", 15 | "speakers": [], 16 | "contents": "" 17 | }, 18 | { 19 | "type": 1, 20 | "tag": false, 21 | "title": "동적 맵 프레임워크와 인터렉션 구현하기", 22 | "time": "10:10", 23 | "speakers": [ 24 | { 25 | "name": "정승욱", 26 | "avatarUrl": "https://drive.google.com/uc?export=view&id=1Dx1DMKmsArJC-UW4-lcn6pA5MmbKvwGC" 27 | } 28 | ], 29 | "contents": "안드로이드에서 GoogleMap, MapBox, HereMap, Tmap 등을 앱 재실행 없이 실시간으로 동적으로 지원하기 위해 처리한 방법과 서로 다른 맵 프레임워크에서 동일한 맵 인터렉션을 독립적인 컴포넌트로 구현하는 방법을 공유하고자 합니다." 30 | }, 31 | { 32 | "type": 1, 33 | "tag": false, 34 | "title": "Master of Android Theme (English)", 35 | "time": "11:10", 36 | "speakers": [ 37 | { 38 | "name": "Yusuke Konishi", 39 | "avatarUrl": "https://avatars0.githubusercontent.com/u/1269214?s=460&v=4" 40 | } 41 | ], 42 | "contents": "Do you manage Android theme effectively? Do you set the view attributes in each styles or views instead of using Android theme?\nI'll talk about the attributes you can set in Android theme especially Material Components Library.\n\nAndroid 테마를 효과적으로 관리합니까? Android 테마를 사용하는 대신 각 스타일 또는보기에서보기 속성을 설정합니까?\nAndroid 테마, 특히 Material Components Library에서 설정할 수있는 속성에 대해 이야기하겠습니다." 43 | }, 44 | { 45 | "type": 1, 46 | "tag": false, 47 | "title": "MotionLayout 무릎까지 담가보기", 48 | "time": "11:55", 49 | "speakers": [ 50 | { 51 | "name": "노현석", 52 | "avatarUrl": "https://pbs.twimg.com/profile_images/683256802704687104/QnjrPuLj_400x400.jpg" 53 | } 54 | ], 55 | "contents": "Google I/O '18에서 소개된 MotionLayout에 대해서 알아봅니다. MotionLayout의 소개, 컴포넌트 정의를 소개하며 샘플 예제를 통해 어떻게 모션 레이아웃을 적용할지 소개할 예정입니다." 56 | }, 57 | { 58 | "type": 1, 59 | "tag": true, 60 | "title": "communication between flutter and native modules baby step", 61 | "time": "12:55", 62 | "speakers": [ 63 | { 64 | "name": "장인수", 65 | "avatarUrl": "https://drive.google.com/uc?export=view&id=1JNv9JAdUMIEYhkJH3sfm5OHl4V6YjWfw" 66 | } 67 | ], 68 | "contents": "Flutter의 전반적인 설명 후 Flutter 와 Native Module 간의 통신 개발하는 방법을 Baby Step 으로 소개 하고자 합니다. " 69 | }, 70 | { 71 | "type": 0, 72 | "tag": false, 73 | "title": "점심시간", 74 | "time": "13:25 \n~ 15:00", 75 | "speakers": [], 76 | "contents": "13:25 ~ 15:00\n약 90분동안 점심 식사 시간입니다." 77 | }, 78 | { 79 | "type": 1, 80 | "tag": true, 81 | "title": "구글 플레이 다이나믹 딜리버리 - APK는 이제 안녕~", 82 | "time": "15:00", 83 | "speakers": [ 84 | { 85 | "name": "양찬석", 86 | "avatarUrl": "https://avatars1.githubusercontent.com/u/1445837?s=400&v=4" 87 | } 88 | ], 89 | "contents": "1. 왜 다이나믹 딜리버리가 필요할까?\n2. 구글에 앱 사인 키를 알려주세요.\n3. 앱 번들 기능 소개 및 적용법\n4. 앱 번들 효과적으로 테스팅 하기\n5. 앱 번들 이 후 - 다이나믹 피쳐 모듈 소개\n6. 다이나믹 피쳐 모듈을 어떻게 활용할 수 있을까? (구현 및 UX)\n7. 앞으로 앱은 어떻게 배포되고 개발될까?" 90 | }, 91 | { 92 | "type": 1, 93 | "tag": true, 94 | "title": "안드로이드 윈도우 마스터 되기", 95 | "time": "16:00", 96 | "speakers": [ 97 | { 98 | "name": "안명욱", 99 | "avatarUrl": "https://scontent.ficn1-1.fna.fbcdn.net/v/t1.0-9/53324220_2161482243910239_8670930524082012160_n.jpg?_nc_cat=102&_nc_ht=scontent.ficn1-1.fna&oh=f95166793eb1a7e3ad4837f3c0216b96&oe=5CDCA40D" 100 | } 101 | ], 102 | "contents": "System UI 영역에 앱을 draw하거나 풀스크린 모드로 화면을 구성 할 때 Display Cutout 대응 등 WindowInset이 활용되는 경우와 주의해야 할 점들에 대해 알아봅니다.\n구글 개발자 Chris Banes가 Droidcon NYC 2017에서 발표한 Becoming a master window fitters를 기반으로 준비하였으며 최신사항을 반영하였습니다." 103 | }, 104 | { 105 | "type": 1, 106 | "tag": false, 107 | "title": "Android Gradle Plugin 버그 잡기", 108 | "time": "16:45", 109 | "speakers": [ 110 | { 111 | "name": "차영호", 112 | "avatarUrl": "https://www.facebook.com/photo.php?fbid=1713043895411121&set=t.1379763942&type=3&theater" 113 | } 114 | ], 115 | "contents": "* AOSP Ecosystem 소개\n* Andorid Gradle Plugin(AGP) 간단 소개\n* 적절한 AGP 브랜치/태그 찾기\n* AGP를 직접 빌드 및 설치\n* AGP의 task 구현 살펴보기\n* 찾은 버그를 AOSP issue tracker에 등록하기\n* 버그 수정을 AOSP gerrit에 등록하기\n* 후기 " 116 | }, 117 | { 118 | "type": 1, 119 | "tag": true, 120 | "title": "Tensorflow Lite 부터 ML Kit, Mobile GPU 활용 까지", 121 | "time": "17:30", 122 | "speakers": [ 123 | { 124 | "name": "신정아", 125 | "avatarUrl": "http://jeongahri.azurewebsites.net/img/profile.jpeg" 126 | } 127 | ], 128 | "contents": "안드로이드 환경에서의 Tensorflow Lite, ML Kit 활용법과 경험기를 공유합니다. 딥러닝 비전 모델 데모와 함께 더 나은 안드로이드 모바일 머신러닝 환경을 갖추기 위한 프리셋을 알아보고, Tensorflow Lite에서 새로 지원되는 기능인 Mobile GPU의 활용 까지 살펴봅니다." 129 | } 130 | ] 131 | -------------------------------------------------------------------------------- /lib/pages/splash_screen.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:droidknights/const/route.dart'; 4 | import 'package:droidknights/util/animation.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'dart:io' show Platform; 7 | 8 | const NUMBER_OF_STARS = 30; 9 | const ANIMATION_TIME_MILL = 2500; 10 | 11 | class SplashScreen extends StatefulWidget { 12 | 13 | @override 14 | SplashScreenState createState() { 15 | return new SplashScreenState(); 16 | } 17 | } 18 | 19 | class SplashScreenState extends State with SingleTickerProviderStateMixin { 20 | 21 | List> _animations; 22 | AnimationController _controller; 23 | List> _topAndLefts; 24 | 25 | @override 26 | void initState() { 27 | super.initState(); 28 | 29 | Random random = new Random(); 30 | _topAndLefts = new List.generate(NUMBER_OF_STARS, (int i) => i) 31 | .map((int i) => Point(random.nextInt(500).toDouble(), random.nextInt(1000) / 3.5)) 32 | .toList(); 33 | 34 | _initAnimation(); 35 | } 36 | 37 | void animationListener(AnimationStatus status) { 38 | if(status == AnimationStatus.completed) { 39 | Navigator.pushReplacementNamed(context, Routes.HOME); 40 | } 41 | } 42 | 43 | void _initAnimation() { 44 | _controller = AnimationController(duration: Duration(milliseconds: ANIMATION_TIME_MILL), vsync: this); 45 | 46 | _controller.addStatusListener(animationListener); 47 | 48 | _animations = [ 49 | makeTweenAnimation(controller: _controller, begin: 0.2, end: 0.6), 50 | makeTweenAnimation(controller: _controller, begin: 0.5, end: 1), 51 | ]; 52 | 53 | _controller.forward(); 54 | } 55 | 56 | @override 57 | void dispose() { 58 | _disposeAnimation(); 59 | super.dispose(); 60 | } 61 | 62 | void _disposeAnimation() { 63 | _controller.dispose(); 64 | } 65 | 66 | @override 67 | Widget build(BuildContext context) => 68 | AnimatedBuilder( 69 | animation: _controller, 70 | builder: (context, widget) => 71 | Scaffold( 72 | backgroundColor: new Color(0xff143F5F), 73 | body: Container( 74 | decoration: BoxDecoration( 75 | gradient: LinearGradient( 76 | begin: Alignment.topCenter, 77 | end: Alignment.bottomCenter, 78 | colors: [ 79 | new Color(0xff000000), 80 | new Color(0xff143F5F), 81 | new Color(0xff143F5F), 82 | ], 83 | ), 84 | ), 85 | child: _splashImages(), 86 | ) 87 | ), 88 | ); 89 | 90 | Widget _splashImages() { 91 | if(Platform.isAndroid) { 92 | return Column( 93 | mainAxisSize: MainAxisSize.max, 94 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 95 | crossAxisAlignment: CrossAxisAlignment.center, 96 | children: [ 97 | _buildStar(), 98 | _buildLogo(), 99 | _buildGraphic(), 100 | ], 101 | ); 102 | } else { 103 | return Container(); 104 | } 105 | } 106 | 107 | Widget _buildStar() => 108 | Opacity( 109 | opacity: calculateAnimationValue(_animations[1], 0, 0.5), 110 | child: Container( 111 | height: 200, 112 | child: Stack( 113 | overflow: Overflow.visible, 114 | children: [ 115 | Positioned(child: Container(width: MediaQuery.of(context).size.width, height: 200)), 116 | ]..addAll(_buildStars()), 117 | ), 118 | ), 119 | ); 120 | 121 | List _buildStars() => 122 | _topAndLefts.map((topAndLeft) => 123 | Positioned( 124 | top: calculateAnimationValue(_animations[1], topAndLeft.y - 20, topAndLeft.y), 125 | left: topAndLeft.x, 126 | child: Image.asset( 127 | 'assets/images/dk19_appicon_star.png', 128 | width: 6, 129 | height: 6, 130 | ), 131 | )) 132 | .toList(); 133 | 134 | Widget _buildLogo() => 135 | Opacity( 136 | child: Center( 137 | child: Image.asset( 138 | 'assets/images/dk19_appicon_transparent.png', 139 | width: 96, 140 | height: 96, 141 | ), 142 | ), 143 | opacity: calculateAnimationValue(_animations[0], 0, 1), 144 | ); 145 | 146 | Widget _buildGraphic() => 147 | Opacity( 148 | opacity: 0.0, 149 | child: Center( 150 | child: Image.asset( 151 | 'assets/images/dk_main_graphic.png', 152 | width: MediaQuery.of(context).size.width, 153 | height: 200, 154 | fit: BoxFit.fitWidth, 155 | ), 156 | ), 157 | ); 158 | } 159 | -------------------------------------------------------------------------------- /assets/json/schedule_track2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": 0, 4 | "tag": false, 5 | "title": "E5", 6 | "time": "장소", 7 | "speakers": [], 8 | "contents": "" 9 | }, 10 | { 11 | "type": 0, 12 | "tag": false, 13 | "title": "키노트", 14 | "time": "9:50", 15 | "speakers": [], 16 | "contents": "" 17 | }, 18 | { 19 | "type": 1, 20 | "tag": false, 21 | "title": "Android TDD 적용기", 22 | "time": "10:10", 23 | "speakers": [ 24 | { 25 | "name": "김성일", 26 | "avatarUrl": "https://drive.google.com/uc?export=view&id=1wkWfJtjuNvb5Xd2O_3z9DetlqsWOPSAl" 27 | } 28 | ], 29 | "contents": "앱 개발을 하며 느리고 반복적인 디바이스 테스트에 회의를 느끼고, 테스트를 도입하려고 마음먹었습니다. 단위테스트 작성부터 TDD를 적용하는 것을 목표로 많은 시행착오를 겪었으며, 최근 실무 프로젝트의 대부분을 TDD로 개발하였습니다. 이번 프로젝트의 일부를 실례로 제시하며, 안드로이드 앱 개발과정에 TDD를 적용하면서 느끼고 경험했던 것을 공유합니다." 30 | }, 31 | { 32 | "type": 1, 33 | "tag": true, 34 | "title": "Android Project with Multiple Modules", 35 | "time": "11:10", 36 | "speakers": [ 37 | { 38 | "name": "장선옥", 39 | "avatarUrl": "https://avatars0.githubusercontent.com/u/8149379?s=460&v=4" 40 | } 41 | ], 42 | "contents": "여러 개의 모듈을 사용해서 안드로이드 프로젝트를 개발하고 있는 이유와, 모듈화 된 앱 개발의 장단점, 모듈화 방법, 프로젝트 관리법 등에 대해 소개합니다." 43 | }, 44 | { 45 | "type": 1, 46 | "tag": false, 47 | "title": "코틀린 디자인 패턴", 48 | "time": "11:55", 49 | "speakers": [ 50 | { 51 | "name": "남상균", 52 | "avatarUrl": "https://drive.google.com/uc?export=view&id=1kd5IFqkWEoUOCOVJep0Y30tQjokzvh-U" 53 | } 54 | ], 55 | "contents": "코틀린은 언어 자체에서 디자인 패턴을 효과적으로 반영할 수 있도록 설계되어 있습니다. 전통적인 GoF의 23가지 디자인 패턴이 코틀린에서 어떻게 적용될 수 있는지 살펴보고, 더 효율적인 코드를 작성하는 방법에 대해 이야기 합니다. 특히 각 패턴들이 자바로는 어떻게 구현되었는지 비교해 보며 코틀린 언어에 대한 이해도를 높이는 계기가 되었으면 합니다." 56 | }, 57 | { 58 | "type": 1, 59 | "tag": false, 60 | "title": "오프라인과 앱 서비스", 61 | "time": "12:55", 62 | "speakers": [ 63 | { 64 | "name": "김현", 65 | "originAvatarUrl": "https://photos.app.goo.gl/7AwTHg6yaaNMPe919", 66 | "avatarUrl": "https://lh3.googleusercontent.com/ci10yO-BTClOV5x6TlJZyJFzobbj_fbjchnaQtIT-0cMhvsvNkMfdtn4ykBscH3imC6NYQB4aWt5I3p4RzVmX0Y_EJzuGUZjK9Acfq4hPyhO9C75yFrG8jEjj7zyo-kkf6FWNmY24Y8aoNQQYD6TdIEzknmlyJft-hvxizuFcxFICneEWct8p9LIS8JnTFuXsS3nA2vL9ZoDXNT65KnDiz2dvOjUGOXh5icqgF-OkkbzHBpPKlVSn2LKxlbZckJQHF-A6WABNaM5FVxeUokKWtQVgwylQ9Q2QaDRZPOSMBl5LO9O7SgJmv8IX0nL12cL_xKD_uizMOg8ca6PS688lyCJnH5iphm4DC5ZSJm61xeTHw-Liu86lDpkvxSWJv637O-SDKfoRbGTTkFnPa4iMT-6L6tb1u2NT4WfciCKaiIX47d3iGaLQsXByfMf7v8kns7LV7cBUox8nq1H0yP-r5Px25MGLCiCDoLeVslJ8X8S3cXkk80ei4eh1aeqDb0mHaCNwNextlPNMqjBa0sM6TOxQsswUn8bO3QxPu3XES1D_-NP_Uz8C2LwqrVtHoQfc0D1u438iXsCclGJ70_vMVrxJRDhDzDepPkJnmmCdhrI3bO9kcRNtKehQrhoJXb6LzMa-SQnSV-rNYgmshGabO_0ZMwXhZWqXITRmUHJRwMCrgItXLESNfbumynQoCKVAzyZa1jMZP4Wac5IbFTy8kWnJg=w1000-no-tmp.jpg" 67 | } 68 | ], 69 | "contents": "인터넷 끊김, 속도저하에 따라 네트워크 없이 서비스를 안정적으로 제공할 방법에 대하여 고민하였습니다. 메모리/디스크 캐시를 이용한 데이터 임시저장, 서버 데이터가 필요없는 서비스에 대한 오프라인 서비스 모드 제공, 오프라인 스토리지에 서버 데이터를 저장하고 동기화 하는 방법 등, 이 과정에서 겪은 문제점과 해결방법 그리고 발전 방향에 대해 공유합니다." 70 | }, 71 | { 72 | "type": 0, 73 | "tag": false, 74 | "title": "점심시간", 75 | "time": "13:25 \n~ 15:00", 76 | "speakers": [ 77 | { 78 | "name": "", 79 | "avatarUrl": "" 80 | } 81 | ], 82 | "contents": "13:25 ~ 15:00\n약 90분동안 점심 식사 시간입니다." 83 | }, 84 | { 85 | "type": 1, 86 | "tag": false, 87 | "title": "코루틴 너 은행에서 뭐하니?", 88 | "time": "15:00", 89 | "speakers": [ 90 | { 91 | "name": "정동진", 92 | "avatarUrl": "https://cdn-images-1.medium.com/max/800/1*IhzasZVTtWbSkVCklSyH7w.jpeg" 93 | } 94 | ], 95 | "contents": "1. 코루틴을 어느 곳에서 사용하고, 어떤 강점을 갖는지에 대한 간략한 설명\n2. 샘플 학습과 안드로이드 적용\n3. 실무코드에 적용 및 문제점 및 적용법\n4. 적용된 소스코드 설명\n5. 최적화된 코드에 대한 고민" 96 | }, 97 | { 98 | "type": 1, 99 | "tag": true, 100 | "title": "PWA 를 이용한 안드로이드 웹뷰 성능 개선기", 101 | "time": "16:00", 102 | "speakers": [ 103 | { 104 | "name": "박민석", 105 | "avatarUrl": "https://bit.ly/2tYiwyg" 106 | }, 107 | { 108 | "name": "유진의", 109 | "avatarUrl": "https://s3.ap-northeast-2.amazonaws.com/jinui/images/jinui.jpg" 110 | } 111 | ], 112 | "contents": "웹뷰를 포함한 앱이 어떻게 하면 사용자에게 더 빠른 속도로 좋은 경험을 전달할 수 있을까요? PWA와 함께 기존 웹뷰의 한계를 극복하고 사용자 경험을 한층 더 발전시킨 경험을 공유합니다." 113 | }, 114 | { 115 | "type": 1, 116 | "tag": false, 117 | "title": "SVC 패턴으로 앱 쉽게 만들기", 118 | "time": "16:45", 119 | "speakers": [ 120 | { 121 | "name": "남반석", 122 | "avatarUrl": "https://cdn1.imggmi.com/uploads/2019/2/27/3729a48ce31876e3ec87c284e060b992-full.png" 123 | } 124 | ], 125 | "contents": "\"어떻게 더 쉽게 코드를 짤 수 있을까?\"를 고민했습니다. 고민 포인트를 공유하고 SVC 패턴의 탄생 배경과 다른 패턴들과의 차이를 비교하고, SVC를 통해서 스펙이 많아 복잡한 화면을 어떻게 나눠서 유지보수를 쉽게 할 수 있을지, RecyclerView에서 ViewModel활용법 등 노하우를 공유합니다." 126 | }, 127 | { 128 | "type": 1, 129 | "tag": true, 130 | "title": "ViewPager2 설레발 치기!", 131 | "time": "17:30", 132 | "speakers": [ 133 | { 134 | "name": "김범준", 135 | "avatarUrl": "https://drive.google.com/uc?export=view&id=1miEdK1RtxMcPgCqm9caPkkcd-WclmQ0p" 136 | } 137 | ], 138 | "contents": "아직 알파 단계인 ViewPager2에 대하여 이야기 하고자 합니다. 왜 ViewPager2가 나온 걸까요? 어떤 유용한 기능들이 추가 되었는지, 기존 ViewPager를 사용 할 때와 어떤 차이점들이 있는지등을 내부 구현 코드와 예시를 적절히 섞어 설명드리려 합니다." 139 | } 140 | ] 141 | -------------------------------------------------------------------------------- /lib/res/strings.dart: -------------------------------------------------------------------------------- 1 | class Strings { 2 | 3 | static const String DROID_KNIGHTS = "DroidKnights"; 4 | static const String IMAGES_DK_PROFILE = "assets/images/dk_profile.png"; 5 | static const String IMAGES_DK_IOS_PROFILE = "assets/images/dk19_ios_appicon.png"; 6 | 7 | // FONT 8 | static const String FONT_FAMILY_ROBOTO = "Roboto"; 9 | static const String FONT_DUNG_GEUN_MO = "DungGeunMo"; 10 | 11 | // INFO TAB 12 | static const String INFO_TAB = "Information"; 13 | static const String INFO_TAB_MAKER = "코엑스"; 14 | static const String INFO_TAB_SNIPPET = "3F E홀"; 15 | static const String INFO_TAB_MOVE_HOMEPAGE = "홈페이지로 이동"; 16 | static const String INFO_TAB_URL_DROID_KNIGHTS = "https://droidknights.github.io/2019/"; 17 | static const String INFO_TAB_MAIN_TITLE = "오직 안드로이드 개발자들을 위한 컨퍼런스! 드로이드나이츠 2019"; 18 | static const String INFO_TAB_APPBAR_TITLE = "CONFERENCE INTRODUCTION"; 19 | 20 | static const String INFO_TAB_SECTION_TITLE_DROID_KNIGHTS = "DROID KNIGHTS 2019"; 21 | static const String INFO_TAB_SECTION_TITLE_PROGRAM = "PROGRAM"; 22 | static const String INFO_TAB_SECTION_TITLE_LOCATION = "LOCATION"; 23 | static const String INFO_TAB_SECTION_TITLE_SPONSOR = "SPONSOR"; 24 | static const String INFO_TAB_SECTION_SUB_TITLE_INTRO = "드로이드나이츠는 \"안드로이드 개발자들을 위한 컨퍼런스\"를 표방하며 안드로이드 기술에 대한 세션으로 안드로이드 개발자들의 경험을 공유하고 만남의 장을 만드는 컨퍼런스 입니다.\n한국은 높은 안드로이드점유율과 관련 제조사, 플랫폼 개발회사, 앱 개발회사 등 개발 생태계가 잘 발달하였음에도 불구하고 안드로이드 개발자들이 지식을 나눌 수 있는 기회가 부족하다는 필요로 인해 비영리 개발자 조직에 의해 만들어졌습니다.\n드로이드나이츠 2017, 2018을 성공리에 개최하고 이번 2019년에는 더욱 성숙한 행사를 통해 안드로이드 개발자들이 새로운 기술과 정보를 공유하고 서로 교류할 수 있는 행사가 되기를 희망합니다."; 25 | static const String INFO_TAB_SECTION_SUB_TITLE_INTRO2 = "2019 드로이드 나이츠는 세션 이외의 다양한 프로그램을 준비하고 있습니다."; 26 | static const String INFO_TAB_SECTION_SUB_TITLE_LOCATION = "장소 : 코엑스 E홀 / 서울특별시 강남구 영동대로 513 (삼성동, 코엑스)"; 27 | 28 | static const String INFO_TAB_PROGRAM_IMG = "assets/images/dk_program.png"; 29 | 30 | static const String INFO_TAB_TITLE_CODE_REVIEW = "코드리뷰 (15:00 ~ 14:30)"; 31 | static const String INFO_TAB_TITLE_CODE_REVIEW_CONTENT = "나의 코드를 간략히 소개하고,\n다른 개발자들에게 리뷰를 받습니다.\n리뷰 과정 참관도 가능합니다."; 32 | static const String INFO_TAB_TITLE_CODE_LAB = "코드랩 (10:30 ~ 13:25)"; 33 | static const String INFO_TAB_TITLE_CODE_LAB_CONTENT = "4가지 flutter 튜토리얼 코드를\n각자 학습하며, 궁금한 부분이 생기면\n도움을 요청할 수 있습니다. (노트북 지참)"; 34 | static const String INFO_TAB_TITLE_LIVE_QUIZ = "실시간 퀴즈쇼"; 35 | static const String INFO_TAB_TITLE_LIVE_QUIZ_CONTENT = "당신의 개발력을 뽐내보세요!\n푸짐한 상품이 함께합니다."; 36 | static const String INFO_TAB_TITLE_LIGHTENING_TALK = "라이트닝 토크 (16:45 ~ 17:30)"; 37 | static const String INFO_TAB_TITLE_LIGHTENING_TALK_CONTENT = "일상적인 업무 속에서 성장하기위한\n노력을 공유하고, 함께 방법을 찾아갑니다.\n4인의 발표 후 주제별로 그룹지어 이야기를 나눕니다."; 38 | 39 | static const String INFO_TAB_IMAGES_PATH_DK_MAIN_GRAPHIC = "assets/images/dk_main_graphic.png"; 40 | static const String INFO_TAB_IMAGES_PATH_DK_TITLE = "assets/images/dk_title.png"; 41 | 42 | static const String INFO_TAB_URL_SPONSOR_LINE = "https://linepluscorp.com/"; 43 | static const String INFO_TAB_URL_IMAGE_SPONSOR_LINE = "https://droidknights.github.io/2019/static/media/banner.76bec31e.png"; 44 | static const String INFO_TAB_URL_SPONSOR_PRD = "https://prnd.co.kr/"; 45 | static const String INFO_TAB_URL_IMAGE_SPONSOR_PRD = "https://droidknights.github.io/2019/static/media/banner.fa39ae88.png"; 46 | static const String INFO_TAB_URL_SPONSOR_JETBRAINS = "https://www.jetbrains.com/"; 47 | static const String INFO_TAB_URL_IMAGE_SPONSOR_JETBRAINS = "https://droidknights.github.io/2019/static/media/banner.0ddeb0f4.png"; 48 | static const String INFO_TAB_URL_SPONSOR_HYPERCONNECT = "https://hyperconnect.com/"; 49 | static const String INFO_TAB_URL_IMAGE_SPONSOR_HYPERCONNECT = "https://droidknights.github.io/2019/static/media/banner.fbcd4102.png"; 50 | static const String INFO_TAB_URL_SPONSOR_YANOLJA = "http://yanolja.in/ko/"; 51 | static const String INFO_TAB_URL_IMAGE_SPONSOR_YANOLJA = "https://droidknights.github.io/2019/static/media/banner.b4594f6d.png"; 52 | static const String INFO_TAB_URL_SPONSOR_RAINIST = "https://rainist.com/"; 53 | static const String INFO_TAB_URL_IMAGE_SPONSOR_RAINIST = "https://droidknights.github.io/2019/static/media/banner.7e2fbc8b.png"; 54 | static const String INFO_TAB_URL_SPONSOR_EBRAIN = "http://www.ebrain.kr/"; 55 | static const String INFO_TAB_URL_IMAGE_SPONSOR_EBRAIN = "https://droidknights.github.io/2019/static/media/banner.69f4dfae.png"; 56 | static const String INFO_TAB_URL_SPONSOR_LEZHIN = "https://www.lezhin.com/ko"; 57 | static const String INFO_TAB_URL_IMAGE_SPONSOR_LEZHIN = "https://droidknights.github.io/2019/static/media/banner.7e86e723.png"; 58 | 59 | 60 | // SCHEDULE TAB 61 | static const String SCHEDULE_TAB_APPBAR_TITLE = "SCHEDULE"; 62 | static const String SCHEDULE_TAB = "Schedule"; 63 | static const String SCHEDULE_TAB_TRACK1 = "Track1"; 64 | static const String SCHEDULE_TAB_TRACK2 = "Track2"; 65 | static const String SCHEDULE_TAB_TRACK3 = "Track3"; 66 | 67 | static const String SCHEDULE_ITEM_BEGINNER_TAG = "FOR BEGINNER"; 68 | 69 | static const String SCHEDULE_TAB_IMAGES_APP_BAR = "assets/images/dk_appbar_title.png"; 70 | static const String SCHEDULE_TAB_JSON_TRACK_SCREEN1 = "assets/json/schedule_track1.json"; 71 | static const String SCHEDULE_TAB_JSON_TRACK_SCREEN2 = "assets/json/schedule_track2.json"; 72 | static const String SCHEDULE_TAB_JSON_TRACK_SCREEN3 = "assets/json/schedule_track3.json"; 73 | 74 | // SESSION DETAIL DIALOG 75 | static const String SESSION_DIALOG_IMAGES_CLOSE = "assets/images/ic_close.png"; 76 | } 77 | -------------------------------------------------------------------------------- /assets/json/schedule_track1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": 0, 4 | "tag": false, 5 | "title": "E2,3,4", 6 | "time": "장소", 7 | "speakers": [ 8 | { 9 | "name": "", 10 | "avatarUrl": "" 11 | } 12 | ], 13 | "contents": "" 14 | }, 15 | { 16 | "type": 0, 17 | "tag": false, 18 | "title": "키노트", 19 | "time": "9:50", 20 | "speakers": [ 21 | { 22 | "name": "", 23 | "avatarUrl": "" 24 | } 25 | ], 26 | "contents": "" 27 | }, 28 | { 29 | "type": 1, 30 | "tag": false, 31 | "title": "RxJava 구독과 구독 제거 메커니즘 설명", 32 | "time": "10:10", 33 | "speakers": [ 34 | { 35 | "name": "노재춘", 36 | "avatarUrl": "https://postfiles.pstatic.net/MjAxOTAzMDRfMTU5/MDAxNTUxNjg1NDk0Mjk4.pZTfcj6Ffr562KxtU_uHYhAA5jWmghIY_CyLcJW5xiog.b_BiOszNZr7Gcc_mKvnFlNPFylAQexcmi27q6W_33B0g.JPEG.hanuldt/SE-abe5ce07-4c48-4f09-9299-731df1da6440.jpg?type=w580" 37 | } 38 | ], 39 | "contents": "RxJava의 구독과 구독 제거 메커니즘을 이해하고 정확하게 이를 적용하는 방법을 얘기합니다." 40 | }, 41 | { 42 | "type": 1, 43 | "tag": true, 44 | "title": "지금까지 이런 간단한 Logic 처리는 없었다 이것은 Rx 인가, UI 이벤트인가? 네, RxBinding입니다.", 45 | "time": "11:10", 46 | "speakers": [ 47 | { 48 | "name": "하동현", 49 | "avatarUrl": "https://drive.google.com/uc?export=view&id=17XUDJDFep7JGtWq71wPPnYVzFU8VY1Gk" 50 | } 51 | ], 52 | "contents": "한 화면에 다양한 UI가 존재하며 각 UI마다 복잡한 로직이 있으며, 처리하다 보면 엉키게 되어 유지보수를 하기 어렵게 됩니다. 
RxBinding을 이용하면 손쉽게 중복코드를 처리하고 UI 이벤트를 조합하여 문제를 해결할 수 있습니다. 
RxBinding의 기본 사용방법과 프로덕트에 적용한 경험을 다양한 예시와 함께 설명합니다." 53 | }, 54 | { 55 | "type": 1, 56 | "tag": false, 57 | "title": "Clean Architecture (in Android) Revised", 58 | "time": "11:55", 59 | "speakers": [ 60 | { 61 | "name": "황성현", 62 | "avatarUrl": "https://avatars0.githubusercontent.com/u/8149378" 63 | } 64 | ], 65 | "contents": "Droid Knights 2017 발표 중 하나였던 [Clean Architecture in Android] 발표를 2019년의 시각으로 다시 재구성을 시도합니다. Android라는 콘텍스트를 조금 벗어나 Clean Architecture의 문제의식과 이를 구현한 코드 여럿을 함께 살펴보고 얘기를 나눕니다." 66 | }, 67 | { 68 | "type": 1, 69 | "tag": true, 70 | "title": "Kotlin 꼭 해야하나요?", 71 | "time": "12:55", 72 | "speakers": [ 73 | { 74 | "name": "박상권", 75 | "avatarUrl": "https://www.dropbox.com/s/i5evo2188d40s28/1550711591729.png?raw=1" 76 | } 77 | ], 78 | "contents": "- Kotlin이 공식언어로 지정된지 2년이 됐음에도 요즘 각종 안드로이드 커뮤니티에서 제일 많이 나오는 질문은 'Kotlin 꼭 해야하나요?' 입니다.\n- Java코드를 Kotlin코드로 코딩하기 시작하면서 느꼈던 Java코드와 Kotlin을 비교했을때의 특징과 장점들에 대해서 이야기 합니다.\n- Kotlin을 학습하려고 하는 분들을 위한 각종 팁들과 삽질경험들을 공유합니다." 79 | }, 80 | { 81 | "type": 0, 82 | "tag": false, 83 | "title": "점심 시간", 84 | "time": "13:25 \n~ 15:00", 85 | "speakers": [], 86 | "contents": "13:25 ~ 15:00\n약 90분동안 점심 식사 시간입니다." 87 | }, 88 | { 89 | "type": 1, 90 | "tag": false, 91 | "title": "안드로이드 아키텍처 총정리", 92 | "time": "15:00", 93 | "speakers": [ 94 | { 95 | "name": "강사룡", 96 | "avatarUrl": "https://www.dropbox.com/s/cshhhpdo4b2kh5y/IMG_2975.png?raw=1" 97 | } 98 | ], 99 | "contents": "당신의 아키텍처, 뭔가 잘못된 것 같은 느낌에 시달리고 있지는 않나요? MVP부터 MVVM, Flux 그리고 클린 아키텍처까지 Best Practice를 중심으로 현업에서 어떤 아키텍처를 적용할 것인가에 대해, 그리고 아키텍처 관점에서 의존성 주입, Rx, 코루틴, 멀티모듈 등의 기술을 어떻게 적용할 수 있을지, 2018년에 이어 더욱 깊은 내용으로 다뤄봅니다." 100 | }, 101 | { 102 | "type": 1, 103 | "tag": false, 104 | "title": "코루틴 안전! 이쁘게 코루틴 사용하는 방법은?", 105 | "time": "16:00", 106 | "speakers": [ 107 | { 108 | "name": "권태환", 109 | "originAvatarUrl": "https://photos.app.goo.gl/JMWyxaUz4RSwpppo9", 110 | "avatarUrl": "https://lh3.googleusercontent.com/rPndEdMcqItGgFsrs50h6NkGmyxYutV5h2SCGkOUcQ2I03SfFHZTQQoIsb8TanrbzDy7JGHF1MTgq-3rRtQW3RZFIP86d4GMWwsW5n_cszPh1TSx4ABZmp-4q1fbq0Q_ASI5Otb1mdL2AkbXfth1JNuFElDXRffLy4kZpkD6gg61QNclhaGlAWoUs7ra_-R6Y8vLhmRVXCJ3Frcn4oinhMi_DvEiJRDBLkQyL7zZXCFrtJk39GPLP5XZ8lZpLp-Tk823EQreBYNPGd8fdS_3qLQoClgpFdOpFt8f26-LsE4DwOxEDDdqWQoHRJ3K6EpDpJJ7J1L60y7eZt6i-pBKQWMCGhmKe_eOPt_7MsuEppNSJnXY3BTno42a-guPpMjWGnz9QhdbjGd7UxOuc2sp34PIZZP43V4It7QvU6oRXuu_dqxXf7y16d0gJiLc3FZvixrj5yGSbYBPVkm9xFqoEmK4uBtr2vhGkIbtdkfmdh22nam_WaI3A1L-0fnqPKR3v01W_-WkMUybnk4owaoMQT-bPec_uek4J7sd-LEZe0zlWbBBivQodtNWg5jeYUQbSvICMTyVZV2PXwPIVsqEtEkf8RFInl8EZr-bUCoqUiwOTiQmQ6RyGpS7mTTXrWebqx_0bEV8AS_-9HdpyXhJ-et6qvO4FORus1tLDIERfB-yNLnokUO7apzKkGKIWEEYR5Iu8BRDVq0e9WwdxyS5ipdPvw=w1000-no-tmp.jpg" 111 | } 112 | ], 113 | "contents": "코루틴은 어렵지 않게 적용할 수 있다. 그러면 코루틴 내에서 발생하는 오류를 어떻게 캐치하고 안전하게 사용할 수 있을까? 코루틴 내에서 발생하는 오류를 안전하게 처리하는 방법을 소개하고, 코루틴으로 라이브러리 형태로 접근 하는 방법을 소개하려고 한다.\n- 코루틴 소개\n- 코루틴 사용 중 발생하는 오류 처리 방법을 알아본다\n- 코루틴 라이브러리를 직접 만들고 활용해보는 방법을 알아본다\n- 실제 적용 사례를 함께 소개한다" 114 | }, 115 | { 116 | "type": 1, 117 | "tag": true, 118 | "title": "Dagger2와 Koin 소개 - 어떻게 쓰는 걸까요?", 119 | "time": "16:45", 120 | "speakers": [ 121 | { 122 | "name": "정현지", 123 | "avatarUrl": "https://drive.google.com/uc?export=view&id=1UnMNRAy81WFIuLP5-65X0LEaXIHufeda" 124 | } 125 | ], 126 | "contents": "1. DI란 무엇일까?\n2. Dagger란 무엇일까 ?\n3. Koin란 무엇일까 ?\n4. 기본적인 두개의 기술에 대한 예시를 들면서 공통점과 차이점은 무엇일까?\n5. 본론\n- 둘의 차이점 비교\n- DI 를 적용했을 때 장단점은?\n- DI를 공부하고 이렇게 적용하면서 우리가 얻고자 하는 것은?" 127 | }, 128 | { 129 | "type": 1, 130 | "tag": false, 131 | "title": "Advanced MVP", 132 | "time": "17:30", 133 | "speakers": [ 134 | { 135 | "name": "박미륵", 136 | "avatarUrl": "https://cdn.banksalad.com/rainist/member/mireuk_profile.png" 137 | } 138 | ], 139 | "contents": "MVP 패턴을 사용하면서 겪었던 어려움에 대해서 이야기하고 이를 개선하기 위해 했던 고민과 방법들에 대해서 이야기하고자 합니다." 140 | } 141 | ] 142 | -------------------------------------------------------------------------------- /lib/pages/session_detail_dialog.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io' show Platform; 2 | import 'dart:math'; 3 | 4 | import 'package:cached_network_image/cached_network_image.dart'; 5 | import 'package:droidknights/models/track_schedule.dart'; 6 | import 'package:droidknights/res/strings.dart'; 7 | import 'package:flutter/material.dart'; 8 | 9 | class SessionDetailDialog extends ModalRoute { 10 | final ScheduleModel sessionData; 11 | 12 | SessionDetailDialog(this.sessionData); 13 | 14 | @override 15 | Duration get transitionDuration => Duration(milliseconds: 300); 16 | 17 | @override 18 | bool get opaque => false; 19 | 20 | @override 21 | bool get barrierDismissible => false; 22 | 23 | @override 24 | Color get barrierColor => Colors.black.withOpacity(0.82); 25 | 26 | @override 27 | String get barrierLabel => null; 28 | 29 | @override 30 | bool get maintainState => true; 31 | 32 | @override 33 | Widget buildPage( 34 | BuildContext context, 35 | Animation animation, 36 | Animation secondaryAnimation, 37 | ) { 38 | // This makes sure that text and other content follows the material style 39 | return GestureDetector( 40 | child: Material( 41 | type: MaterialType.transparency, 42 | // make sure that the overlay content is not cut off 43 | child: SafeArea( 44 | child: new Stack( 45 | children: [ 46 | new Row( 47 | mainAxisAlignment: MainAxisAlignment.end, 48 | children: [ 49 | new Padding( 50 | padding: const EdgeInsets.all(27.0), 51 | child: new IconButton( 52 | icon: 53 | new Image.asset(Strings.SESSION_DIALOG_IMAGES_CLOSE), 54 | iconSize: 24, 55 | onPressed: () => Navigator.pop(context), 56 | ), 57 | ), 58 | ], 59 | ), 60 | _buildOverlayContent(context), 61 | ], 62 | ), 63 | ), 64 | ), 65 | onTap: () => Navigator.pop(context), 66 | ); 67 | } 68 | 69 | Widget _buildOverlayContent(BuildContext context) { 70 | return Column( 71 | mainAxisAlignment: MainAxisAlignment.center, 72 | mainAxisSize: MainAxisSize.max, 73 | children: [ 74 | new Center( 75 | child: new Stack( 76 | children: [ 77 | new Padding( 78 | padding: const EdgeInsets.only( 79 | left: 27.0, right: 27.0, top: avatarHalfSize, bottom: 27.0), 80 | child: GestureDetector( 81 | child: new Container( 82 | width: double.infinity, 83 | decoration: new BoxDecoration( 84 | color: Colors.white, 85 | borderRadius: new BorderRadius.all( 86 | const Radius.circular(4.0), 87 | ), 88 | ), 89 | padding: const EdgeInsets.only( 90 | left: 10.0, 91 | right: 10.0, 92 | top: avatarHalfSize, 93 | bottom: avatarHalfSize), 94 | child: new Column( 95 | mainAxisAlignment: MainAxisAlignment.center, 96 | crossAxisAlignment: CrossAxisAlignment.center, 97 | children: [ 98 | new Padding( 99 | padding: const EdgeInsets.only( 100 | left: 32.0, 101 | right: 32.0, 102 | top: 16.0, 103 | bottom: 3.0), 104 | child: new Text( 105 | sessionData.title, 106 | textAlign: TextAlign.center, 107 | style: new TextStyle(fontSize: 16.0), 108 | )), 109 | Row( 110 | mainAxisAlignment: MainAxisAlignment.center, 111 | crossAxisAlignment: CrossAxisAlignment.center, 112 | children: [ 113 | new Text( 114 | sessionData.names.join(", "), 115 | style: new TextStyle( 116 | color: new Color(0xffa5b495), fontSize: 16.0), 117 | ), 118 | sessionData.tag ? _setTag() : Container(), 119 | ], 120 | ), 121 | new Padding( 122 | padding: const EdgeInsets.symmetric( 123 | horizontal: 10.0, vertical: 13.0), 124 | child: new Text( 125 | sessionData.contents.toString(), 126 | style: new TextStyle( 127 | color: new Color(0xff4a4a4a), 128 | fontSize: 12.0), 129 | )), 130 | //rating 131 | ], 132 | ), 133 | ), 134 | onTap: () => {}), 135 | ), 136 | new Row( 137 | mainAxisAlignment: MainAxisAlignment.center, 138 | children: [profileImage], 139 | ), 140 | ], 141 | ), 142 | ), 143 | ], 144 | ); 145 | } 146 | 147 | Widget _setTag() { 148 | return Padding( 149 | padding: const EdgeInsets.all(5.0), 150 | child: Text( 151 | Strings.SCHEDULE_ITEM_BEGINNER_TAG, 152 | style: 153 | TextStyle(color: Color(0xff40d225), fontSize: 12.0), 154 | ), 155 | ); 156 | } 157 | 158 | @override 159 | Widget buildTransitions(BuildContext context, Animation animation, 160 | Animation secondaryAnimation, Widget child) { 161 | // You can add your own animations for the overlay content 162 | return FadeTransition( 163 | opacity: animation, 164 | child: ScaleTransition( 165 | scale: animation, 166 | child: child, 167 | ), 168 | ); 169 | } 170 | 171 | static const double avatarSize = 160.0; 172 | static const double avatarHalfSize = avatarSize / 2; 173 | 174 | Widget get profileImage { 175 | return new Hero( 176 | tag: sessionData, 177 | child: Row( 178 | children: sessionData.speakers 179 | .sublist(0, min(sessionData.speakers.length, 2)) 180 | .map(avatarContainer) 181 | .expand((w) => [w, Padding(padding: EdgeInsets.only(left: 8.0))]) 182 | .toList() 183 | ..removeLast(), 184 | )); 185 | } 186 | 187 | Widget avatarContainer(SpeakerModel speaker) { 188 | return GestureDetector( 189 | child: ClipOval( 190 | child: FadeInImage( 191 | width: avatarSize, 192 | height: avatarSize, 193 | fadeInDuration: const Duration(seconds: 0), 194 | fadeOutDuration: const Duration(seconds: 0), 195 | image: CachedNetworkImageProvider(speaker.avatarUrl), 196 | placeholder: AssetImage(Platform.isAndroid 197 | ? Strings.IMAGES_DK_PROFILE 198 | : Strings.IMAGES_DK_IOS_PROFILE), 199 | fit: BoxFit.fitHeight, 200 | ) 201 | ), 202 | 203 | onTap: () => {} 204 | ); 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /lib/pages/schedule_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io' show Platform; 2 | 3 | import 'package:cached_network_image/cached_network_image.dart'; 4 | import 'package:droidknights/bloc/schedule_like_bloc.dart'; 5 | import 'package:droidknights/models/schedule_service.dart'; 6 | import 'package:droidknights/models/track_schedule.dart'; 7 | import 'package:droidknights/pages/session_detail_dialog.dart'; 8 | import 'package:droidknights/res/strings.dart'; 9 | import 'package:flutter/material.dart'; 10 | 11 | class SchedulePage extends StatelessWidget { 12 | static final int ITEMVIEW_TYPE_NORMAL = 0; 13 | static final int ITEMVIEW_TYPE_SESSTION = 1; 14 | final ScheduleLikeBloc _likeBloc = new ScheduleLikeBloc(); 15 | 16 | Widget scheduleAppbar() { 17 | return SliverAppBar( 18 | centerTitle: true, 19 | title: Platform.isAndroid ? androidAppBarTitle() : iosAppBarTitle(), 20 | pinned: true, 21 | floating: true, 22 | bottom: TabBar( 23 | labelColor: Color(0xff40d225), 24 | unselectedLabelColor: Colors.grey, 25 | indicatorColor: Color(0xff40d225), 26 | tabs: [ 27 | Tab(text: Strings.SCHEDULE_TAB_TRACK1), 28 | Tab(text: Strings.SCHEDULE_TAB_TRACK2), 29 | Tab(text: Strings.SCHEDULE_TAB_TRACK3), 30 | ], 31 | ), 32 | ); 33 | } 34 | 35 | Widget androidAppBarTitle() => Image.asset( 36 | Strings.SCHEDULE_TAB_IMAGES_APP_BAR, 37 | fit: BoxFit.fitHeight, 38 | height: 25, 39 | ); 40 | 41 | Widget iosAppBarTitle() => Text( 42 | Strings.SCHEDULE_TAB_APPBAR_TITLE, 43 | style: new TextStyle( 44 | fontSize: 24.0, 45 | fontWeight: FontWeight.w600, 46 | ), 47 | ); 48 | 49 | @override 50 | Widget build(BuildContext context) { 51 | return DefaultTabController( 52 | length: 3, 53 | child: Scaffold( 54 | body: NestedScrollView( 55 | headerSliverBuilder: 56 | (BuildContext context, bool innerBoxIsScrolled) => [ 57 | scheduleAppbar(), 58 | ], 59 | body: TabBarView( 60 | children: [ 61 | trackScreen(Strings.SCHEDULE_TAB_JSON_TRACK_SCREEN1), 62 | trackScreen(Strings.SCHEDULE_TAB_JSON_TRACK_SCREEN2), 63 | trackScreen(Strings.SCHEDULE_TAB_JSON_TRACK_SCREEN3), 64 | ], 65 | ), 66 | ), 67 | )); 68 | } 69 | 70 | Widget trackScreen(String filePath) { 71 | return FutureBuilder( 72 | future: loadSchedule(filePath), 73 | builder: (BuildContext context, 74 | AsyncSnapshot> snapshot) { 75 | if (!snapshot.hasData) return Container(color: Colors.black); 76 | return Container( 77 | color: Colors.black, 78 | child: ListView.builder( 79 | padding: new EdgeInsets.only(bottom: 30), 80 | itemCount: snapshot.data.length, 81 | itemBuilder: (context, i) => Column( 82 | children: [_itemView(context, snapshot.data[i])])), 83 | ); 84 | }); 85 | } 86 | 87 | Widget _itemView(context, data) { 88 | return StreamBuilder( 89 | stream: _likeBloc.$likeMap, 90 | builder: (context, snapshot) { 91 | if (!snapshot.hasData) return Container(); 92 | return data.type == ITEMVIEW_TYPE_SESSTION 93 | ? _showItemSection( 94 | context, 95 | data, 96 | snapshot.data[_likeBloc.toBase64(data.title + data.time)] == 97 | null 98 | ? false 99 | : snapshot 100 | .data[_likeBloc.toBase64(data.title + data.time)]) 101 | : _showItemNormal(context, data); 102 | }); 103 | } 104 | 105 | Widget _showItemSection(context, data, liked) { 106 | return ListTile( 107 | leading: Text( 108 | data.time, 109 | style: TextStyle( 110 | color: Theme.of(context).primaryColorLight, fontSize: 12.0), 111 | ), 112 | title: Container( 113 | decoration: BoxDecoration( 114 | color: Colors.white, 115 | borderRadius: new BorderRadius.all( 116 | const Radius.circular(4.0), 117 | ), 118 | boxShadow: [ 119 | BoxShadow( 120 | color: Color(0xFFE9EEF6), 121 | blurRadius: 4.0, 122 | offset: Offset(0, 2.0), 123 | ), 124 | ], 125 | ), 126 | padding: const EdgeInsets.all(12.0), 127 | child: Row( 128 | mainAxisAlignment: MainAxisAlignment.start, 129 | children: [ 130 | Container( 131 | decoration: BoxDecoration( 132 | shape: BoxShape.circle, 133 | border: new Border.all(color: Colors.grey, width: 1)), 134 | child: ClipOval( 135 | child: FadeInImage( 136 | width: 56.0, 137 | height: 56.0, 138 | fadeInDuration: const Duration(seconds: 0), 139 | fadeOutDuration: const Duration(seconds: 0), 140 | image: CachedNetworkImageProvider(data.avatarUrls.first), 141 | placeholder: AssetImage(Platform.isAndroid 142 | ? Strings.IMAGES_DK_PROFILE 143 | : Strings.IMAGES_DK_IOS_PROFILE), 144 | fit: BoxFit.fitHeight, 145 | ), 146 | ), 147 | ), 148 | Padding(padding: const EdgeInsets.symmetric(horizontal: 6.0)), 149 | Expanded( 150 | child: Container( 151 | constraints: BoxConstraints(minHeight: 60.0), 152 | child: Column( 153 | mainAxisAlignment: MainAxisAlignment.center, 154 | crossAxisAlignment: CrossAxisAlignment.start, 155 | children: [ 156 | Text( 157 | data.title, 158 | maxLines: 2, 159 | overflow: TextOverflow.ellipsis, 160 | style: TextStyle(fontSize: 16.0), 161 | ), 162 | Row( 163 | children: [ 164 | Text( 165 | data.names.join(", "), 166 | style: 167 | TextStyle(color: Color(0xffa5b495), fontSize: 12.0), 168 | ), 169 | data.tag ?_setTag() : Container(), 170 | ], 171 | ), 172 | ], 173 | ), 174 | ), 175 | ), 176 | IconButton( 177 | icon: Icon(liked ? Icons.favorite : Icons.favorite_border), 178 | onPressed: () { 179 | liked 180 | ? _likeBloc.removeLike(data.title + data.time) 181 | : _likeBloc.addLike(data.title + data.time); 182 | }) 183 | ], 184 | ), 185 | ), 186 | onTap: () => showDetailPage(context, data), 187 | ); 188 | } 189 | 190 | Widget _setTag() { 191 | return Padding( 192 | padding: const EdgeInsets.all(5.0), 193 | child: Text( 194 | Strings.SCHEDULE_ITEM_BEGINNER_TAG, 195 | style: 196 | TextStyle(color: Color(0xff40d225), fontSize: 10.0), 197 | ), 198 | ); 199 | } 200 | 201 | Widget _showItemNormal(context, data) { 202 | return ListTile( 203 | leading: Text( 204 | data.time, 205 | style: TextStyle( 206 | color: Theme.of(context).primaryColorLight, fontSize: 12.0), 207 | ), 208 | title: Text( 209 | data.title, 210 | style: TextStyle(color: Theme.of(context).accentColor, fontSize: 16.0), 211 | ), 212 | ); 213 | } 214 | 215 | showDetailPage(BuildContext context, data) { 216 | Navigator.of(context).push(SessionDetailDialog(data)); 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /lib/pages/info_ios_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:droidknights/res/strings.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:google_maps_flutter/google_maps_flutter.dart'; 6 | import 'package:url_launcher/url_launcher.dart'; 7 | 8 | class InfoIosPage extends StatefulWidget { 9 | @override 10 | State createState() => InfoIosPageState(); 11 | } 12 | 13 | class InfoIosPageState extends State { 14 | static const double _sectionAllPadding = 20.0; 15 | static const double _sectionTopPadding = 10.0; 16 | static const double _contentsAllPadding = 10.0; 17 | 18 | 19 | Completer _controller = Completer(); 20 | static final CameraPosition _coexPosition = CameraPosition( 21 | target: LatLng(37.513212, 127.058595), 22 | zoom: 14.4746, 23 | ); 24 | 25 | static MarkerId markerId = MarkerId(Strings.INFO_TAB_MAKER); 26 | static Marker marker = Marker( 27 | markerId: markerId, 28 | position: LatLng(37.513212, 127.058595), 29 | infoWindow: InfoWindow(title: Strings.INFO_TAB_MAKER, snippet: '*'), 30 | ); 31 | 32 | Map markers = { 33 | markerId:marker, 34 | }; 35 | 36 | 37 | final TextStyle _titleTextStyle = new TextStyle( 38 | fontSize: 19.0, 39 | color: const Color(0xFF77e448), 40 | fontWeight: FontWeight.w400, 41 | height: 1.3, 42 | fontFamily: Strings.FONT_DUNG_GEUN_MO); 43 | 44 | final TextStyle _subtitleTextStyle = new TextStyle( 45 | fontSize: 13.0, 46 | color: const Color(0xFFededed), 47 | fontWeight: FontWeight.w200, 48 | height: 1.5, 49 | fontFamily: Strings.FONT_DUNG_GEUN_MO); 50 | 51 | final TextStyle _buttonTextStyle = new TextStyle( 52 | fontSize: 15.0, 53 | color: const Color(0xFFededed), 54 | fontWeight: FontWeight.w500, 55 | fontFamily: Strings.FONT_DUNG_GEUN_MO); 56 | 57 | @override 58 | Widget build(BuildContext context) { 59 | return Scaffold( 60 | appBar: AppBar( 61 | backgroundColor: const Color(0xFF112030), 62 | centerTitle: true, 63 | title: new Text( 64 | Strings.INFO_TAB_APPBAR_TITLE, 65 | style: new TextStyle( 66 | fontSize: 24.0, 67 | fontWeight: FontWeight.w600, 68 | ), 69 | ), 70 | ), 71 | body: _contentWidget() 72 | ); 73 | } 74 | 75 | _contentWidget() { 76 | return Container( 77 | color: const Color(0xFF112030), 78 | child: SingleChildScrollView( 79 | scrollDirection: Axis.vertical, 80 | padding: const EdgeInsets.all(_sectionAllPadding), 81 | child: Column( 82 | mainAxisAlignment: MainAxisAlignment.start, 83 | mainAxisSize: MainAxisSize.max, 84 | crossAxisAlignment: CrossAxisAlignment.start, 85 | children: [ 86 | //imageBanner(), 87 | //mainTitle(Strings.INFO_TAB_MAIN_TITLE), 88 | //sectionTopPadding(), 89 | sectionTitle(Strings.INFO_TAB_SECTION_TITLE_DROID_KNIGHTS), 90 | //sectionSubTitle(Strings.INFO_TAB_SECTION_SUB_TITLE_INTRO), 91 | goToHomepage(), 92 | sectionTopPadding(), 93 | sectionTitle(Strings.INFO_TAB_SECTION_TITLE_PROGRAM), 94 | sectionSubTitle(Strings.INFO_TAB_SECTION_SUB_TITLE_INTRO2), 95 | sectionTopPadding(), 96 | programImage(), 97 | programList(), 98 | sectionTopPadding(), 99 | sectionTitle(Strings.INFO_TAB_SECTION_TITLE_LOCATION), 100 | sectionSubTitle(Strings.INFO_TAB_SECTION_SUB_TITLE_LOCATION), 101 | googleMap(), 102 | sectionTitle(Strings.INFO_TAB_SECTION_TITLE_SPONSOR), 103 | sponsorList(), 104 | ] 105 | ), 106 | ) 107 | ); 108 | } 109 | 110 | Widget programImage() => new Image.asset( 111 | Strings.INFO_TAB_PROGRAM_IMG, 112 | fit: BoxFit.fitWidth, 113 | ); 114 | 115 | Widget imageBanner() => new Stack(children: [ 116 | new Image.asset( 117 | Strings.INFO_TAB_IMAGES_PATH_DK_MAIN_GRAPHIC, 118 | fit: BoxFit.fitWidth, 119 | ), 120 | new Image.asset( 121 | Strings.INFO_TAB_IMAGES_PATH_DK_TITLE, 122 | fit: BoxFit.fitWidth, 123 | ), 124 | ]); 125 | 126 | Widget sectionTopPadding() => new Padding(padding: const EdgeInsets.symmetric(vertical: _sectionTopPadding)); 127 | 128 | Widget mainTitle(String title) => new Text( 129 | title, 130 | style: new TextStyle( 131 | fontSize: 24.0, 132 | color: const Color(0xFFFFFFFF), 133 | fontWeight: FontWeight.w600, 134 | height: 1.2, 135 | fontFamily: Strings.FONT_DUNG_GEUN_MO), 136 | ); 137 | 138 | Widget sectionTitle(String title) => new Text(title, style: _titleTextStyle,); 139 | 140 | Widget sectionSubTitle(String title) => new Text(title, style: _subtitleTextStyle,); 141 | 142 | Widget goToHomepage() => 143 | new Container( 144 | margin: const EdgeInsets.symmetric(vertical: 5), 145 | padding: const EdgeInsets.only(bottom: 3), 146 | child: new MaterialButton( 147 | onPressed: () => _launchURL(Strings.INFO_TAB_URL_DROID_KNIGHTS), 148 | color: const Color(0xFF77e448), 149 | child: new Text(Strings.INFO_TAB_MOVE_HOMEPAGE, style: _buttonTextStyle), 150 | ), 151 | ); 152 | 153 | Widget programList() => new SingleChildScrollView( 154 | scrollDirection: Axis.horizontal, 155 | child: new Row( 156 | mainAxisAlignment: MainAxisAlignment.start, 157 | mainAxisSize: MainAxisSize.max, 158 | crossAxisAlignment: CrossAxisAlignment.center, 159 | children: [ 160 | program(Strings.INFO_TAB_TITLE_CODE_LAB, 161 | Strings.INFO_TAB_TITLE_CODE_LAB_CONTENT), 162 | program(Strings.INFO_TAB_TITLE_CODE_REVIEW, 163 | Strings.INFO_TAB_TITLE_CODE_REVIEW_CONTENT), 164 | program(Strings.INFO_TAB_TITLE_LIGHTENING_TALK, 165 | Strings.INFO_TAB_TITLE_LIGHTENING_TALK_CONTENT), 166 | ] 167 | ) 168 | ); 169 | 170 | Widget program(String title, String description) => new Padding( 171 | padding: const EdgeInsets.all(_contentsAllPadding), 172 | child: new Column( 173 | mainAxisAlignment: MainAxisAlignment.start, 174 | mainAxisSize: MainAxisSize.max, 175 | crossAxisAlignment: CrossAxisAlignment.start, 176 | children: [ 177 | new Text( 178 | title, 179 | style: new TextStyle( 180 | fontSize: 13.0, 181 | color: const Color(0xFFededed), 182 | fontWeight: FontWeight.w600, 183 | fontFamily: Strings.FONT_DUNG_GEUN_MO), 184 | ), 185 | new Text( 186 | description, 187 | style: _subtitleTextStyle, 188 | ), 189 | ], 190 | ), 191 | ); 192 | 193 | Widget googleMap() => new Container( 194 | padding: const EdgeInsets.all(_contentsAllPadding), 195 | alignment: Alignment.topLeft, 196 | width: 300.0, 197 | height: 200.0, 198 | child: GoogleMap( 199 | mapType: MapType.normal, 200 | initialCameraPosition: _coexPosition, 201 | onMapCreated: (GoogleMapController controller) { 202 | _controller.complete(controller); 203 | }, 204 | markers: Set.of(markers.values), 205 | ), 206 | ); 207 | 208 | Widget sponsorList() => new SingleChildScrollView( 209 | scrollDirection: Axis.horizontal, 210 | child: new Row( 211 | mainAxisAlignment: MainAxisAlignment.start, 212 | mainAxisSize: MainAxisSize.max, 213 | crossAxisAlignment: CrossAxisAlignment.center, 214 | children: [ 215 | new Row( 216 | mainAxisAlignment: MainAxisAlignment.start, 217 | mainAxisSize: MainAxisSize.max, 218 | crossAxisAlignment: CrossAxisAlignment.start, 219 | children: [ 220 | new Padding( 221 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 222 | child: GestureDetector( 223 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_LINE), 224 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 225 | child: Image.network( 226 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_LINE, 227 | width: 80.0, 228 | height: 80.0, 229 | fit: BoxFit.fitWidth, 230 | ), 231 | ), 232 | ), 233 | new Padding( 234 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 235 | child: GestureDetector( 236 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_PRD), 237 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 238 | child: Image.network( 239 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_PRD, 240 | width: 80.0, 241 | height: 80.0, 242 | fit: BoxFit.fitWidth, 243 | ), 244 | ), 245 | ), 246 | new Padding( 247 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 248 | child: GestureDetector( 249 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_JETBRAINS), 250 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 251 | child: Image.network( 252 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_JETBRAINS, 253 | width: 80.0, 254 | height: 80.0, 255 | fit: BoxFit.fitHeight, 256 | ), 257 | ), 258 | ), 259 | new Padding( 260 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 261 | child: GestureDetector( 262 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_HYPERCONNECT), 263 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 264 | child: Image.network( 265 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_HYPERCONNECT, 266 | width: 80.0, 267 | height: 80.0, 268 | fit: BoxFit.fitWidth, 269 | ), 270 | ), 271 | ), 272 | new Padding( 273 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 274 | child: GestureDetector( 275 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_YANOLJA), 276 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 277 | child: Image.network( 278 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_YANOLJA, 279 | width: 80.0, 280 | height: 80.0, 281 | fit: BoxFit.fitWidth, 282 | ), 283 | ), 284 | ), 285 | new Padding( 286 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 287 | child: GestureDetector( 288 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_RAINIST), 289 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 290 | child: Image.network( 291 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_RAINIST, 292 | width: 80.0, 293 | height: 80.0, 294 | fit: BoxFit.fitWidth, 295 | ), 296 | ), 297 | ), 298 | new Padding( 299 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 300 | child: GestureDetector( 301 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_EBRAIN), 302 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 303 | child: Image.network( 304 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_EBRAIN, 305 | width: 80.0, 306 | height: 80.0, 307 | fit: BoxFit.fitWidth, 308 | ), 309 | ), 310 | ), 311 | new Padding( 312 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 313 | child: GestureDetector( 314 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_LEZHIN), 315 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 316 | child: Image.network( 317 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_LEZHIN, 318 | width: 80.0, 319 | height: 80.0, 320 | fit: BoxFit.fitHeight, 321 | ), 322 | ), 323 | ), 324 | ], 325 | ), 326 | ] 327 | ) 328 | ); 329 | 330 | _launchURL(url) async { 331 | //const url = 'https://flutter.io'; 332 | if (await canLaunch(url)) { 333 | await launch(url); 334 | } else { 335 | throw 'Could not launch $url'; 336 | } 337 | } 338 | } 339 | -------------------------------------------------------------------------------- /lib/pages/info_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:droidknights/res/strings.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/gestures.dart'; 6 | import 'package:flutter/foundation.dart'; 7 | import 'package:google_maps_flutter/google_maps_flutter.dart'; 8 | import 'package:url_launcher/url_launcher.dart'; 9 | class InfoPage extends StatefulWidget { 10 | @override 11 | State createState() => InfoPageState(); 12 | } 13 | 14 | class InfoPageState extends State { 15 | static const double _sectionAllPadding = 20.0; 16 | static const double _sectionTopPadding = 10.0; 17 | static const double _contentsAllPadding = 10.0; 18 | 19 | 20 | Completer _controller = Completer(); 21 | static final CameraPosition _coexPosition = CameraPosition( 22 | target: LatLng(37.513212, 127.058595), 23 | zoom: 14.4746, 24 | ); 25 | 26 | static MarkerId markerId = MarkerId(Strings.INFO_TAB_MAKER); 27 | static Marker marker = Marker( 28 | markerId: markerId, 29 | position: LatLng(37.513212, 127.058595), 30 | infoWindow: InfoWindow(title: Strings.INFO_TAB_MAKER, snippet: Strings.INFO_TAB_SNIPPET), 31 | ); 32 | 33 | Map markers = { 34 | markerId:marker, 35 | }; 36 | 37 | 38 | final TextStyle _titleTextStyle = new TextStyle( 39 | fontSize: 19.0, 40 | color: const Color(0xFF77e448), 41 | fontWeight: FontWeight.w400, 42 | height: 1.3, 43 | fontFamily: Strings.FONT_DUNG_GEUN_MO); 44 | 45 | final TextStyle _subtitleTextStyle = new TextStyle( 46 | fontSize: 13.0, 47 | color: const Color(0xFFededed), 48 | fontWeight: FontWeight.w200, 49 | height: 1.5, 50 | fontFamily: Strings.FONT_DUNG_GEUN_MO); 51 | 52 | final TextStyle _buttonTextStyle = new TextStyle( 53 | fontSize: 15.0, 54 | color: const Color(0xFFededed), 55 | fontWeight: FontWeight.w500, 56 | fontFamily: Strings.FONT_DUNG_GEUN_MO); 57 | 58 | @override 59 | Widget build(BuildContext context) { 60 | return Scaffold( 61 | backgroundColor: const Color(0xFF112030), 62 | body: NestedScrollView( 63 | headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) => [ 64 | SliverAppBar( 65 | backgroundColor: const Color(0xFF112030), 66 | centerTitle: true, 67 | title: Image.asset( 68 | Strings.SCHEDULE_TAB_IMAGES_APP_BAR, 69 | fit: BoxFit.fitHeight, 70 | height: 25, 71 | ), 72 | pinned: true, 73 | floating: true, 74 | expandedHeight: 450, 75 | flexibleSpace: FlexibleSpaceBar( 76 | collapseMode: CollapseMode.parallax, 77 | background: imageBanner(), 78 | ) 79 | ) 80 | ], 81 | body: _contentWidget(), 82 | ), 83 | ); 84 | } 85 | 86 | _contentWidget() { 87 | return Container( 88 | color: const Color(0xFF112030), 89 | child: SingleChildScrollView( 90 | scrollDirection: Axis.vertical, 91 | padding: const EdgeInsets.all(_sectionAllPadding), 92 | child: Column( 93 | mainAxisAlignment: MainAxisAlignment.start, 94 | mainAxisSize: MainAxisSize.max, 95 | crossAxisAlignment: CrossAxisAlignment.start, 96 | children: [ 97 | mainTitle(Strings.INFO_TAB_MAIN_TITLE), 98 | sectionTopPadding(), 99 | sectionTitle(Strings.INFO_TAB_SECTION_TITLE_DROID_KNIGHTS), 100 | sectionSubTitle(Strings.INFO_TAB_SECTION_SUB_TITLE_INTRO), 101 | goToHomepage(), 102 | sectionTopPadding(), 103 | sectionTitle(Strings.INFO_TAB_SECTION_TITLE_PROGRAM), 104 | sectionSubTitle(Strings.INFO_TAB_SECTION_SUB_TITLE_INTRO2), 105 | programList(), 106 | sectionTopPadding(), 107 | sectionTitle(Strings.INFO_TAB_SECTION_TITLE_LOCATION), 108 | sectionSubTitle(Strings.INFO_TAB_SECTION_SUB_TITLE_LOCATION), 109 | googleMap(), 110 | sectionTitle(Strings.INFO_TAB_SECTION_TITLE_SPONSOR), 111 | sponsorList(), 112 | ] 113 | ), 114 | ) 115 | ); 116 | } 117 | 118 | Widget imageBanner() => new Stack(children: [ 119 | new Positioned( 120 | left: 5, 121 | bottom: 30, 122 | right: 5, 123 | child: new Image.asset( 124 | Strings.INFO_TAB_IMAGES_PATH_DK_MAIN_GRAPHIC, 125 | fit: BoxFit.fitWidth, 126 | ), 127 | ), 128 | new Positioned( 129 | left: 5, 130 | top: 150, 131 | right: 5, 132 | child: new Image.asset( 133 | Strings.INFO_TAB_IMAGES_PATH_DK_TITLE, 134 | fit: BoxFit.fitWidth, 135 | ), 136 | ), 137 | ]); 138 | 139 | Widget sectionTopPadding() => new Padding(padding: const EdgeInsets.symmetric(vertical: _sectionTopPadding)); 140 | 141 | Widget mainTitle(String title) => new Text( 142 | title, 143 | style: new TextStyle( 144 | fontSize: 24.0, 145 | color: const Color(0xFFFFFFFF), 146 | fontWeight: FontWeight.w600, 147 | height: 1.2, 148 | fontFamily: Strings.FONT_DUNG_GEUN_MO), 149 | ); 150 | 151 | Widget sectionTitle(String title) => new Text(title, style: _titleTextStyle,); 152 | 153 | Widget sectionSubTitle(String title) => new Text(title, style: _subtitleTextStyle,); 154 | 155 | Widget goToHomepage() => 156 | new Container( 157 | margin: const EdgeInsets.symmetric(vertical: 5), 158 | padding: const EdgeInsets.only(bottom: 3), 159 | child: new MaterialButton( 160 | onPressed: () => _launchURL(Strings.INFO_TAB_URL_DROID_KNIGHTS), 161 | color: const Color(0xFF77e448), 162 | child: new Text(Strings.INFO_TAB_MOVE_HOMEPAGE, style: _buttonTextStyle), 163 | ), 164 | ); 165 | 166 | Widget programList() => new SingleChildScrollView( 167 | scrollDirection: Axis.horizontal, 168 | child: new Row( 169 | mainAxisAlignment: MainAxisAlignment.start, 170 | mainAxisSize: MainAxisSize.max, 171 | crossAxisAlignment: CrossAxisAlignment.center, 172 | children: [ 173 | program(Strings.INFO_TAB_TITLE_CODE_LAB, 174 | Strings.INFO_TAB_TITLE_CODE_LAB_CONTENT), 175 | program(Strings.INFO_TAB_TITLE_CODE_REVIEW, 176 | Strings.INFO_TAB_TITLE_CODE_REVIEW_CONTENT), 177 | program(Strings.INFO_TAB_TITLE_LIGHTENING_TALK, 178 | Strings.INFO_TAB_TITLE_LIGHTENING_TALK_CONTENT), 179 | ] 180 | ) 181 | ); 182 | 183 | Widget program(String title, String description) => new Padding( 184 | padding: const EdgeInsets.all(_contentsAllPadding), 185 | child: new Column( 186 | mainAxisAlignment: MainAxisAlignment.start, 187 | mainAxisSize: MainAxisSize.max, 188 | crossAxisAlignment: CrossAxisAlignment.start, 189 | children: [ 190 | new Text( 191 | title, 192 | style: new TextStyle( 193 | fontSize: 13.0, 194 | color: const Color(0xFFededed), 195 | fontWeight: FontWeight.w600, 196 | fontFamily: Strings.FONT_DUNG_GEUN_MO), 197 | ), 198 | new Text( 199 | description, 200 | style: _subtitleTextStyle, 201 | ), 202 | ], 203 | ), 204 | ); 205 | 206 | Widget googleMap() => new Container( 207 | padding: const EdgeInsets.all(_contentsAllPadding), 208 | alignment: Alignment.topLeft, 209 | width: 300.0, 210 | height: 200.0, 211 | child: GoogleMap( 212 | mapType: MapType.normal, 213 | initialCameraPosition: _coexPosition, 214 | onMapCreated: (GoogleMapController controller) { 215 | _controller.complete(controller); 216 | }, 217 | markers: Set.of(markers.values), 218 | gestureRecognizers: >[ 219 | Factory( 220 | () => EagerGestureRecognizer(), 221 | ), 222 | ].toSet(), 223 | ), 224 | ); 225 | 226 | Widget sponsorList() => new SingleChildScrollView( 227 | scrollDirection: Axis.horizontal, 228 | child: new Row( 229 | mainAxisAlignment: MainAxisAlignment.start, 230 | mainAxisSize: MainAxisSize.max, 231 | crossAxisAlignment: CrossAxisAlignment.center, 232 | children: [ 233 | new Row( 234 | mainAxisAlignment: MainAxisAlignment.start, 235 | mainAxisSize: MainAxisSize.max, 236 | crossAxisAlignment: CrossAxisAlignment.start, 237 | children: [ 238 | new Padding( 239 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 240 | child: GestureDetector( 241 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_LINE), 242 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 243 | child: Image.network( 244 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_LINE, 245 | width: 80.0, 246 | height: 80.0, 247 | fit: BoxFit.fitWidth, 248 | ), 249 | ), 250 | ), 251 | new Padding( 252 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 253 | child: GestureDetector( 254 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_PRD), 255 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 256 | child: Image.network( 257 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_PRD, 258 | width: 80.0, 259 | height: 80.0, 260 | fit: BoxFit.fitWidth, 261 | ), 262 | ), 263 | ), 264 | new Padding( 265 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 266 | child: GestureDetector( 267 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_JETBRAINS), 268 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 269 | child: Image.network( 270 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_JETBRAINS, 271 | width: 80.0, 272 | height: 80.0, 273 | fit: BoxFit.fitHeight, 274 | ), 275 | ), 276 | ), 277 | new Padding( 278 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 279 | child: GestureDetector( 280 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_HYPERCONNECT), 281 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 282 | child: Image.network( 283 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_HYPERCONNECT, 284 | width: 80.0, 285 | height: 80.0, 286 | fit: BoxFit.fitWidth, 287 | ), 288 | ), 289 | ), 290 | new Padding( 291 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 292 | child: GestureDetector( 293 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_YANOLJA), 294 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 295 | child: Image.network( 296 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_YANOLJA, 297 | width: 80.0, 298 | height: 80.0, 299 | fit: BoxFit.fitWidth, 300 | ), 301 | ), 302 | ), 303 | new Padding( 304 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 305 | child: GestureDetector( 306 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_RAINIST), 307 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 308 | child: Image.network( 309 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_RAINIST, 310 | width: 80.0, 311 | height: 80.0, 312 | fit: BoxFit.fitWidth, 313 | ), 314 | ), 315 | ), 316 | new Padding( 317 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 318 | child: GestureDetector( 319 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_EBRAIN), 320 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 321 | child: Image.network( 322 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_EBRAIN, 323 | width: 80.0, 324 | height: 80.0, 325 | fit: BoxFit.fitWidth, 326 | ), 327 | ), 328 | ), 329 | new Padding( 330 | padding: const EdgeInsets.symmetric(horizontal: _contentsAllPadding), 331 | child: GestureDetector( 332 | onTap: () => _launchURL(Strings.INFO_TAB_URL_SPONSOR_LEZHIN), 333 | // child: Text("NO IMAGE", style:_subtitleTextStyle), 334 | child: Image.network( 335 | Strings.INFO_TAB_URL_IMAGE_SPONSOR_LEZHIN, 336 | width: 80.0, 337 | height: 80.0, 338 | fit: BoxFit.fitHeight, 339 | ), 340 | ), 341 | ), 342 | ], 343 | ), 344 | ] 345 | ) 346 | ); 347 | 348 | _launchURL(url) async { 349 | //const url = 'https://flutter.io'; 350 | if (await canLaunch(url)) { 351 | await launch(url); 352 | } else { 353 | throw 'Could not launch $url'; 354 | } 355 | } 356 | } 357 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 18 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 19 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 20 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 21 | AB7C1886884D1B9F37908E56 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A33BAD3E9F397A856AC14BB /* Pods_Runner.framework */; }; 22 | B5E75413224B345500E9C53D /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5E75412224B345500E9C53D /* GoogleService-Info.plist */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXCopyFilesBuildPhase section */ 26 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 27 | isa = PBXCopyFilesBuildPhase; 28 | buildActionMask = 2147483647; 29 | dstPath = ""; 30 | dstSubfolderSpec = 10; 31 | files = ( 32 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 33 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 34 | ); 35 | name = "Embed Frameworks"; 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXCopyFilesBuildPhase section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 42 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 43 | 3A33BAD3E9F397A856AC14BB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 45 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 46 | 5A9DAC16A741A5E6AFB91013 /* 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 = ""; }; 47 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 48 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 49 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 50 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 51 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 52 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 53 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 55 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 56 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 57 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | 9CE61B1B4451443A309A21E4 /* 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 = ""; }; 59 | AD0F2ABDFCE82A04F77DFEEC /* 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 = ""; }; 60 | B5E75412224B345500E9C53D /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = SOURCE_ROOT; }; 61 | /* End PBXFileReference section */ 62 | 63 | /* Begin PBXFrameworksBuildPhase section */ 64 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 65 | isa = PBXFrameworksBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 69 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 70 | AB7C1886884D1B9F37908E56 /* Pods_Runner.framework in Frameworks */, 71 | ); 72 | runOnlyForDeploymentPostprocessing = 0; 73 | }; 74 | /* End PBXFrameworksBuildPhase section */ 75 | 76 | /* Begin PBXGroup section */ 77 | 3F2E6CF55F828CDF2A908CC4 /* Pods */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 5A9DAC16A741A5E6AFB91013 /* Pods-Runner.debug.xcconfig */, 81 | AD0F2ABDFCE82A04F77DFEEC /* Pods-Runner.release.xcconfig */, 82 | 9CE61B1B4451443A309A21E4 /* Pods-Runner.profile.xcconfig */, 83 | ); 84 | path = Pods; 85 | sourceTree = ""; 86 | }; 87 | 9740EEB11CF90186004384FC /* Flutter */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 3B80C3931E831B6300D905FE /* App.framework */, 91 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 92 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 93 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 94 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 95 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 96 | ); 97 | name = Flutter; 98 | sourceTree = ""; 99 | }; 100 | 97C146E51CF9000F007C117D = { 101 | isa = PBXGroup; 102 | children = ( 103 | 9740EEB11CF90186004384FC /* Flutter */, 104 | 97C146F01CF9000F007C117D /* Runner */, 105 | 97C146EF1CF9000F007C117D /* Products */, 106 | 3F2E6CF55F828CDF2A908CC4 /* Pods */, 107 | B143D5916DA23600F49A4896 /* Frameworks */, 108 | ); 109 | sourceTree = ""; 110 | }; 111 | 97C146EF1CF9000F007C117D /* Products */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 97C146EE1CF9000F007C117D /* Runner.app */, 115 | ); 116 | name = Products; 117 | sourceTree = ""; 118 | }; 119 | 97C146F01CF9000F007C117D /* Runner */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | B5E75412224B345500E9C53D /* GoogleService-Info.plist */, 123 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 124 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 125 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 126 | 97C147021CF9000F007C117D /* Info.plist */, 127 | 97C146F11CF9000F007C117D /* Supporting Files */, 128 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 129 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 130 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 131 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 132 | ); 133 | path = Runner; 134 | sourceTree = ""; 135 | }; 136 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | ); 140 | name = "Supporting Files"; 141 | sourceTree = ""; 142 | }; 143 | B143D5916DA23600F49A4896 /* Frameworks */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 3A33BAD3E9F397A856AC14BB /* Pods_Runner.framework */, 147 | ); 148 | name = Frameworks; 149 | sourceTree = ""; 150 | }; 151 | /* End PBXGroup section */ 152 | 153 | /* Begin PBXNativeTarget section */ 154 | 97C146ED1CF9000F007C117D /* Runner */ = { 155 | isa = PBXNativeTarget; 156 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 157 | buildPhases = ( 158 | 9C694C33AFC163DE897630BE /* [CP] Check Pods Manifest.lock */, 159 | 9740EEB61CF901F6004384FC /* Run Script */, 160 | 97C146EA1CF9000F007C117D /* Sources */, 161 | 97C146EB1CF9000F007C117D /* Frameworks */, 162 | 97C146EC1CF9000F007C117D /* Resources */, 163 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 164 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 165 | 4AC965F175658302226B9C9A /* [CP] Embed Pods Frameworks */, 166 | 8D38CA03E8E6AE4E0208D641 /* [CP] Copy Pods Resources */, 167 | ); 168 | buildRules = ( 169 | ); 170 | dependencies = ( 171 | ); 172 | name = Runner; 173 | productName = Runner; 174 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 175 | productType = "com.apple.product-type.application"; 176 | }; 177 | /* End PBXNativeTarget section */ 178 | 179 | /* Begin PBXProject section */ 180 | 97C146E61CF9000F007C117D /* Project object */ = { 181 | isa = PBXProject; 182 | attributes = { 183 | LastUpgradeCheck = 0910; 184 | ORGANIZATIONNAME = "The Chromium Authors"; 185 | TargetAttributes = { 186 | 97C146ED1CF9000F007C117D = { 187 | CreatedOnToolsVersion = 7.3.1; 188 | DevelopmentTeam = 49RADVS8CU; 189 | LastSwiftMigration = 0910; 190 | }; 191 | }; 192 | }; 193 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 194 | compatibilityVersion = "Xcode 3.2"; 195 | developmentRegion = English; 196 | hasScannedForEncodings = 0; 197 | knownRegions = ( 198 | English, 199 | en, 200 | Base, 201 | ); 202 | mainGroup = 97C146E51CF9000F007C117D; 203 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 204 | projectDirPath = ""; 205 | projectRoot = ""; 206 | targets = ( 207 | 97C146ED1CF9000F007C117D /* Runner */, 208 | ); 209 | }; 210 | /* End PBXProject section */ 211 | 212 | /* Begin PBXResourcesBuildPhase section */ 213 | 97C146EC1CF9000F007C117D /* Resources */ = { 214 | isa = PBXResourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 218 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 219 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 220 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 221 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 222 | B5E75413224B345500E9C53D /* GoogleService-Info.plist in Resources */, 223 | ); 224 | runOnlyForDeploymentPostprocessing = 0; 225 | }; 226 | /* End PBXResourcesBuildPhase section */ 227 | 228 | /* Begin PBXShellScriptBuildPhase section */ 229 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 230 | isa = PBXShellScriptBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | ); 234 | inputPaths = ( 235 | ); 236 | name = "Thin Binary"; 237 | outputPaths = ( 238 | ); 239 | runOnlyForDeploymentPostprocessing = 0; 240 | shellPath = /bin/sh; 241 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 242 | }; 243 | 4AC965F175658302226B9C9A /* [CP] Embed Pods Frameworks */ = { 244 | isa = PBXShellScriptBuildPhase; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | ); 248 | inputPaths = ( 249 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", 250 | "${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework", 251 | "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", 252 | "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", 253 | "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", 254 | "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", 255 | "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", 256 | ); 257 | name = "[CP] Embed Pods Frameworks"; 258 | outputPaths = ( 259 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", 260 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", 261 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", 262 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", 263 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", 264 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | shellPath = /bin/sh; 268 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 269 | showEnvVarsInLog = 0; 270 | }; 271 | 8D38CA03E8E6AE4E0208D641 /* [CP] Copy Pods Resources */ = { 272 | isa = PBXShellScriptBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | ); 276 | inputPaths = ( 277 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", 278 | "${PODS_ROOT}/GoogleMaps/Maps/Frameworks/GoogleMaps.framework/Resources/GoogleMaps.bundle", 279 | ); 280 | name = "[CP] Copy Pods Resources"; 281 | outputPaths = ( 282 | "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleMaps.bundle", 283 | ); 284 | runOnlyForDeploymentPostprocessing = 0; 285 | shellPath = /bin/sh; 286 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; 287 | showEnvVarsInLog = 0; 288 | }; 289 | 9740EEB61CF901F6004384FC /* Run Script */ = { 290 | isa = PBXShellScriptBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | ); 294 | inputPaths = ( 295 | ); 296 | name = "Run Script"; 297 | outputPaths = ( 298 | ); 299 | runOnlyForDeploymentPostprocessing = 0; 300 | shellPath = /bin/sh; 301 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 302 | }; 303 | 9C694C33AFC163DE897630BE /* [CP] Check Pods Manifest.lock */ = { 304 | isa = PBXShellScriptBuildPhase; 305 | buildActionMask = 2147483647; 306 | files = ( 307 | ); 308 | inputFileListPaths = ( 309 | ); 310 | inputPaths = ( 311 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 312 | "${PODS_ROOT}/Manifest.lock", 313 | ); 314 | name = "[CP] Check Pods Manifest.lock"; 315 | outputFileListPaths = ( 316 | ); 317 | outputPaths = ( 318 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 319 | ); 320 | runOnlyForDeploymentPostprocessing = 0; 321 | shellPath = /bin/sh; 322 | 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"; 323 | showEnvVarsInLog = 0; 324 | }; 325 | /* End PBXShellScriptBuildPhase section */ 326 | 327 | /* Begin PBXSourcesBuildPhase section */ 328 | 97C146EA1CF9000F007C117D /* Sources */ = { 329 | isa = PBXSourcesBuildPhase; 330 | buildActionMask = 2147483647; 331 | files = ( 332 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 333 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 334 | ); 335 | runOnlyForDeploymentPostprocessing = 0; 336 | }; 337 | /* End PBXSourcesBuildPhase section */ 338 | 339 | /* Begin PBXVariantGroup section */ 340 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 341 | isa = PBXVariantGroup; 342 | children = ( 343 | 97C146FB1CF9000F007C117D /* Base */, 344 | ); 345 | name = Main.storyboard; 346 | sourceTree = ""; 347 | }; 348 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 349 | isa = PBXVariantGroup; 350 | children = ( 351 | 97C147001CF9000F007C117D /* Base */, 352 | ); 353 | name = LaunchScreen.storyboard; 354 | sourceTree = ""; 355 | }; 356 | /* End PBXVariantGroup section */ 357 | 358 | /* Begin XCBuildConfiguration section */ 359 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 360 | isa = XCBuildConfiguration; 361 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 362 | buildSettings = { 363 | ALWAYS_SEARCH_USER_PATHS = NO; 364 | CLANG_ANALYZER_NONNULL = YES; 365 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 366 | CLANG_CXX_LIBRARY = "libc++"; 367 | CLANG_ENABLE_MODULES = YES; 368 | CLANG_ENABLE_OBJC_ARC = YES; 369 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 370 | CLANG_WARN_BOOL_CONVERSION = YES; 371 | CLANG_WARN_COMMA = YES; 372 | CLANG_WARN_CONSTANT_CONVERSION = YES; 373 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 374 | CLANG_WARN_EMPTY_BODY = YES; 375 | CLANG_WARN_ENUM_CONVERSION = YES; 376 | CLANG_WARN_INFINITE_RECURSION = YES; 377 | CLANG_WARN_INT_CONVERSION = YES; 378 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 379 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 380 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 381 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 382 | CLANG_WARN_STRICT_PROTOTYPES = YES; 383 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 384 | CLANG_WARN_UNREACHABLE_CODE = YES; 385 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 386 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 387 | COPY_PHASE_STRIP = NO; 388 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 389 | ENABLE_NS_ASSERTIONS = NO; 390 | ENABLE_STRICT_OBJC_MSGSEND = YES; 391 | GCC_C_LANGUAGE_STANDARD = gnu99; 392 | GCC_NO_COMMON_BLOCKS = YES; 393 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 394 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 395 | GCC_WARN_UNDECLARED_SELECTOR = YES; 396 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 397 | GCC_WARN_UNUSED_FUNCTION = YES; 398 | GCC_WARN_UNUSED_VARIABLE = YES; 399 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 400 | MTL_ENABLE_DEBUG_INFO = NO; 401 | SDKROOT = iphoneos; 402 | TARGETED_DEVICE_FAMILY = "1,2"; 403 | VALIDATE_PRODUCT = YES; 404 | }; 405 | name = Profile; 406 | }; 407 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 408 | isa = XCBuildConfiguration; 409 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 410 | buildSettings = { 411 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 412 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 413 | DEVELOPMENT_TEAM = 49RADVS8CU; 414 | ENABLE_BITCODE = NO; 415 | FRAMEWORK_SEARCH_PATHS = ( 416 | "$(inherited)", 417 | "$(PROJECT_DIR)/Flutter", 418 | ); 419 | INFOPLIST_FILE = Runner/Info.plist; 420 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 421 | LIBRARY_SEARCH_PATHS = ( 422 | "$(inherited)", 423 | "$(PROJECT_DIR)/Flutter", 424 | ); 425 | PRODUCT_BUNDLE_IDENTIFIER = com.droidknights.flutterdroidknights; 426 | PRODUCT_NAME = "$(TARGET_NAME)"; 427 | SWIFT_VERSION = 4.0; 428 | TARGETED_DEVICE_FAMILY = 1; 429 | VERSIONING_SYSTEM = "apple-generic"; 430 | }; 431 | name = Profile; 432 | }; 433 | 97C147031CF9000F007C117D /* Debug */ = { 434 | isa = XCBuildConfiguration; 435 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 436 | buildSettings = { 437 | ALWAYS_SEARCH_USER_PATHS = NO; 438 | CLANG_ANALYZER_NONNULL = YES; 439 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 440 | CLANG_CXX_LIBRARY = "libc++"; 441 | CLANG_ENABLE_MODULES = YES; 442 | CLANG_ENABLE_OBJC_ARC = YES; 443 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 444 | CLANG_WARN_BOOL_CONVERSION = YES; 445 | CLANG_WARN_COMMA = YES; 446 | CLANG_WARN_CONSTANT_CONVERSION = YES; 447 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 448 | CLANG_WARN_EMPTY_BODY = YES; 449 | CLANG_WARN_ENUM_CONVERSION = YES; 450 | CLANG_WARN_INFINITE_RECURSION = YES; 451 | CLANG_WARN_INT_CONVERSION = YES; 452 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 453 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 454 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 455 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 456 | CLANG_WARN_STRICT_PROTOTYPES = YES; 457 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 458 | CLANG_WARN_UNREACHABLE_CODE = YES; 459 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 460 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 461 | COPY_PHASE_STRIP = NO; 462 | DEBUG_INFORMATION_FORMAT = dwarf; 463 | ENABLE_STRICT_OBJC_MSGSEND = YES; 464 | ENABLE_TESTABILITY = YES; 465 | GCC_C_LANGUAGE_STANDARD = gnu99; 466 | GCC_DYNAMIC_NO_PIC = NO; 467 | GCC_NO_COMMON_BLOCKS = YES; 468 | GCC_OPTIMIZATION_LEVEL = 0; 469 | GCC_PREPROCESSOR_DEFINITIONS = ( 470 | "DEBUG=1", 471 | "$(inherited)", 472 | ); 473 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 474 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 475 | GCC_WARN_UNDECLARED_SELECTOR = YES; 476 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 477 | GCC_WARN_UNUSED_FUNCTION = YES; 478 | GCC_WARN_UNUSED_VARIABLE = YES; 479 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 480 | MTL_ENABLE_DEBUG_INFO = YES; 481 | ONLY_ACTIVE_ARCH = YES; 482 | SDKROOT = iphoneos; 483 | TARGETED_DEVICE_FAMILY = "1,2"; 484 | }; 485 | name = Debug; 486 | }; 487 | 97C147041CF9000F007C117D /* Release */ = { 488 | isa = XCBuildConfiguration; 489 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 490 | buildSettings = { 491 | ALWAYS_SEARCH_USER_PATHS = NO; 492 | CLANG_ANALYZER_NONNULL = YES; 493 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 494 | CLANG_CXX_LIBRARY = "libc++"; 495 | CLANG_ENABLE_MODULES = YES; 496 | CLANG_ENABLE_OBJC_ARC = YES; 497 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 498 | CLANG_WARN_BOOL_CONVERSION = YES; 499 | CLANG_WARN_COMMA = YES; 500 | CLANG_WARN_CONSTANT_CONVERSION = YES; 501 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 502 | CLANG_WARN_EMPTY_BODY = YES; 503 | CLANG_WARN_ENUM_CONVERSION = YES; 504 | CLANG_WARN_INFINITE_RECURSION = YES; 505 | CLANG_WARN_INT_CONVERSION = YES; 506 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 507 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 508 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 509 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 510 | CLANG_WARN_STRICT_PROTOTYPES = YES; 511 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 512 | CLANG_WARN_UNREACHABLE_CODE = YES; 513 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 514 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 515 | COPY_PHASE_STRIP = NO; 516 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 517 | ENABLE_NS_ASSERTIONS = NO; 518 | ENABLE_STRICT_OBJC_MSGSEND = YES; 519 | GCC_C_LANGUAGE_STANDARD = gnu99; 520 | GCC_NO_COMMON_BLOCKS = YES; 521 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 522 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 523 | GCC_WARN_UNDECLARED_SELECTOR = YES; 524 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 525 | GCC_WARN_UNUSED_FUNCTION = YES; 526 | GCC_WARN_UNUSED_VARIABLE = YES; 527 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 528 | MTL_ENABLE_DEBUG_INFO = NO; 529 | SDKROOT = iphoneos; 530 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 531 | TARGETED_DEVICE_FAMILY = "1,2"; 532 | VALIDATE_PRODUCT = YES; 533 | }; 534 | name = Release; 535 | }; 536 | 97C147061CF9000F007C117D /* Debug */ = { 537 | isa = XCBuildConfiguration; 538 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 539 | buildSettings = { 540 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 541 | CLANG_ENABLE_MODULES = YES; 542 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 543 | DEVELOPMENT_TEAM = 49RADVS8CU; 544 | ENABLE_BITCODE = NO; 545 | FRAMEWORK_SEARCH_PATHS = ( 546 | "$(inherited)", 547 | "$(PROJECT_DIR)/Flutter", 548 | ); 549 | INFOPLIST_FILE = Runner/Info.plist; 550 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 551 | LIBRARY_SEARCH_PATHS = ( 552 | "$(inherited)", 553 | "$(PROJECT_DIR)/Flutter", 554 | ); 555 | PRODUCT_BUNDLE_IDENTIFIER = com.droidknights.flutterdroidknights; 556 | PRODUCT_NAME = "$(TARGET_NAME)"; 557 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 558 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 559 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 560 | SWIFT_VERSION = 4.0; 561 | TARGETED_DEVICE_FAMILY = 1; 562 | VERSIONING_SYSTEM = "apple-generic"; 563 | }; 564 | name = Debug; 565 | }; 566 | 97C147071CF9000F007C117D /* Release */ = { 567 | isa = XCBuildConfiguration; 568 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 569 | buildSettings = { 570 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 571 | CLANG_ENABLE_MODULES = YES; 572 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 573 | DEVELOPMENT_TEAM = 49RADVS8CU; 574 | ENABLE_BITCODE = NO; 575 | FRAMEWORK_SEARCH_PATHS = ( 576 | "$(inherited)", 577 | "$(PROJECT_DIR)/Flutter", 578 | ); 579 | INFOPLIST_FILE = Runner/Info.plist; 580 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 581 | LIBRARY_SEARCH_PATHS = ( 582 | "$(inherited)", 583 | "$(PROJECT_DIR)/Flutter", 584 | ); 585 | PRODUCT_BUNDLE_IDENTIFIER = com.droidknights.flutterdroidknights; 586 | PRODUCT_NAME = "$(TARGET_NAME)"; 587 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 588 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 589 | SWIFT_VERSION = 4.0; 590 | TARGETED_DEVICE_FAMILY = 1; 591 | VERSIONING_SYSTEM = "apple-generic"; 592 | }; 593 | name = Release; 594 | }; 595 | /* End XCBuildConfiguration section */ 596 | 597 | /* Begin XCConfigurationList section */ 598 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 599 | isa = XCConfigurationList; 600 | buildConfigurations = ( 601 | 97C147031CF9000F007C117D /* Debug */, 602 | 97C147041CF9000F007C117D /* Release */, 603 | 249021D3217E4FDB00AE95B9 /* Profile */, 604 | ); 605 | defaultConfigurationIsVisible = 0; 606 | defaultConfigurationName = Release; 607 | }; 608 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 609 | isa = XCConfigurationList; 610 | buildConfigurations = ( 611 | 97C147061CF9000F007C117D /* Debug */, 612 | 97C147071CF9000F007C117D /* Release */, 613 | 249021D4217E4FDB00AE95B9 /* Profile */, 614 | ); 615 | defaultConfigurationIsVisible = 0; 616 | defaultConfigurationName = Release; 617 | }; 618 | /* End XCConfigurationList section */ 619 | }; 620 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 621 | } 622 | --------------------------------------------------------------------------------