diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..8f5f664
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,63 @@
+name: Build
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+env:
+ FLUTTER_VERSION: "3"
+ JAVA_VERSION: "11"
+
+jobs:
+ build-android:
+ name: Build Android
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up Java
+ uses: actions/setup-java@v3
+ with:
+ distribution: "adopt"
+ java-version: ${{ env.JAVA_VERSION }}
+ - name: Set up Flutter
+ uses: subosito/flutter-action@v2
+ with:
+ flutter-version: ${{ env.FLUTTER_VERSION }}
+ - name: Create .env
+ run: |
+ echo "FRONT_ADDRESS=https://taxi.sparcs.org" > .env
+ echo "BACK_ADDRESS=https://taxi.sparcs.org" >> .env
+ - name: Create key.properties
+ run: |
+ echo "UPLOAD_STORE_FILE=../ci.jks" > android/key.properties
+ echo "UPLOAD_STORE_PASSWORD=123456" >> android/key.properties
+ echo "UPLOAD_KEY_PASSWORD=123456" >> android/key.properties
+ echo "UPLOAD_KEY_ALIAS=ci" >> android/key.properties
+ - name: Create google-services.json
+ run: echo '${{ secrets.GOOGLE_SERVICES_JSON }}' | base64 --decode > android/app/google-services.json
+ - name: Install dependencies
+ run: flutter pub get
+ - name: Build APK
+ run: flutter build apk --release
+
+ build-ios:
+ name: Build iOS
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up Flutter
+ uses: subosito/flutter-action@v2
+ with:
+ flutter-version: ${{ env.FLUTTER_VERSION }}
+ - name: Create .env
+ run: |
+ echo "FRONT_ADDRESS=https://taxi.sparcs.org" > .env
+ echo "BACK_ADDRESS=https://taxi.sparcs.org" >> .env
+ - name: Create GoogleService-Info.plist
+ run: echo '${{ secrets.GOOGLE_SERVICE_INFO_PLIST }}' | base64 --decode > ios/Runner/GoogleService-Info.plist
+ - name: Install dependencies
+ run: flutter pub get
+ - name: Build iOS
+ run: flutter build ios --release --no-codesign
diff --git a/android/.gitignore b/android/.gitignore
index 6f56801..7d27f31 100644
--- a/android/.gitignore
+++ b/android/.gitignore
@@ -11,3 +11,4 @@ GeneratedPluginRegistrant.java
key.properties
**/*.keystore
**/*.jks
+!/ci.jks
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 12a0001..8a76fc3 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,4 +1,4 @@
-
@@ -11,6 +11,11 @@
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/com/example/taxi_app/MainActivity.kt b/android/app/src/main/kotlin/com/example/taxi_app/MainActivity.kt
index bfe5e35..fee0a26 100644
--- a/android/app/src/main/kotlin/com/example/taxi_app/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/example/taxi_app/MainActivity.kt
@@ -22,6 +22,7 @@ class MainActivity: FlutterActivity() {
val intent = Intent.parseUri(call.arguments as String, Intent.URI_INTENT_SCHEME)
if (intent.resolveActivity(packageManager) != null) {
+ packageManager.getLaunchIntentForPackage(""+intent.getPackage())
startActivity(intent)
result.success(null)
} else {
diff --git a/android/app/src/main/res/xml/filepaths.xml b/android/app/src/main/res/xml/filepaths.xml
new file mode 100644
index 0000000..c0f3b31
--- /dev/null
+++ b/android/app/src/main/res/xml/filepaths.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/android/build.gradle b/android/build.gradle
index 88720e4..9f980fc 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,5 +1,5 @@
buildscript {
- ext.kotlin_version = '1.6.10'
+ ext.kotlin_version = '1.9.10'
repositories {
google()
mavenCentral()
diff --git a/android/ci.jks b/android/ci.jks
new file mode 100644
index 0000000..edcba2b
Binary files /dev/null and b/android/ci.jks differ
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index bfcca70..8533716 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -160,7 +160,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1300;
+ LastUpgradeCheck = 1430;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index c87d15a..a6b826d 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
ITSAppUsesNonExemptEncryption
+ FacebookAppID
+ 278480901639073
LSApplicationQueriesSchemes
itms-beta
itms
+ instagram-stories
+ facebook-stories
+ facebook
+ instagram
+ twitter
+ whatsapp
+ tg
+ supertoss
+ uber
+ tmoneyonda
+ kakaotalk
+ kakaot
LSRequiresIPhoneOS
diff --git a/lib/constants/constants.dart b/lib/constants/constants.dart
deleted file mode 100644
index 81b3bf7..0000000
--- a/lib/constants/constants.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-import "package:dio/dio.dart";
-import 'package:flutter_dotenv/flutter_dotenv.dart';
-import 'package:taxiapp/utils/remoteConfigController.dart';
-
-String address = RemoteConfigController().backUrl;
-
-final BaseOptions connectionOptions = BaseOptions(
- baseUrl: address,
- connectTimeout: Duration(seconds: 150),
- receiveTimeout: Duration(seconds: 130),
-);
diff --git a/lib/constants/theme.dart b/lib/constants/theme.dart
new file mode 100644
index 0000000..2870a0e
--- /dev/null
+++ b/lib/constants/theme.dart
@@ -0,0 +1,173 @@
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+//primaryColor 지정 (색상코드: #6E3647)
+final Map primaryColor1 = {
+ 50: const Color.fromRGBO(110, 54, 120, .1),
+ 100: const Color.fromRGBO(110, 54, 120, .2),
+ 200: const Color.fromRGBO(110, 54, 120, .3),
+ 300: const Color.fromRGBO(110, 54, 120, .4),
+ 400: const Color.fromRGBO(110, 54, 120, .5),
+ 500: const Color.fromRGBO(110, 54, 120, .6),
+ 600: const Color.fromRGBO(110, 54, 120, .7),
+ 700: const Color.fromRGBO(110, 54, 120, .8),
+ 800: const Color.fromRGBO(110, 54, 120, .9),
+ 900: const Color.fromRGBO(110, 54, 120, 1),
+};
+final MaterialColor taxiPrimaryMaterialColor =
+ MaterialColor(0xFF6E3678, primaryColor1);
+const Color taxiPrimaryColor = Color(0xFF6E3678);
+const Color taxiMainBackgroundColor = Colors.white;
+const Color toastBackgroundColor = Colors.white;
+const Color toastTextColor = Colors.black;
+const Color notiColor = Color(0x66C8C8C8);
+final Color dialogBarrierColor = Colors.black.withOpacity(0.6);
+
+double devicePixelRatio = 3.0;
+const double taxiDialogPadding = 15.0;
+const double taxiNotificationPadding = 20.0;
+final defaultDialogUpperTitlePadding =
+ Padding(padding: EdgeInsets.symmetric(vertical: 36.0 / devicePixelRatio));
+
+final defaultDialogMedianTitlePadding =
+ Padding(padding: EdgeInsets.all(6 / devicePixelRatio));
+
+final defaultDialogLowerTitlePadding =
+ Padding(padding: EdgeInsets.symmetric(vertical: 24 / devicePixelRatio));
+
+final defaultDialogVerticalMedianButtonPadding = Padding(
+ padding:
+ EdgeInsets.symmetric(horizontal: taxiDialogPadding / devicePixelRatio));
+
+final defaultDialogLowerButtonPadding = Padding(
+ padding:
+ EdgeInsets.only(bottom: (taxiDialogPadding / 2) / devicePixelRatio));
+
+final defaultDialogPadding =
+ Padding(padding: EdgeInsets.all(taxiDialogPadding / devicePixelRatio));
+
+final defaultDialogButtonSize = Size(147.50, 35);
+
+final defaultDialogButtonInnerPadding = EdgeInsets.only(top: 9, bottom: 9);
+
+final defaultDialogButtonBorderRadius = BorderRadius.circular(8.0);
+
+final defaultTaxiMarginDouble = 20.0;
+
+final defaultTaxiMargin =
+ EdgeInsets.symmetric(horizontal: defaultTaxiMarginDouble);
+
+const defaultNotificationButtonSize = Size(90, 25);
+const defaultNotificationButtonInnerPadding =
+ EdgeInsets.symmetric(horizontal: 15.0, vertical: 2.0);
+final defaultNotificationButtonBorderRadius = BorderRadius.circular(30.0);
+final defaultNotificatonOutlinedButtonStyle = OutlinedButton.styleFrom(
+ minimumSize: Size.zero,
+ fixedSize: defaultNotificationButtonSize,
+ padding: defaultNotificationButtonInnerPadding,
+ backgroundColor: taxiPrimaryMaterialColor,
+ shape: RoundedRectangleBorder(
+ borderRadius: defaultNotificationButtonBorderRadius,
+ side: const BorderSide(color: Colors.black),
+ ),
+); // TODO: ThemeData에 있는 OutlinedButtonThemeData 분리
+
+ThemeData taxiTheme() {
+ final base = ThemeData(
+ primarySwatch: taxiPrimaryMaterialColor,
+ primaryColor: const Color(0xFF6E3678),
+
+ //dialog 테마
+ dialogTheme: DialogTheme(
+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
+ backgroundColor: Colors.white,
+ actionsPadding: const EdgeInsets.all(10.0),
+ surfaceTintColor: Colors.black,
+ ),
+ dialogBackgroundColor: Colors.white,
+
+ //dialog 버튼
+ elevatedButtonTheme: ElevatedButtonThemeData(
+ style: ElevatedButton.styleFrom(
+ elevation: 0.5,
+ fixedSize: defaultDialogButtonSize,
+ padding: defaultDialogButtonInnerPadding,
+ backgroundColor: const Color.fromARGB(255, 238, 238, 238),
+ shape: RoundedRectangleBorder(
+ borderRadius: defaultDialogButtonBorderRadius,
+ ),
+ ),
+ ),
+ outlinedButtonTheme: OutlinedButtonThemeData(
+ style: OutlinedButton.styleFrom(
+ fixedSize: defaultDialogButtonSize,
+ padding: defaultDialogButtonInnerPadding,
+ backgroundColor: taxiPrimaryMaterialColor,
+ shape: RoundedRectangleBorder(
+ borderRadius: defaultDialogButtonBorderRadius,
+ side: const BorderSide(color: Colors.black),
+ ),
+ ),
+ ),
+ bannerTheme: MaterialBannerThemeData(
+ backgroundColor: Colors.white,
+ ),
+
+ //텍스트 테마
+ textTheme: const TextTheme(
+ //Dialog 제목
+ titleSmall: TextStyle(
+ fontFamily: 'NanumSquare',
+ color: Color(0xFF323232),
+ fontSize: 16,
+ fontWeight: FontWeight.w400),
+
+ //Dialog 상세 설명
+ bodySmall: TextStyle(
+ fontFamily: 'NanumSquare_acB',
+ color: Color(0xFF888888),
+ fontSize: 10,
+ fontWeight: FontWeight.w700),
+
+ //Dialog Outlined 버튼 텍스트
+ labelLarge: TextStyle(
+ fontFamily: 'NanumSquare_acB',
+ color: Color(0xFFEEEEEE),
+ fontSize: 14,
+ fontWeight: FontWeight.w700),
+
+ //Dialog Elevated 버튼 텍스트
+ labelMedium: TextStyle(
+ fontFamily: 'NanumSquare',
+ color: Color.fromARGB(255, 129, 129, 129),
+ fontSize: 14,
+ fontWeight: FontWeight.w400),
+ labelSmall: TextStyle(
+ color: Color(0xFFEEEEEE),
+ fontFamily: 'NanumSquare_acB',
+ fontSize: 12,
+ fontWeight: FontWeight.w700,
+ letterSpacing: 0.4,
+ ),
+ ),
+
+ bottomNavigationBarTheme: BottomNavigationBarThemeData(
+ type: BottomNavigationBarType.fixed,
+ backgroundColor: Colors.white,
+ selectedItemColor: Color(0xFF6E3678),
+ selectedLabelStyle: TextStyle(
+ fontFamily: 'NanumSquare',
+ fontSize: 12,
+ fontWeight: FontWeight.w700,
+ letterSpacing: 0.4,
+ ),
+ unselectedLabelStyle: TextStyle(
+ fontFamily: 'NanumSquare',
+ fontSize: 12,
+ fontWeight: FontWeight.w700,
+ letterSpacing: 0.4,
+ ),
+ ),
+ );
+ return base;
+}
diff --git a/lib/main.dart b/lib/main.dart
index f408d7c..40b3bd9 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -14,6 +14,7 @@ import 'package:taxiapp/utils/token.dart';
import 'package:taxiapp/views/taxiView.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:taxiapp/firebase_options.dart';
+import 'constants/theme.dart';
late AndroidNotificationChannel channel;
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
@@ -82,13 +83,11 @@ class MyHome extends HookWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Taxi App',
- theme: ThemeData(
- primarySwatch: Colors.blue,
- ),
+ theme: taxiTheme(),
home: Container(
- color: const Color(0xFF6E3647),
+ color: Theme.of(context).primaryColor,
child: Container(
- color: Colors.white,
+ color: taxiMainBackgroundColor,
child: TaxiView(),
),
),
diff --git a/lib/utils/fcmToken.dart b/lib/utils/fcmToken.dart
index c591753..dbedeb6 100644
--- a/lib/utils/fcmToken.dart
+++ b/lib/utils/fcmToken.dart
@@ -1,13 +1,13 @@
import "package:dio/dio.dart";
import 'package:firebase_messaging/firebase_messaging.dart';
-import 'package:taxiapp/constants/constants.dart';
+import 'package:taxiapp/utils/remoteConfigController.dart';
class FcmToken {
String token;
static FcmToken? _instance;
- final Dio _dio = Dio(connectionOptions);
+ final Dio _dio = Dio();
FcmToken._internal({required this.token});
@@ -21,6 +21,15 @@ class FcmToken {
Future init() async {
final token = await FirebaseMessaging.instance.getToken();
+ _dio.interceptors
+ .add(InterceptorsWrapper(onRequest: (options, handler) async {
+ options.headers["Origin"] = options.uri.origin;
+ return handler.next(options);
+ }, onResponse: (response, handler) async {
+ return handler.next(response);
+ }, onError: (error, handler) async {
+ return handler.next(error);
+ }));
if (token == null) {
this.token = '';
@@ -32,6 +41,7 @@ class FcmToken {
String get fcmToken => token;
Future registerToken(String accessToken) async {
+ _dio.options.baseUrl = RemoteConfigController().backUrl;
return _dio.post("auth/app/device", data: {
"accessToken": accessToken,
"deviceToken": token,
@@ -43,6 +53,7 @@ class FcmToken {
}
Future removeToken(String accessToken) async {
+ _dio.options.baseUrl = RemoteConfigController().backUrl;
return _dio.delete("auth/app/device", data: {
"accessToken": accessToken,
"deviceToken": token,
diff --git a/lib/utils/pushHandler.dart b/lib/utils/pushHandler.dart
index bb8c0ae..f92094f 100644
--- a/lib/utils/pushHandler.dart
+++ b/lib/utils/pushHandler.dart
@@ -33,11 +33,9 @@ Future handleMessage(RemoteMessage message) async {
var details =
NotificationDetails(android: androidNotiDetails, iOS: iOSNotiDetails);
- if (message.data != null) {
- flutterLocalNotificationsPlugin.show(Random().nextInt(100000000),
- message.data['title'], message.data['body'], details,
- payload: message.data['url']);
- }
+ flutterLocalNotificationsPlugin.show(Random().nextInt(100000000),
+ message.data['title'], message.data['body'], details,
+ payload: message.data['url']);
}
Future _getByteArrayFromUrl(String url) async {
diff --git a/lib/utils/remoteConfigController.dart b/lib/utils/remoteConfigController.dart
index 2754eab..ade4ee4 100644
--- a/lib/utils/remoteConfigController.dart
+++ b/lib/utils/remoteConfigController.dart
@@ -1,13 +1,11 @@
-import "package:dio/dio.dart";
-import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:package_info/package_info.dart';
class RemoteConfigController {
String backUrl;
String frontUrl;
- String ios_version;
- String android_version;
+ String iosVersion;
+ String androidVersion;
static RemoteConfigController? _instance;
@@ -16,34 +14,28 @@ class RemoteConfigController {
RemoteConfigController._internal(
{required this.backUrl,
required this.frontUrl,
- required this.ios_version,
- required this.android_version});
+ required this.iosVersion,
+ required this.androidVersion});
factory RemoteConfigController(
{String? backUrl,
String? frontUrl,
- String? ios_version,
- String? android_version}) {
+ String? iosVersion,
+ String? androidVersion}) {
if (frontUrl == null ||
backUrl == null ||
- ios_version == null ||
- android_version == null) {
+ iosVersion == null ||
+ androidVersion == null) {
return _instance ??= RemoteConfigController._internal(
- backUrl: 'https://taxi.sparcs.org/api/',
- frontUrl: 'https://taxi.sparcs.org',
- ios_version: '',
- android_version: '');
+ backUrl: '', frontUrl: '', iosVersion: '', androidVersion: '');
}
_instance = RemoteConfigController._internal(
backUrl: backUrl,
frontUrl: frontUrl,
- ios_version: ios_version,
- android_version: android_version);
+ iosVersion: iosVersion,
+ androidVersion: androidVersion);
return _instance ??= RemoteConfigController._internal(
- backUrl: 'https://taxi.sparcs.org/api/',
- frontUrl: 'https://taxi.sparcs.org',
- ios_version: '',
- android_version: '');
+ backUrl: '', frontUrl: '', iosVersion: '', androidVersion: '');
}
Future init() async {
@@ -55,7 +47,7 @@ class RemoteConfigController {
));
await remoteConfig.setDefaults({
"back_url": "https://taxi.sparcs.org/api/",
- "front_url": "https://taxi.sparcs.org",
+ "front_url": "https://taxi.sparcs.org/",
"version": value.version,
"ios_version": value.version,
});
@@ -64,8 +56,8 @@ class RemoteConfigController {
this.backUrl = remoteConfig.getString("back_url");
this.frontUrl = remoteConfig.getString("front_url");
- this.android_version = remoteConfig.getString("version");
- this.ios_version = remoteConfig.getString("ios_version");
+ this.androidVersion = remoteConfig.getString("version");
+ this.iosVersion = remoteConfig.getString("ios_version");
return;
}
diff --git a/lib/utils/token.dart b/lib/utils/token.dart
index c58c12b..31e5b1a 100644
--- a/lib/utils/token.dart
+++ b/lib/utils/token.dart
@@ -1,11 +1,11 @@
import 'dart:io';
import "package:dio/dio.dart";
-import 'package:taxiapp/constants/constants.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:taxiapp/utils/fcmToken.dart';
+import 'package:taxiapp/utils/remoteConfigController.dart';
class Token {
String accessToken;
@@ -13,7 +13,7 @@ class Token {
static Token? _instance;
static final _storage = FlutterSecureStorage();
- final Dio _dio = Dio(connectionOptions);
+ final Dio _dio = Dio();
final CookieJar _cookieJar = CookieJar();
Token._internal({required this.accessToken, required this.refreshToken});
@@ -30,6 +30,16 @@ class Token {
Future init() async {
accessToken = (await getAccessTokenFromStorage()) ?? '';
refreshToken = (await getRefreshTokenFromStorage()) ?? '';
+ _dio.interceptors.add(CookieManager(_cookieJar));
+ _dio.interceptors
+ .add(InterceptorsWrapper(onRequest: (options, handler) async {
+ options.headers["Origin"] = options.uri.origin;
+ return handler.next(options);
+ }, onResponse: (response, handler) async {
+ return handler.next(response);
+ }, onError: (error, handler) async {
+ return handler.next(error);
+ }));
}
Future setAccessToken({required String accessToken}) async {
@@ -56,6 +66,7 @@ class Token {
}
Future getSession() async {
+ _dio.options.baseUrl = RemoteConfigController().backUrl;
_dio.interceptors.add(CookieManager(_cookieJar));
return _dio.get("/auth/app/token/login", queryParameters: {
"accessToken": accessToken,
@@ -74,8 +85,8 @@ class Token {
return null;
}
if (response.statusCode == 200) {
- List cookies = await _cookieJar.loadForRequest(
- Uri.parse(connectionOptions.baseUrl + "auth/app/token/login"));
+ List cookies = await _cookieJar.loadForRequest(Uri.parse(
+ RemoteConfigController().backUrl + "auth/app/token/login"));
for (Cookie cookie in cookies) {
if (cookie.name == "connect.sid") {
return cookie.value;
@@ -90,6 +101,7 @@ class Token {
}
Future updateAccessTokenUsingRefreshToken() {
+ _dio.options.baseUrl = RemoteConfigController().backUrl;
return _dio.get("/auth/app/token/refresh", queryParameters: {
"accessToken": accessToken,
"refreshToken": refreshToken,
diff --git a/lib/views/taxiDialog.dart b/lib/views/taxiDialog.dart
index 5d91e70..2f7aa70 100644
--- a/lib/views/taxiDialog.dart
+++ b/lib/views/taxiDialog.dart
@@ -2,91 +2,85 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
-import 'package:google_fonts/google_fonts.dart';
import 'package:open_store/open_store.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
+import 'package:taxiapp/constants/theme.dart';
class TaxiDialog extends StatelessWidget {
- late Set boxContent;
+ late Set boxMainContent;
+ late Set boxSecondaryContent;
late String leftButtonContent;
late String rightButtonContent;
TaxiDialog(
{super.key,
- required this.boxContent,
+ required this.boxMainContent,
+ required this.boxSecondaryContent,
required this.leftButtonContent,
required this.rightButtonContent});
@override
Widget build(BuildContext context) {
return Container(
- width: 350,
- height: 165,
- decoration: BoxDecoration(
- color: Colors.white, borderRadius: BorderRadius.circular(15)),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- const Padding(padding: EdgeInsets.all(15)),
- ...boxContent,
- const Padding(
- padding: EdgeInsets.all(15),
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- ElevatedButton(
- style: ElevatedButton.styleFrom(
- elevation: 0.5,
- fixedSize: const Size(150, 45),
- backgroundColor: const Color(0xFFFAF8FB),
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(12.0),
- side: const BorderSide(color: Colors.white),
- ),
- ),
- child: Text(leftButtonContent,
- style: GoogleFonts.roboto(
- textStyle: const TextStyle(
- color: Color(0xFFC8C8C8),
- fontSize: 13,
- fontWeight: FontWeight.normal))),
- onPressed: () async {
- if (Platform.isIOS) {
- exit(0);
- } else {
- SystemNavigator.pop();
- }
- }),
- const Padding(
- padding: EdgeInsets.all(10),
- ),
- OutlinedButton(
- style: ButtonStyle(
- fixedSize: MaterialStateProperty.all(const Size(150, 45)),
- backgroundColor: MaterialStateProperty.all(
- const Color(0xFF6E3678)),
- shape: MaterialStateProperty.all(
- RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(12.0),
- side: const BorderSide(color: Colors.black),
+ height: double.infinity,
+ width: double.infinity,
+ color: dialogBarrierColor,
+ child: Dialog(
+ alignment: Alignment.center,
+ backgroundColor: Theme.of(context).dialogBackgroundColor,
+ shape: Theme.of(context).dialogTheme.shape,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ mainAxisAlignment: MainAxisAlignment.center,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ defaultDialogUpperTitlePadding,
+ ...boxMainContent,
+ defaultDialogMedianTitlePadding,
+ ...boxSecondaryContent,
+ defaultDialogLowerTitlePadding,
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ mainAxisAlignment: MainAxisAlignment.center,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ defaultDialogPadding,
+ Expanded(
+ child: ElevatedButton(
+ style: Theme.of(context).elevatedButtonTheme.style,
+ child: Text(
+ leftButtonContent,
+ style: Theme.of(context).textTheme.labelMedium,
+ overflow: TextOverflow.visible,
),
- ),
- ),
- child: Text(rightButtonContent,
- style: GoogleFonts.roboto(
- textStyle: const TextStyle(
- color: Color(0xFFEEEEEE),
- fontSize: 13,
- fontWeight: FontWeight.bold))),
- onPressed: () async {
- OpenStore.instance.open(
- androidAppBundleId: dotenv.get("ANDROID_APPID"),
- appStoreId: dotenv.get("IOS_APPID"));
- }),
- ],
- )
- ]),
+ onPressed: () async {
+ if (Platform.isIOS) {
+ exit(0);
+ } else {
+ SystemNavigator.pop();
+ }
+ }),
+ ),
+ defaultDialogVerticalMedianButtonPadding,
+ Expanded(
+ child: OutlinedButton(
+ style: Theme.of(context).outlinedButtonTheme.style,
+ child: Text(
+ rightButtonContent,
+ style: Theme.of(context).textTheme.labelLarge,
+ overflow: TextOverflow.visible,
+ ),
+ onPressed: () async {
+ OpenStore.instance.open(
+ androidAppBundleId: dotenv.get("ANDROID_APPID"),
+ appStoreId: dotenv.get("IOS_APPID"));
+ }),
+ ),
+ defaultDialogPadding,
+ ],
+ ),
+ defaultDialogLowerButtonPadding
+ ]),
+ ),
);
}
}
diff --git a/lib/views/taxiView.dart b/lib/views/taxiView.dart
index 0af51c2..03661f9 100644
--- a/lib/views/taxiView.dart
+++ b/lib/views/taxiView.dart
@@ -1,16 +1,18 @@
import 'dart:async';
import 'dart:io';
+import 'package:dio/dio.dart';
import 'package:firebase_dynamic_links/firebase_dynamic_links.dart';
-import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
-import 'package:flutter_dotenv/flutter_dotenv.dart';
-import 'package:google_fonts/google_fonts.dart';
import 'package:package_info/package_info.dart';
+import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
+import 'package:social_share/social_share.dart';
+import 'package:taxiapp/constants/theme.dart';
import 'package:taxiapp/utils/fcmToken.dart';
import 'package:taxiapp/utils/pushHandler.dart';
import 'package:taxiapp/utils/remoteConfigController.dart';
@@ -21,17 +23,27 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:taxiapp/views/taxiDialog.dart';
import 'package:app_links/app_links.dart';
+import 'package:taxiapp/constants/theme.dart';
+import 'dart:math';
+import 'package:url_launcher/url_launcher_string.dart';
+import 'package:open_store/open_store.dart';
class TaxiView extends HookWidget {
final CookieManager _cookieManager = CookieManager.instance();
// late InAppWebViewController _controller;
-
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
@override
Widget build(BuildContext context) {
String address = RemoteConfigController().frontUrl;
+ OverlayEntry? overlayEntry;
+ AnimationController _aniController =
+ useAnimationController(duration: const Duration(milliseconds: 300));
+ Animation _animation =
+ Tween(begin: const Offset(0, -0.5), end: const Offset(0.0, 0)).animate(
+ CurvedAnimation(parent: _aniController, curve: Curves.decelerate));
+ bool isBannerShow = false;
// States
// 로딩 여부 확인
@@ -61,6 +73,8 @@ class TaxiView extends HookWidget {
// FCM init 여부 확인
final isFcmInit = useState(false);
+ devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
+
useEffect(() {
if (isTimerUp.value) {
FcmToken().init().then((value) {
@@ -207,13 +221,13 @@ class TaxiView extends HookWidget {
try {
if (Platform.isIOS) {
if (int.parse(
- RemoteConfigController().ios_version.replaceAll(".", "")) >
+ RemoteConfigController().iosVersion.replaceAll(".", "")) >
int.parse(value.version.replaceAll(".", ""))) {
isMustUpdate.value = true;
}
} else {
if (int.parse(RemoteConfigController()
- .android_version
+ .androidVersion
.replaceAll(".", "")) >
int.parse(value.version.replaceAll(".", ""))) {
isMustUpdate.value = true;
@@ -222,9 +236,9 @@ class TaxiView extends HookWidget {
} catch (e) {
Fluttertoast.showToast(
msg: "버전 체크에 실패했습니다. " + e.toString(),
- backgroundColor: Colors.white,
+ backgroundColor: toastBackgroundColor,
toastLength: Toast.LENGTH_SHORT,
- textColor: Colors.black,
+ textColor: toastTextColor,
);
}
});
@@ -238,8 +252,11 @@ class TaxiView extends HookWidget {
if (Token().accessToken != '') {
await Token().deleteAll();
}
- isLogin.value = false;
+ await _cookieManager.deleteCookie(
+ url: Uri.parse(RemoteConfigController().backUrl),
+ name: "connect.sid");
isAuthLogin.value = false;
+ isLogin.value = false;
isFirstLogin.value = false;
LoadCount.value += 1;
} else {
@@ -255,12 +272,11 @@ class TaxiView extends HookWidget {
LoadCount.value += 1;
}
} catch (e) {
- print(e);
Fluttertoast.showToast(
msg: "로그인에 실패했습니다.",
- backgroundColor: Colors.white,
+ backgroundColor: toastBackgroundColor,
toastLength: Toast.LENGTH_SHORT,
- textColor: Colors.black,
+ textColor: toastTextColor,
);
}
}
@@ -269,6 +285,156 @@ class TaxiView extends HookWidget {
return;
}, [isAuthLogin.value, isFcmInit.value]);
+ void removeOverlayNotification({required Uri? uri}) {
+ if (uri != Uri.parse("")) {
+ url.value = uri.toString();
+ LoadCount.value += 1;
+ }
+ overlayEntry?.remove();
+ overlayEntry = null;
+ }
+
+ void removeAnimation() {
+ _aniController.reverse(); //TODO: 일정 dy 미만시 배너 삭제 취소 및 애니메이션 다시 재생
+ isBannerShow = false;
+ // removeOverlayNotification();
+ }
+
+ void createOverlayNotification(
+ {required String title,
+ required String subTitle,
+ required String content,
+ required Map button,
+ Uri? imageUrl}) {
+ print("asd");
+ if (overlayEntry != null) {
+ removeOverlayNotification(uri: Uri.parse(""));
+ }
+ assert(overlayEntry == null);
+ isBannerShow = true;
+
+ overlayEntry = OverlayEntry(builder: (BuildContext context) {
+ _aniController.reset();
+ _animation =
+ Tween(begin: const Offset(0, -0.5), end: const Offset(0, 0))
+ .animate(CurvedAnimation(
+ parent: _aniController, curve: Curves.decelerate));
+ _aniController.forward();
+
+ return SlideTransition(
+ position: _animation,
+ child: GestureDetector(
+ onPanUpdate: (details) {
+ if (details.delta.dy < -1 && isBannerShow) {
+ removeAnimation();
+ }
+ },
+ onPanEnd: (details) {
+ if (!isBannerShow) {
+ removeOverlayNotification(uri: button.values.first);
+ }
+ },
+ child: UnconstrainedBox(
+ alignment: Alignment.topCenter,
+ child: Container(
+ width: MediaQuery.of(context).size.width,
+ height: min(MediaQuery.of(context).size.height * 0.15, 200),
+ margin:
+ EdgeInsets.only(top: MediaQuery.of(context).padding.top),
+ color: Colors.white,
+ child: Stack(
+ children: [
+ Container(
+ alignment: Alignment.topCenter,
+ height: 5.0,
+ color: taxiPrimaryColor,
+ ),
+ Positioned(
+ left: 20,
+ top: 25,
+ child: (imageUrl != Uri.parse(""))
+ ? Image(
+ image: NetworkImage(imageUrl.toString()),
+ width: 40,
+ height: 40,
+ fit: BoxFit.cover,
+ )
+ : const Padding(padding: EdgeInsets.zero)),
+ Positioned(
+ left: 20 +
+ ((imageUrl != Uri.parse(""))
+ ? 60
+ : 0), // 이미지 없을 시 마진 20으로 변경
+ top: 25,
+ child: Text.rich(
+ TextSpan(
+ children: [
+ TextSpan(
+ text: title,
+ style: Theme.of(context)
+ .textTheme
+ .bodySmall!
+ .copyWith(
+ fontSize: 12,
+ ),
+ ),
+ TextSpan(
+ text:
+ (subTitle.isNotEmpty) ? " / $subTitle" : "",
+ style: Theme.of(context)
+ .textTheme
+ .bodySmall!
+ .copyWith(
+ fontSize: 12,
+ fontWeight: FontWeight.w400)),
+ ],
+ ),
+ ),
+ ),
+ Positioned(
+ left: 20 + ((imageUrl != Uri.parse("")) ? 60 : 0),
+ top: 40,
+ child: Text(
+ content,
+ overflow: TextOverflow.ellipsis,
+ style: Theme.of(context).textTheme.bodySmall!.copyWith(
+ color: Colors.black,
+ fontSize: 14,
+ fontWeight: FontWeight.w400,
+ letterSpacing: 0.4),
+ ),
+ ),
+ Positioned(
+ bottom: 20 / devicePixelRatio,
+ right: 25 / devicePixelRatio,
+ child: OutlinedButton(
+ style: defaultNotificatonOutlinedButtonStyle,
+ child: Text(
+ button.keys.first,
+ style: Theme.of(context)
+ .textTheme
+ .labelSmall!
+ .copyWith(fontSize: 14),
+ ),
+ onPressed: () {
+ removeAnimation();
+ Future.delayed(const Duration(milliseconds: 300),
+ () {
+ removeOverlayNotification(
+ uri: button.values.first);
+ });
+ }),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ );
+ });
+ Overlay.of(context).insert(overlayEntry!);
+ }
+
return SafeArea(
child: Stack(children: [
WillPopScope(
@@ -279,12 +445,46 @@ class TaxiView extends HookWidget {
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
- resourceCustomSchemes: ['intent']),
+ applicationNameForUserAgent: "taxi-app-webview/" +
+ (Platform.isAndroid ? "android" : "ios"),
+ resourceCustomSchemes: [
+ 'intent',
+ 'supertoss',
+ 'uber',
+ 'tmoneyonda',
+ 'kakaotalk',
+ 'kakaot'
+ ]),
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
overScrollMode:
- AndroidOverScrollMode.OVER_SCROLL_NEVER)),
+ AndroidOverScrollMode.OVER_SCROLL_NEVER),
+ ios: IOSInAppWebViewOptions(disallowOverScroll: true)),
// initialUrlRequest: URLRequest(url: Uri.parse(address)),
+ shouldOverrideUrlLoading: (controller, navigationAction) async {
+ var newHeaders = Map.from(
+ navigationAction.request.headers ?? {});
+ if (Platform.isAndroid &&
+ !newHeaders.containsKey("Referer") &&
+ navigationAction.request.url.toString() !=
+ 'about:blank' &&
+ (navigationAction.request.url?.origin ==
+ Uri.parse(address).origin ||
+ navigationAction.request.url?.origin ==
+ Uri.parse(RemoteConfigController().backUrl)
+ .origin)) {
+ newHeaders['Referer'] =
+ navigationAction.request.url.toString();
+ newHeaders['Origin'] = RemoteConfigController().frontUrl;
+ var newRequest = navigationAction.request;
+ newRequest.headers = newHeaders;
+ await controller.loadUrl(urlRequest: newRequest);
+
+ return NavigationActionPolicy.CANCEL;
+ }
+
+ return NavigationActionPolicy.ALLOW;
+ },
onWebViewCreated: (InAppWebViewController webcontroller) async {
_controller.value = webcontroller;
_controller.value?.addJavaScriptHandler(
@@ -297,14 +497,17 @@ class TaxiView extends HookWidget {
}
// 로그인 성공 시 / 기존 토큰 삭제 후 새로운 토큰 저장
if (!isAuthLogin.value) {
- print("IS AUTH 변경됨");
- await Token().setAccessToken(
- accessToken: arguments[0]['accessToken']);
- await Token().setRefreshToken(
- refreshToken: arguments[0]['refreshToken']);
- await FcmToken()
- .registerToken(arguments[0]['accessToken']);
- isAuthLogin.value = true;
+ if (arguments[0]['accessToken'] != null &&
+ arguments[0]['refreshToken'] != null) {
+ await Token().deleteAll();
+ await Token().setAccessToken(
+ accessToken: arguments[0]['accessToken']);
+ await Token().setRefreshToken(
+ refreshToken: arguments[0]['refreshToken']);
+ await FcmToken()
+ .registerToken(arguments[0]['accessToken']);
+ isAuthLogin.value = true;
+ }
}
return;
},
@@ -317,18 +520,21 @@ class TaxiView extends HookWidget {
await FcmToken()
.removeToken(Token().getAccessToken());
await Token().deleteAll();
+ await _cookieManager.deleteAllCookies();
isLogin.value = false;
isAuthLogin.value = false;
- await _cookieManager.deleteAllCookies();
- await _controller.value!.loadUrl(
- urlRequest: URLRequest(url: Uri.parse(address)));
+ await _controller.value?.loadUrl(
+ urlRequest: URLRequest(
+ url: Uri.parse(RemoteConfigController()
+ .frontUrl
+ .toString())));
} catch (e) {
// TODO
Fluttertoast.showToast(
msg: "서버와의 연결에 실패했습니다.",
toastLength: Toast.LENGTH_SHORT,
- textColor: Colors.black,
- backgroundColor: Colors.white);
+ textColor: toastTextColor,
+ backgroundColor: toastBackgroundColor);
isAuthLogin.value = false;
}
});
@@ -343,8 +549,8 @@ class TaxiView extends HookWidget {
Fluttertoast.showToast(
msg: "알림 권한을 허용해주세요.",
toastLength: Toast.LENGTH_SHORT,
- textColor: Colors.black,
- backgroundColor: Colors.white);
+ textColor: toastTextColor,
+ backgroundColor: toastBackgroundColor);
return false;
}
});
@@ -356,6 +562,69 @@ class TaxiView extends HookWidget {
await Clipboard.setData(ClipboardData(text: args[0]));
}
});
+
+ // Web -> App
+ _controller.value?.addJavaScriptHandler(
+ handlerName: "popup_inAppNotification",
+ callback: (args) async {
+ createOverlayNotification(
+ title: args[0]['title'].toString(),
+ subTitle: args[0]['subtitle'].toString(),
+ content: args[0]['content'].toString(),
+ button: {
+ args[0]['button']['text'].toString():
+ (args[0]['button']['path'].toString() != "")
+ ? Uri.parse(
+ args[0]['button']['path'].toString())
+ : Uri.parse("")
+ },
+ imageUrl: (args[0]['type'].toString() ==
+ "default") //TODO: type showMaterialBanner 함수에서 관리
+ ? Uri.parse(args[0]['imageUrl'].toString())
+ : Uri.parse(""));
+ });
+
+ _controller.value?.addJavaScriptHandler(
+ handlerName: "popup_instagram_story_share",
+ callback: (args) async {
+ if (args[0] == {}) {
+ return;
+ }
+ print(args);
+ try {
+ final Dio _dio = Dio();
+ final backgroundResponse = await _dio.get(
+ args[0]['backgroundLayerUrl'],
+ options:
+ Options(responseType: ResponseType.bytes));
+ final stickerResponse = await _dio.get(
+ args[0]['stickerLayerUrl'],
+ options:
+ Options(responseType: ResponseType.bytes));
+ final backgroundFile = await File(
+ (await getTemporaryDirectory()).path +
+ "/background.png")
+ .create(recursive: true);
+ final stickerFile = await File(
+ (await getTemporaryDirectory()).path +
+ "/sticker.png")
+ .create(recursive: true);
+ await backgroundFile
+ .writeAsBytes(backgroundResponse.data);
+ await stickerFile.writeAsBytes(stickerResponse.data);
+
+ await SocialShare.shareInstagramStory(
+ appId: dotenv.get("FACEBOOK_APPID"),
+ imagePath: stickerFile.path,
+ backgroundResourcePath: backgroundFile.path);
+ } catch (e) {
+ Fluttertoast.showToast(
+ msg: "인스타그램 스토리 공유에 실패했습니다.",
+ toastLength: Toast.LENGTH_SHORT,
+ textColor: toastTextColor,
+ backgroundColor: toastBackgroundColor);
+ }
+ });
},
onLoadStart: (controller, uri) async {
if (isFcmInit.value &&
@@ -363,60 +632,77 @@ class TaxiView extends HookWidget {
sessionToken.value != '' &&
uri?.origin == Uri.parse(address).origin &&
(await _cookieManager.getCookie(
- url: Uri.parse(address), name: "connect.sid"))
+ url: Uri.parse(
+ RemoteConfigController().backUrl),
+ name: "connect.sid"))
?.value !=
sessionToken.value) {
try {
await _controller.value?.stopLoading();
await _cookieManager.deleteCookie(
- url: Uri.parse(address), name: "connect.sid");
+ url: Uri.parse(RemoteConfigController().backUrl),
+ name: "connect.sid");
await _cookieManager.setCookie(
- url: Uri.parse(address),
+ url: Uri.parse(RemoteConfigController().backUrl),
name: "connect.sid",
value: sessionToken.value,
);
- await _cookieManager.setCookie(
- url: Uri.parse(address),
- name: "deviceToken",
- value: FcmToken().fcmToken,
- );
await _controller.value?.reload();
} catch (e) {
// TODO : handle error
Fluttertoast.showToast(
msg: "서버와의 연결에 실패했습니다.",
toastLength: Toast.LENGTH_SHORT,
- textColor: Colors.black,
- backgroundColor: Colors.white);
+ textColor: toastTextColor,
+ backgroundColor: toastBackgroundColor);
isAuthLogin.value = false;
}
}
},
- onUpdateVisitedHistory:
- (controller, url, androidIsReload) async {
- // 로그아웃 링크 감지
- if (url.toString().contains("logout") && isAuthLogin.value) {
+ onLoadResourceCustomScheme: (controller, url) async {
+ if (!['intent'].contains(url.scheme)) {
await controller.stopLoading();
- try {
- await FcmToken().removeToken(Token().getAccessToken());
- await Token().deleteAll();
- isLogin.value = false;
- isAuthLogin.value = false;
- await _cookieManager.deleteAllCookies();
- await _controller.value!.loadUrl(
- urlRequest: URLRequest(url: Uri.parse(address)));
- } catch (e) {
- // TODO
- Fluttertoast.showToast(
- msg: "서버와의 연결에 실패했습니다.",
- toastLength: Toast.LENGTH_SHORT,
- textColor: Colors.black,
- backgroundColor: Colors.white);
- isAuthLogin.value = false;
+ if (await canLaunchUrlString(url.toString())) {
+ await launchUrlString(url.toString(),
+ mode: LaunchMode.externalApplication);
+ return;
}
+ switch (url.scheme) {
+ case 'supertoss':
+ OpenStore.instance.open(
+ androidAppBundleId: "viva.republica.toss",
+ appStoreId: "839333328");
+ break;
+ case 'uber':
+ OpenStore.instance.open(
+ androidAppBundleId: "com.ubercab",
+ appStoreId: "368677368");
+ break;
+ case 'tmoneyonda':
+ OpenStore.instance.open(
+ androidAppBundleId: "kr.co.orangetaxi.passenger",
+ appStoreId: "1489918157");
+ break;
+ case 'kakaotalk': //카카오페이 결제시
+ OpenStore.instance.open(
+ androidAppBundleId: "com.kakao.talk",
+ appStoreId: "362057947");
+ break;
+ case 'kakaot':
+ OpenStore.instance.open(
+ androidAppBundleId: "com.kakao.taxi",
+ appStoreId: "981110422");
+ break;
+ default:
+ await Fluttertoast.showToast(
+ msg: "해당 앱을 실행할 수 없습니다.",
+ toastLength: Toast.LENGTH_SHORT,
+ textColor: Colors.black,
+ backgroundColor: Colors.white);
+ break;
+ }
+ return null;
}
- },
- onLoadResourceCustomScheme: (controller, url) async {
if (Platform.isAndroid) {
if (url.scheme == 'intent') {
try {
@@ -434,8 +720,8 @@ class TaxiView extends HookWidget {
await Fluttertoast.showToast(
msg: "카카오톡을 실행할 수 없습니다.",
toastLength: Toast.LENGTH_SHORT,
- textColor: Colors.black,
- backgroundColor: Colors.white);
+ textColor: toastTextColor,
+ backgroundColor: toastBackgroundColor);
}
}
}
@@ -445,14 +731,14 @@ class TaxiView extends HookWidget {
// 될 때까지 리로드
if (!isLoaded.value && LoadCount.value < 10) {
LoadCount.value++;
- }
-
- if (code == -2) {
+ } else if (isServerError.value == false &&
+ code != 102 &&
+ code != -999) {
Fluttertoast.showToast(
msg: "서버와의 연결에 실패했습니다.",
toastLength: Toast.LENGTH_SHORT,
- textColor: Colors.black,
- backgroundColor: Colors.white);
+ textColor: toastTextColor,
+ backgroundColor: toastBackgroundColor);
isServerError.value = true;
}
},
@@ -463,92 +749,82 @@ class TaxiView extends HookWidget {
}),
)),
isTimerUp.value && isLoaded.value && isFcmInit.value
- ? Stack()
+ ? const Stack()
: Scaffold(
body: FadeTransition(opacity: animation, child: loadingView())),
isMustUpdate.value
? Container(
- color: const Color(0x66C8C8C8),
+ color: notiColor,
child: Center(
child: TaxiDialog(
- boxContent: {
+ boxMainContent: {
RichText(
textAlign: TextAlign.center,
text: TextSpan(
- text: "새로운 ",
- style: GoogleFonts.roboto(
- textStyle: const TextStyle(
- color: Color(0xFF323232),
- fontSize: 22,
- fontWeight: FontWeight.bold)),
+ style: Theme.of(context).textTheme.titleSmall,
children: const [
- TextSpan(text: "버전"),
TextSpan(
- text: "이 ",
- style: TextStyle(fontWeight: FontWeight.normal)),
+ text: "새로운 버전",
+ style: TextStyle(
+ fontFamily: 'NanumSquare_acB',
+ fontWeight: FontWeight.w700),
+ ),
+ TextSpan(text: "이 "),
TextSpan(
text: "출시",
- style: TextStyle(color: Color(0xFF6E3678))),
- TextSpan(
- text: "되었습니다!",
- style: TextStyle(fontWeight: FontWeight.normal))
+ style: TextStyle(
+ fontFamily: 'NanumSquare_acB',
+ color: taxiPrimaryColor,
+ fontWeight: FontWeight.w700)),
+ TextSpan(text: "되었습니다!")
]),
),
+ },
+ boxSecondaryContent: {
Text("정상적인 사용을 위해 앱을 업데이트 해주세요.",
textAlign: TextAlign.center,
- style: GoogleFonts.roboto(
- textStyle: const TextStyle(
- color: Color(0xFF888888),
- fontSize: 12,
- fontWeight: FontWeight.bold))),
+ style: Theme.of(context).textTheme.bodySmall),
},
rightButtonContent: "업데이트 하러가기",
leftButtonContent: "앱 종료하기",
)),
)
- : Stack(),
+ : const Stack(),
isServerError.value
? Container(
- color: const Color(0x66C8C8C8),
+ color: notiColor,
child: Center(
child: TaxiDialog(
- boxContent: {
+ boxMainContent: {
RichText(
textAlign: TextAlign.center,
text: TextSpan(
- text: "서버",
- style: GoogleFonts.roboto(
- textStyle: const TextStyle(
- color: Color(0xFF323232),
- fontSize: 22,
- fontWeight: FontWeight.bold)),
+ style: Theme.of(context).textTheme.titleSmall,
children: const [
- TextSpan(text: "와의 "),
TextSpan(
- text: "연결에 ",
- style: TextStyle(fontWeight: FontWeight.normal)),
+ text: "서버와의 ",
+ style: TextStyle(fontWeight: FontWeight.bold),
+ ),
+ TextSpan(text: "연결에 "),
TextSpan(
text: "실패",
- style: TextStyle(color: Color(0xFF6E3678))),
- TextSpan(
- text: "했습니다.",
- style: TextStyle(fontWeight: FontWeight.normal))
+ style: TextStyle(
+ color: taxiPrimaryColor,
+ fontWeight: FontWeight.bold)),
+ TextSpan(text: "했습니다.")
]),
),
- Padding(padding: EdgeInsets.only(top: 5)),
+ },
+ boxSecondaryContent: {
Text("일시적인 오류일 수 있습니다.",
textAlign: TextAlign.center,
- style: GoogleFonts.roboto(
- textStyle: const TextStyle(
- color: Color(0xFF888888),
- fontSize: 12,
- fontWeight: FontWeight.bold))),
+ style: Theme.of(context).textTheme.bodySmall),
},
rightButtonContent: "스토어로 가기",
leftButtonContent: "앱 종료하기",
)),
)
- : Stack()
+ : const Stack()
]));
}
@@ -576,8 +852,8 @@ class TaxiView extends HookWidget {
backCount.value = true;
Fluttertoast.showToast(
msg: "한번 더 누르시면 앱을 종료합니다.",
- backgroundColor: Colors.white,
- textColor: Colors.black,
+ backgroundColor: toastBackgroundColor,
+ textColor: toastTextColor,
toastLength: Toast.LENGTH_SHORT,
);
return false;
diff --git a/pubspec.yaml b/pubspec.yaml
index 2bccdc3..7935def 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
-version: 1.0.2+3
+version: 1.0.4+29
environment:
sdk: ">=2.17.5 <3.0.0"
@@ -53,6 +53,10 @@ dependencies:
firebase_dynamic_links: ^5.1.1
app_links: ^3.4.3
firebase_crashlytics: ^3.3.1
+ url_launcher: ^6.1.14
+ social_share: ^2.3.1
+ path_provider: ^2.1.1
+ http: ^1.1.0
dev_dependencies:
flutter_test: