Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions ios/fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,18 @@ platform :ios do

UI.message("📦 IPA 경로: #{ipa_path}")

# 릴리즈 노트 설정
release_notes = ENV["RELEASE_NOTES"] || "새로운 빌드가 업로드되었습니다."
# 릴리즈 노트 설정 (Ruby 3.4+ frozen string 호환을 위해 .dup 사용)
release_notes = (ENV["RELEASE_NOTES"] || "새로운 빌드가 업로드되었습니다.").dup
UI.message("📝 릴리즈 노트: #{release_notes}")

# TestFlight 업로드 (upload_to_testflight = pilot)
upload_to_testflight(
api_key: api_key,
ipa: ipa_path,
changelog: release_notes,
changelog: release_notes.dup,
localized_build_info: {
"ko" => { whats_new: release_notes },
"en-US" => { whats_new: release_notes }
"ko" => { whats_new: release_notes.dup },
"en-US" => { whats_new: release_notes.dup }
},
skip_waiting_for_build_processing: ENV["SKIP_WAITING_FOR_BUILD_PROCESSING"] == "true",
distribute_external: false,
Expand Down
3 changes: 2 additions & 1 deletion lib/core/constants/api_endpoints.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ class ApiEndpoints {
static const String onboardingTerms = '/api/members/onboarding/terms';

/// 온보딩: 생년월일
static const String onboardingBirthDate = '/api/members/onboarding/birth-date';
static const String onboardingBirthDate =
'/api/members/onboarding/birth-date';

/// 온보딩: 성별
static const String onboardingGender = '/api/members/onboarding/gender';
Expand Down
5 changes: 1 addition & 4 deletions lib/core/network/auth_interceptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ class AuthInterceptor extends Interceptor {
final Ref _ref;

/// 인증이 필요 없는 경로 목록
static const _publicPaths = [
'/api/auth/sign-in',
'/api/auth/reissue',
];
static const _publicPaths = ['/api/auth/sign-in', '/api/auth/reissue'];

AuthInterceptor(this._ref);

Expand Down
19 changes: 11 additions & 8 deletions lib/core/network/error_interceptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ class ErrorInterceptor extends Interceptor {
debugPrint(' Status: ${err.response?.statusCode}');

// DioException을 유지하되, error 필드에 AppException을 담아서 전달
handler.next(DioException(
requestOptions: err.requestOptions,
response: err.response,
type: err.type,
error: exception,
message: exception.message,
));
handler.next(
DioException(
requestOptions: err.requestOptions,
response: err.response,
type: err.type,
error: exception,
message: exception.message,
),
);
}

/// DioException을 AppException으로 변환
Expand Down Expand Up @@ -65,7 +67,8 @@ class ErrorInterceptor extends Interceptor {
String? serverMessage;
String? serverCode;
if (responseData is Map<String, dynamic>) {
serverMessage = responseData['message'] as String? ??
serverMessage =
responseData['message'] as String? ??
responseData['error'] as String?;
serverCode = responseData['code'] as String?;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/core/network/token_refresh_interceptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class TokenRefreshInterceptor extends Interceptor {

/// 갱신 완료 대기 중인 요청들
final List<({RequestOptions options, ErrorInterceptorHandler handler})>
_pendingRequests = [];
_pendingRequests = [];

TokenRefreshInterceptor(this._ref, this._mainDio, this._refreshDio);

Expand Down
13 changes: 8 additions & 5 deletions lib/core/network/token_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ class TokenStorage {
final FlutterSecureStorage _storage;

TokenStorage({FlutterSecureStorage? storage})
: _storage = storage ??
const FlutterSecureStorage(
aOptions: AndroidOptions(encryptedSharedPreferences: true),
iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
);
: _storage =
storage ??
const FlutterSecureStorage(
aOptions: AndroidOptions(encryptedSharedPreferences: true),
iOptions: IOSOptions(
accessibility: KeychainAccessibility.first_unlock,
),
);

// ============================================
// Access Token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class AuthRemoteDataSource {
/// Throws: DioException (network errors), AppException (converted errors)
Future<SignInResponse> signIn(SignInRequest request) async {
debugPrint('🔐 Calling sign-in API...');
debugPrint(' Firebase ID Token length: ${request.firebaseIdToken.length}');
debugPrint(
' Firebase ID Token length: ${request.firebaseIdToken.length}',
);

final response = await _dio.post(
ApiEndpoints.signIn,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ class AuthRepositoryImpl implements AuthRepository {
requiresOnboarding: response.requiresOnboarding,
onboardingStep: response.onboardingStep,
);
debugPrint('✅ Onboarding state saved: requiresOnboarding=${response.requiresOnboarding}');
debugPrint(
'✅ Onboarding state saved: requiresOnboarding=${response.requiresOnboarding}',
);

return response;
}
Expand Down
8 changes: 6 additions & 2 deletions lib/features/auth/presentation/pages/login_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ class LoginPage extends ConsumerWidget {
/// Google 로그인을 수행하고 에러 발생 시 SnackBar를 표시합니다.
Future<void> _handleGoogleSignIn(BuildContext context, WidgetRef ref) async {
// AuthNotifier로 로그인 수행 (백엔드 응답 포함)
final signInResponse = await ref.read(authNotifierProvider.notifier).signInWithGoogle();
final signInResponse = await ref
.read(authNotifierProvider.notifier)
.signInWithGoogle();

// 에러 체크 및 SnackBar 표시
if (!context.mounted) return;
Expand Down Expand Up @@ -56,7 +58,9 @@ class LoginPage extends ConsumerWidget {
/// Apple 로그인을 수행하고 에러 발생 시 SnackBar를 표시합니다.
Future<void> _handleAppleSignIn(BuildContext context, WidgetRef ref) async {
// AuthNotifier로 로그인 수행 (백엔드 응답 포함)
final signInResponse = await ref.read(authNotifierProvider.notifier).signInWithApple();
final signInResponse = await ref
.read(authNotifierProvider.notifier)
.signInWithApple();

// 에러 체크 및 SnackBar 표시
if (!context.mounted) return;
Expand Down
1 change: 0 additions & 1 deletion lib/features/auth/presentation/pages/splash_page.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ class OnboardingRemoteDataSource {
Future<void> submitTerms(TermsRequest request) async {
debugPrint('📤 OnboardingRemoteDataSource: Submitting terms agreement...');

await _dio.post(
ApiEndpoints.onboardingTerms,
data: request.toJson(),
);
await _dio.post(ApiEndpoints.onboardingTerms, data: request.toJson());

debugPrint('✅ Terms agreement submitted successfully');
}
Expand All @@ -47,10 +44,7 @@ class OnboardingRemoteDataSource {
Future<void> submitBirthDate(BirthDateRequest request) async {
debugPrint('📤 OnboardingRemoteDataSource: Submitting birth date...');

await _dio.post(
ApiEndpoints.onboardingBirthDate,
data: request.toJson(),
);
await _dio.post(ApiEndpoints.onboardingBirthDate, data: request.toJson());

debugPrint('✅ Birth date submitted successfully');
}
Expand All @@ -61,10 +55,7 @@ class OnboardingRemoteDataSource {
Future<void> submitGender(GenderRequest request) async {
debugPrint('📤 OnboardingRemoteDataSource: Submitting gender...');

await _dio.post(
ApiEndpoints.onboardingGender,
data: request.toJson(),
);
await _dio.post(ApiEndpoints.onboardingGender, data: request.toJson());

debugPrint('✅ Gender submitted successfully');
}
Expand All @@ -75,10 +66,7 @@ class OnboardingRemoteDataSource {
Future<void> submitProfile(ProfileRequest request) async {
debugPrint('📤 OnboardingRemoteDataSource: Submitting profile...');

await _dio.post(
ApiEndpoints.memberProfile,
data: request.toJson(),
);
await _dio.post(ApiEndpoints.memberProfile, data: request.toJson());

debugPrint('✅ Profile submitted successfully');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,7 @@ class _BirthDateStepPageState extends ConsumerState<BirthDateStepPage> {
SizedBox(height: 8.h),
Text(
'맞춤 콘텐츠 추천을 위해 사용됩니다.',
style: TextStyle(
fontSize: 14.sp,
color: AppColors.gray600,
),
style: TextStyle(fontSize: 14.sp, color: AppColors.gray600),
),
SizedBox(height: 48.h),

Expand All @@ -88,7 +85,10 @@ class _BirthDateStepPageState extends ConsumerState<BirthDateStepPage> {
style: OutlinedButton.styleFrom(
foregroundColor: AppColors.primary,
side: const BorderSide(color: AppColors.primary),
padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 12.h),
padding: EdgeInsets.symmetric(
horizontal: 24.w,
vertical: 12.h,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
Expand All @@ -101,10 +101,7 @@ class _BirthDateStepPageState extends ConsumerState<BirthDateStepPage> {
if (state.errorMessage != null) ...[
Text(
state.errorMessage!,
style: TextStyle(
fontSize: 14.sp,
color: AppColors.error,
),
style: TextStyle(fontSize: 14.sp, color: AppColors.error),
),
SizedBox(height: 8.h),
],
Expand Down Expand Up @@ -147,9 +144,7 @@ class _BirthDateStepPageState extends ConsumerState<BirthDateStepPage> {
padding: EdgeInsets.symmetric(horizontal: 16.w),
decoration: const BoxDecoration(
color: AppColors.gray100,
border: Border(
bottom: BorderSide(color: AppColors.gray200),
),
border: Border(bottom: BorderSide(color: AppColors.gray200)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
Expand Down Expand Up @@ -208,10 +203,7 @@ class _DateDisplay extends StatelessWidget {
final DateTime date;
final VoidCallback onTap;

const _DateDisplay({
required this.date,
required this.onTap,
});
const _DateDisplay({required this.date, required this.onTap});

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -245,10 +237,7 @@ class _DateBox extends StatelessWidget {
final String value;
final String label;

const _DateBox({
required this.value,
required this.label,
});
const _DateBox({required this.value, required this.label});

@override
Widget build(BuildContext context) {
Expand All @@ -265,10 +254,7 @@ class _DateBox extends StatelessWidget {
SizedBox(height: 4.h),
Text(
label,
style: TextStyle(
fontSize: 14.sp,
color: AppColors.gray500,
),
style: TextStyle(fontSize: 14.sp, color: AppColors.gray500),
),
],
);
Expand Down
14 changes: 5 additions & 9 deletions lib/features/onboarding/presentation/pages/gender_step_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,7 @@ class GenderStepPage extends ConsumerWidget {
SizedBox(height: 8.h),
Text(
'맞춤 콘텐츠 추천을 위해 사용됩니다.',
style: TextStyle(
fontSize: 14.sp,
color: AppColors.gray600,
),
style: TextStyle(fontSize: 14.sp, color: AppColors.gray600),
),
SizedBox(height: 48.h),

Expand Down Expand Up @@ -95,10 +92,7 @@ class GenderStepPage extends ConsumerWidget {
if (state.errorMessage != null) ...[
Text(
state.errorMessage!,
style: TextStyle(
fontSize: 14.sp,
color: AppColors.error,
),
style: TextStyle(fontSize: 14.sp, color: AppColors.error),
),
SizedBox(height: 8.h),
],
Expand Down Expand Up @@ -147,7 +141,9 @@ class _GenderButton extends StatelessWidget {
child: Container(
padding: EdgeInsets.symmetric(vertical: 24.h),
decoration: BoxDecoration(
color: isSelected ? AppColors.primary.withValues(alpha: 0.1) : AppColors.gray100,
color: isSelected
? AppColors.primary.withValues(alpha: 0.1)
: AppColors.gray100,
borderRadius: BorderRadius.circular(12.r),
border: Border.all(
color: isSelected ? AppColors.primary : AppColors.gray200,
Expand Down
Loading