diff --git a/assets/config/.env b/assets/config/.env index 71e1140..256ca9b 100644 --- a/assets/config/.env +++ b/assets/config/.env @@ -1,2 +1,2 @@ # 양자택일 AWS 서버 주소 -BASE_URL='http://ec2-3-34-98-67.ap-northeast-2.compute.amazonaws.com' \ No newline at end of file +BASE_URL='http://ec2-3-34-98-67.ap-northeast-2.compute.amazonaws.com' diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 72d75e2..e6ba84d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -14,6 +14,8 @@ PODS: - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS + - url_launcher_ios (0.0.1): + - Flutter - webview_flutter_wkwebview (0.0.1): - Flutter - FlutterMacOS @@ -26,6 +28,7 @@ DEPENDENCIES: - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`) EXTERNAL SOURCES: @@ -43,6 +46,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/path_provider_foundation/darwin" shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" webview_flutter_wkwebview: :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin" @@ -54,6 +59,7 @@ SPEC CHECKSUMS: package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe webview_flutter_wkwebview: 0982481e3d9c78fd5c6f62a002fcd24fc791f1e4 PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 diff --git a/lib/controller/auth/auth_controller.dart b/lib/controller/auth/auth_controller.dart index 6a61da0..dcdab48 100644 --- a/lib/controller/auth/auth_controller.dart +++ b/lib/controller/auth/auth_controller.dart @@ -1,8 +1,13 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:get/get.dart'; + // import 'package:package_info/package_info.dart'; import 'package:package_info_plus/package_info_plus.dart'; +import 'package:url_launcher/url_launcher.dart'; import 'package:yangjataekil/data/model/auth/reject_reason_response_model.dart'; import 'package:yangjataekil/data/model/version_model.dart'; import 'package:yangjataekil/data/repository/auth_repository.dart'; @@ -88,7 +93,7 @@ class AuthController extends GetxController { final Rx rejectAdminName = Rx('익명의 어드민1'); /// 차단 당한 이유 - final Rx rejectReason = Rx('규정 위반으로 차단되었습니다.'); + final Rx rejectReason = Rx('규정 위반으로 차단되었습니다.'); /// 유저 정보 final RxInt uid = RxInt(0); @@ -106,8 +111,8 @@ class AuthController extends GetxController { @override void onInit() { + // getVersion(); super.onInit(); - getVersion(); } /// 비밀번호 변경 @@ -136,8 +141,7 @@ class AuthController extends GetxController { /// 비밀번호 변경 Future changePw() async { // 비밀번호 조건 확인 (영문 대문자/소문자, 숫자, 특수문자 중 2가지 이상 포함, 6~20자) - const passwordPattern = - r'^(?=.*[A-Za-z])(?=.*\d|(?=.*[!@#\$&*~])).{6,20}$'; + const passwordPattern = r'^(?=.*[A-Za-z])(?=.*\d|(?=.*[!@#\$&*~])).{6,20}$'; final regex = RegExp(passwordPattern); if (!regex.hasMatch(newPw.value)) { @@ -150,8 +154,7 @@ class AuthController extends GetxController { // 비밀번호 확인 if (newPw.value != newPwCheck.value || newPw.value.isEmpty) { CustomSnackBar.showErrorSnackBar( - title: '비밀번호 불일치', - message: '새 비밀번호가 일치하지 않습니다'); + title: '비밀번호 불일치', message: '새 비밀번호가 일치하지 않습니다'); return; } @@ -170,8 +173,7 @@ class AuthController extends GetxController { // 현재 비밀번호 불일치 처리 else if (response == 'PASSWORD_MISMATCH_ERROR') { CustomSnackBar.showErrorSnackBar( - title: '비밀번호 변경 실패', - message: '현재 비밀번호가 일치하지 않습니다.'); + title: '비밀번호 변경 실패', message: '현재 비밀번호가 일치하지 않습니다.'); } // 기타 실패 처리 else { @@ -258,9 +260,10 @@ class AuthController extends GetxController { /// 회원탈퇴 Future deleteUser() async { - final String deleteReason = selectedDeleteReason.value == DELETEREASONS.directInput - ? directInputText.value - : selectedDeleteReason.value.name; + final String deleteReason = + selectedDeleteReason.value == DELETEREASONS.directInput + ? directInputText.value + : selectedDeleteReason.value.name; try { await authRepository.deleteUser(accessToken.value, deleteReason); @@ -268,13 +271,12 @@ class AuthController extends GetxController { Get.offAllNamed('/main'); } catch (e) { print('회원탈퇴 중 에러 발생: $e'); - CustomSnackBar.showErrorSnackBar( - title: '회원탈퇴 실패', message: '다시 시도해주세요.'); + CustomSnackBar.showErrorSnackBar(title: '회원탈퇴 실패', message: '다시 시도해주세요.'); } } /// 버전조회 - Future getVersion() async { + Future getVersion() async { try { final PackageInfo packageInfo = await PackageInfo.fromPlatform(); final String appVersion = packageInfo.version; @@ -282,17 +284,23 @@ class AuthController extends GetxController { final VersionModel response = await authRepository.getVersion(); print('버전 정보 조회, profileUrl>> ${response.toString()}'); - final checkVersion = _checkVersion(appVersion, response.minimumVersion); + final checkVersion = _checkVersion("1.0.0", response.minimumVersion); if (checkVersion == -1) { // TODO: 업데이트 유도 링크 추가 print('업데이트 해야합니다'); + // await _launchAppStore(); + return false; + exit(0); } else if (checkVersion == 0) { isCurrent.value = true; + return true; } version.value = appVersion; + return true; } catch (e) { print('버전 조회 실패: $e'); CustomSnackBar.showErrorSnackBar(message: '버전 조회 실패'); + return false; } } @@ -305,11 +313,10 @@ class AuthController extends GetxController { } try { bool isReject = await authRepository.checkRejectUser(accessToken.value); - if(isReject){ + if (isReject) { isRejectUser.value = isReject; getRejectReason(); } - } catch (e) { print('회원 차단 확인 중 에러 발생: $e'); } @@ -332,6 +339,21 @@ class AuthController extends GetxController { } } + /// 플레이스토어, 앱스토어 이동 (앱 업데이트) + Future launchAppStore() async { + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + + Uri storeUrl = Platform.isAndroid + ? Uri.parse( + "market://details/?id=${packageInfo.packageName}") + : Uri.parse("https://apps.apple.com/us/app/id6557054135"); + + if (await canLaunchUrl(storeUrl)) { + await launchUrl(storeUrl); + } else { + print("스토어 이동 실패"); + } + } } int _checkVersion(String appVersion, String minimumVersion) { @@ -339,6 +361,8 @@ int _checkVersion(String appVersion, String minimumVersion) { List minimumVersionList = minimumVersion.split('.').map(int.parse).toList(); + print("appVersion: appversion: $appVersion, appVersionList: $appVersionList"); + for (int i = 0; i < appVersionList.length; i++) { if (appVersionList[i] > minimumVersionList[i]) return 1; if (appVersionList[i] < minimumVersionList[i]) return -1; diff --git a/lib/main.dart b/lib/main.dart index 44a8cc9..61bcbaa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -8,6 +8,7 @@ import 'package:yangjataekil/pref/app_preferences.dart'; import 'package:yangjataekil/route/app_pages.dart'; import 'package:yangjataekil/theme/app_thene.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:yangjataekil/widget/dialog/custom_dialog_widget.dart'; import 'data/repository/auth_repository.dart'; @@ -58,16 +59,35 @@ void main() async { )); } -/// 앱 내에서 사용할 로그인 컨트롤러 등록 Future initService() async { - print("앱 초기화"); - /// 로그인 컨트롤러 영속성 설정 await Get.putAsync(() async { - final controller = AuthController(); - await controller.getToken(); - await controller.getUserInfoFromHomeScreen(); - await controller.getRejectReason(); - await controller.getVersion(); - return controller; - }, permanent: true); + return AuthController(); + }, permanent: true) + .then((value) async { + await value.getToken(); + await value.getUserInfoFromHomeScreen(); + + if (!await value.getVersion()) { + // UI가 렌더링된 후 실행 + WidgetsBinding.instance.addPostFrameCallback((_) { + showUpdateDialog(value); + }); + } + + await value.checkRejectUser(); + }); +} + +void showUpdateDialog(AuthController value) { + MyCustomDialog().showConfirmDialog( + title: '업데이트 필요', + content: '최신 버전으로 업데이트해주세요!', + onConfirm: () async => value.launchAppStore(), + confirmText: '업데이트', + isBarrierDismissible: false, + onCancel: () { + Get.back(); + showUpdateDialog(value); + }, + ); } diff --git a/lib/widget/dialog/custom_dialog_widget.dart b/lib/widget/dialog/custom_dialog_widget.dart index bccf065..48944ea 100644 --- a/lib/widget/dialog/custom_dialog_widget.dart +++ b/lib/widget/dialog/custom_dialog_widget.dart @@ -7,8 +7,11 @@ class MyCustomDialog { required String content, required Future Function() onConfirm, required String confirmText, + bool? isBarrierDismissible, + void Function()? onCancel, }) { Get.dialog( + barrierDismissible: isBarrierDismissible ?? true, AlertDialog( backgroundColor: Colors.white, shape: RoundedRectangleBorder( @@ -56,7 +59,8 @@ class MyCustomDialog { overlayColor: Colors.white, ), onPressed: () { - Get.back(); + // onCancel 기본값 Get.back() 처리 + (onCancel ?? Get.back)(); }, child: const Text( '취소', diff --git a/pubspec.lock b/pubspec.lock index 983d000..9cf1d21 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -794,6 +794,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" + url: "https://pub.dev" + source: hosted + version: "6.3.1" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" + url: "https://pub.dev" + source: hosted + version: "6.3.14" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" + url: "https://pub.dev" + source: hosted + version: "6.3.2" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" + url: "https://pub.dev" + source: hosted + version: "3.2.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + url: "https://pub.dev" + source: hosted + version: "3.1.4" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index ae21f4a..20150cc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -53,7 +53,6 @@ dependencies: animations: ^2.0.7 # 배너 슬라이더 -# carousel_slider: ^4.2.1 carousel_slider_plus: ^7.0.1 # dropdown 위젯 @@ -78,6 +77,8 @@ dependencies: # 딥링크 # uni_links: ^0.5.1 +# app_links: ^6.3.3 + url_launcher: ^6.3.1 # 웹뷰 webview_flutter: ^4.0.2