Skip to content

Commit

Permalink
Merge pull request #46 from pet-sitter/45-유저-유저-프로필-이미지-등록-기능-구현
Browse files Browse the repository at this point in the history
Feat: [회원가입] 유저 프로필을 포함하여 회원가입 진행 로직 구현
  • Loading branch information
Yellowtoast authored Jan 16, 2024
2 parents 655a737 + 47952bb commit 07c1cf8
Show file tree
Hide file tree
Showing 44 changed files with 1,282 additions and 176 deletions.
5 changes: 5 additions & 0 deletions assets/svgs/common/icon_image.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/svgs/common/icon_plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
6 changes: 6 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,11 @@
<false/>
<key>UIStatusBarHidden</key>
<false/>
<key>NSPhotoLibraryUsageDescription</key>
<string>Need to upload image</string>
<key>NSCameraUsageDescription</key>
<string>Need to upload image</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need to upload image</string>
</dict>
</plist>
2 changes: 2 additions & 0 deletions lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:pets_next_door_flutter/app/router/app_router.dart';
import 'package:pets_next_door_flutter/core/constants/colors.dart';
import 'package:pets_next_door_flutter/core/services/size_service.dart';
import 'package:pets_next_door_flutter/core/theme/app_theme.dart';

class App extends ConsumerWidget {
Expand All @@ -20,6 +21,7 @@ class App extends ConsumerWidget {
theme: AppTheme.light,
builder: EasyLoading.init(builder: (context, child) {
AppColor.init(context);
AppSizeService.to.init(context);

return FToastBuilder()(
context,
Expand Down
2 changes: 2 additions & 0 deletions lib/app/di/app_binding.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:pets_next_door_flutter/app/di/modules/auth_di.dart';
import 'package:pets_next_door_flutter/app/di/modules/media_di.dart';
import 'package:pets_next_door_flutter/app/di/modules/user_di.dart';

final class AppBinder {
Expand All @@ -14,6 +15,7 @@ final class AppBinder {
for (final di in [
AuthDependencyInjection(),
UserDependencyInjection(),
MediaDependencyInjection(),
]) {
di.init();
}
Expand Down
2 changes: 0 additions & 2 deletions lib/app/di/modules/auth_di.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import 'package:pets_next_door_flutter/app/di/locator.dart';
import 'package:pets_next_door_flutter/features/auth/auth.dart';
import 'package:pets_next_door_flutter/features/auth/data/remote/auth_remote_data_source_impl.dart';
import 'package:pets_next_door_flutter/features/auth/repositories/auth_repository_impl.dart';
import 'package:pets_next_door_flutter/features/auth/auth.dart';
import 'package:pets_next_door_flutter/features/auth/usecases/sign_in_oauth_use_case.dart';

final class AuthDependencyInjection extends FeatureDependencyInjection {
@override
Expand Down
33 changes: 33 additions & 0 deletions lib/app/di/modules/media_di.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:get_it/get_it.dart';
import 'package:pets_next_door_flutter/app/di/feature_di_interface.dart';
import 'package:pets_next_door_flutter/features/media/data/remote/media_remote_data_source_impl.dart';
import 'package:pets_next_door_flutter/features/media/media.dart';
import 'package:pets_next_door_flutter/features/media/repositories/media_repository_impl.dart';

final class MediaDependencyInjection extends FeatureDependencyInjection {
@override
Future<void> dataSources() async {
GetIt.I.registerLazySingleton<MediaRemoteDataSource>(
MediaRemoteDataSourceImpl.new,
);
}

@override
void repositories() {
GetIt.I.registerLazySingleton<MediaRepository>(
() => MediaRepositoryImpl(
mediaRemoteDataSource,
),
);
}

@override
void useCases() {
GetIt.I
..registerFactory<UploadImageUseCase>(
() => UploadImageUseCase(
mediaRepository,
),
);
}
}
2 changes: 1 addition & 1 deletion lib/app/router/app_router.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 23 additions & 13 deletions lib/core/constants/svgs.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
abstract class PNDSvgs {
static const String mainIcon = 'assets/svgs/main_icon.svg';
static const String mainTitleIcon = 'assets/svgs/main_title_icon.svg';
static const String google = 'assets/svgs/login/google_icon.svg';
static const String kakao = 'assets/svgs/login/kakao_icon.svg';
static const String apple = 'assets/svgs/login/apple_icon.svg';

static const String home = 'assets/svgs/home/icon_home.svg';
static const String community = 'assets/svgs/home/icon_community.svg';
static const String chat = 'assets/svgs/home/icon_chat.svg';
static const String user = 'assets/svgs/home/icon_user.svg';

static const String catActive = 'assets/svgs/pet/cat_active.svg';
static const String dogActive = 'assets/svgs/pet/dog_active.svg';
static const String _basePath = 'assets/svgs/';

static const String _login = 'login/';
static const String google = _basePath + _login + 'google_icon.svg';
static const String kakao = _basePath + _login + 'kakao_icon.svg';
static const String apple = _basePath + _login + 'apple_icon.svg';

static const String _home = 'home/';
static const String home = _basePath + _home + 'icon_home.svg';
static const String community = _basePath + _home + 'icon_community.svg';
static const String chat = _basePath + _home + 'icon_chat.svg';
static const String user = _basePath + _home + 'icon_user.svg';

static const String _pet = 'pet/';
static const String catActive = _basePath + _pet + 'cat_active.svg';
static const String dogActive = _basePath + _pet + 'dog_active.svg';

static const String _common = 'common/';
static const String mainIcon = _basePath + _common + 'main_icon.svg';
static const String mainTitleIcon =
_basePath + _common + 'main_title_icon.svg';
static const String image = _basePath + _common + 'icon_image.svg';
static const String plus = _basePath + _common + 'icon_plus.svg';
}
17 changes: 17 additions & 0 deletions lib/core/enums/image_format.enum.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:pets_next_door_flutter/core/network_handling/exceptions/custom_exception.dart';

enum ImageFormat {
png('jpeg'),
jpeg('jpeg');

const ImageFormat(this.str);

final str;

factory ImageFormat.getByTypeStr({required String type}) {
return ImageFormat.values.firstWhere(
(element) => element.str == type,
orElse: () => throw ParsingEnumException(),
);
}
}
8 changes: 4 additions & 4 deletions lib/core/enums/media_type.enum.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import 'package:pets_next_door_flutter/core/network_handling/exceptions/custom_exception.dart';

enum MediaType {
enum AppMediaType {
image('image'),
video('video');

const MediaType(this.code);
const AppMediaType(this.code);

final code;

factory MediaType.getByTypeStr({required String type}) {
return MediaType.values.firstWhere(
factory AppMediaType.getByTypeStr({required String type}) {
return AppMediaType.values.firstWhere(
(element) => element.code == type,
orElse: () => throw ParsingEnumException(),
);
Expand Down
8 changes: 8 additions & 0 deletions lib/core/network_handling/exceptions/custom_exception.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,11 @@ class NoFirebaseUserEssentialDataException extends CustomException {
const NoFirebaseUserEssentialDataException()
: super('100008', '파이어베이스 유저 필수 데이터가 없습니다.');
}

class ImageNotCompressedException extends CustomException {
const ImageNotCompressedException() : super('100009', '이미지 변환에 실패했습니다.');
}

class InvalidMimeTypeException extends CustomException {
const InvalidMimeTypeException() : super('100009', '올바른 Mime 타입이 아닙니다.');
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class LoggerInterceptor implements Interceptor {
log('🌍 Header: ${options.headers}');
log('🌍 Query: ${options.queryParameters}');
log('🌍 Data: ${options.data}');

return handler.next(options);
}

Expand All @@ -28,7 +29,7 @@ class LoggerInterceptor implements Interceptor {
ResponseInterceptorHandler handler,
) {
log('⬅️ Received network response');
log('${response.statusCode != 200 ? '❌ ${response.statusCode} ❌' : '✅ 200 ✅'} ${response.requestOptions.baseUrl}${response.requestOptions.path}');
log('${'✅ ${response.statusCode} ✅'} ${response.requestOptions.baseUrl}${response.requestOptions.path}');
log('Query params: ${response.requestOptions.queryParameters}');
log('Response Data: ${response.data}');
log('-------------------------');
Expand Down
77 changes: 77 additions & 0 deletions lib/core/services/image_picker_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:pets_next_door_flutter/core/enums/image_format.enum.dart';
import 'package:pets_next_door_flutter/presentation/widgets/bottom_sheet/option_bottom_sheet.dart';

class ImagePickerService {
ImagePickerService._();

final _imagePicker = ImagePicker();

static final ImagePickerService to = ImagePickerService._();

Future<File?> pickImage(ImageSource imageSource) async {
XFile? imageXFile = await _imagePicker.pickImage(source: imageSource);

if (imageXFile == null) return null;

return File(imageXFile.path);
}

static Future<ImageSource?> showImageSourceOptions(
BuildContext context) async {
return showModalBottomSheet<ImageSource?>(
context: context,
builder: (context) => OptionListBottomSheet<ImageSource>(
options: ImageSource.values.map((e) => e.name).toList(),
onOptionTapped: (int option) {
context.pop(ImageSource.values[option]);
},
onCloseBtnTapped: () {
context.pop();
},
leadingText: ''),
);
}

static Future<File?> compressAndConvertFormat(
File imageFile, {
CompressFormat format = CompressFormat.png,
int quality = 100,
int? minWidth,
int? minHeight,
}) async {
XFile? result;

try {
result = await FlutterImageCompress.compressAndGetFile(
imageFile.path,
'${(await getTemporaryDirectory()).path}/${DateTime.now().millisecondsSinceEpoch}.${format.name}',
format: format,
quality: quality,
minWidth: minWidth ?? 1920,
minHeight: minHeight ?? 1080,
);

if (result == null) return null;
} on UnsupportedError catch (e) {}

return File(result!.path);
}

static ImageFormat? getImageFormat(File file) {
if (file.path.endsWith('.${ImageFormat.jpeg.str}') ||
file.path.endsWith('.jpg')) {
return ImageFormat.jpeg;
} else if (file.path.endsWith('.${ImageFormat.png.str}')) {
return ImageFormat.png;
} else {
return null;
}
}
}
29 changes: 29 additions & 0 deletions lib/core/services/size_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:flutter/material.dart';

class AppSizeService {
AppSizeService._();

late double statusBarHeight; // Safe Area 상단 Inset
late double bottomInset; // Safe Area 하단 Inset
late double screenWidth; // 디바이스 넓이
late double screenHeight; // 디바이스 높이
late double responsiveBottomInset; // 반응형 하단 Safe Area 하단 Inset

// 비율로 처리했을 때 높이 넓이. (375 * 812) 기준
double ratioHeight(double givenHeight) => (givenHeight / 375) * 375;
double rationWidth(double givenWidth) => (givenWidth / 812) * 812;

// 초기화 구문
void init(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
final bool isTablet = mediaQuery.size.width > 600;
statusBarHeight = mediaQuery.padding.top;
bottomInset = mediaQuery.padding.bottom;
screenWidth = isTablet ? 375 : mediaQuery.size.width;
screenHeight = isTablet ? 812 : mediaQuery.size.height;
responsiveBottomInset =
mediaQuery.padding.bottom == 0 ? 16 : mediaQuery.padding.bottom;
}

static final AppSizeService to = AppSizeService._();
}
Empty file.
Loading

0 comments on commit 07c1cf8

Please sign in to comment.