diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 47df3465..8184a0ae 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -62,16 +62,6 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; AEE2471C28CF82200092F192 /* Embed App Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 12; @@ -358,11 +348,10 @@ 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, + AEE2471C28CF82200092F192 /* Embed App Extensions */, 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 242C769F86A7805781E3C954 /* [CP] Embed Pods Frameworks */, - AEE2471C28CF82200092F192 /* Embed App Extensions */, ); buildRules = ( ); @@ -384,7 +373,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1340; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 0F872E3A28D875E3002954CC = { @@ -517,7 +506,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -609,11 +598,9 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = Extension/Extension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 18; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = T583WJWNAK; + DEVELOPMENT_TEAM = T583WJWNAK; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Extension/Info.plist; @@ -631,7 +618,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mr.acProjectApp.Extension; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.mr.acProjectApp.Extension"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_EMIT_LOC_STRINGS = YES; @@ -651,11 +637,9 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = Extension/Extension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 18; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = T583WJWNAK; + DEVELOPMENT_TEAM = T583WJWNAK; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Extension/Info.plist; @@ -672,7 +656,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mr.acProjectApp.Extension; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.mr.acProjectApp.Extension"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -690,11 +673,9 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = Extension/Extension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 18; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = T583WJWNAK; + DEVELOPMENT_TEAM = T583WJWNAK; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Extension/Info.plist; @@ -711,7 +692,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mr.acProjectApp.Extension; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.mr.acProjectApp.Extension"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -780,11 +760,9 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 18; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = T583WJWNAK; + DEVELOPMENT_TEAM = T583WJWNAK; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; @@ -795,7 +773,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mr.acProjectApp; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.mr.acProjectApp"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -926,11 +903,9 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 18; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = T583WJWNAK; + DEVELOPMENT_TEAM = T583WJWNAK; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; @@ -941,7 +916,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mr.acProjectApp; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.mr.acProjectApp"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -962,11 +936,9 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 18; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = T583WJWNAK; + DEVELOPMENT_TEAM = T583WJWNAK; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; @@ -977,7 +949,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mr.acProjectApp; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.mr.acProjectApp"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; diff --git a/lib/const/consts.dart b/lib/const/consts.dart index ffce5335..8e21fb12 100644 --- a/lib/const/consts.dart +++ b/lib/const/consts.dart @@ -6,5 +6,5 @@ const reportReasons = [ 'SLANDER', 'SPAM', 'PERSONAL_INFO', - 'OTHER' + 'OTHER', ]; diff --git a/lib/cubits/folders/get_user_folders_cubit.dart b/lib/cubits/folders/get_user_folders_cubit.dart index c6cacd0e..6eb794c2 100644 --- a/lib/cubits/folders/get_user_folders_cubit.dart +++ b/lib/cubits/folders/get_user_folders_cubit.dart @@ -4,7 +4,7 @@ import 'package:ac_project_app/provider/api/folders/folder_api.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class GetUserFoldersCubit extends Cubit { - GetUserFoldersCubit(): super(FolderList([])); + GetUserFoldersCubit(): super(const FolderList([])); final FolderApi folderApi = getIt(); @@ -16,11 +16,11 @@ class GetUserFoldersCubit extends Cubit { emit(FolderList(list)); }, error: (msg) { - emit(FolderList([])); + emit(const FolderList([])); }, ); } catch (e) { - emit(FolderList([])); + emit(const FolderList([])); } } } diff --git a/lib/cubits/links/upload_link_cubit.dart b/lib/cubits/links/upload_link_cubit.dart index e4f26bcd..cad41af9 100644 --- a/lib/cubits/links/upload_link_cubit.dart +++ b/lib/cubits/links/upload_link_cubit.dart @@ -1,11 +1,11 @@ import 'package:ac_project_app/cubits/links/upload_result_state.dart'; -import 'package:ac_project_app/util/url_loader.dart'; import 'package:ac_project_app/di/set_up_get_it.dart'; import 'package:ac_project_app/models/link/link.dart'; import 'package:ac_project_app/models/link/upload_type.dart'; import 'package:ac_project_app/provider/api/folders/link_api.dart'; import 'package:ac_project_app/util/logger.dart'; import 'package:ac_project_app/util/string_utils.dart'; +import 'package:ac_project_app/util/url_loader.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class UploadLinkCubit extends Cubit { diff --git a/lib/models/job/topic.dart b/lib/models/job/topic.dart index 910dc26a..51a6400f 100644 --- a/lib/models/job/topic.dart +++ b/lib/models/job/topic.dart @@ -7,6 +7,11 @@ class Topic { _name = name; } + Topic.fromJson(dynamic json) { + _id = json['id'] as int?; + _name = json['name'] as String?; + } + static List fromJsonList(List jsonList) { final result = []; for (final json in jsonList) { @@ -15,12 +20,9 @@ class Topic { return result; } - Topic.fromJson(dynamic json) { - _id = json['id'] as int?; - _name = json['name'] as String?; - } int? _id; String? _name; + Topic copyWith({ int? id, String? name, @@ -29,7 +31,9 @@ class Topic { id: id ?? _id, name: name ?? _name, ); + int? get id => _id; + String? get name => _name; Map toJson() { diff --git a/lib/models/user/detail_user.dart b/lib/models/user/detail_user.dart index c128eb90..dff74c97 100644 --- a/lib/models/user/detail_user.dart +++ b/lib/models/user/detail_user.dart @@ -22,6 +22,7 @@ class DetailUser extends Equatable { json['job_group'] != null ? JobGroup.fromJson(json['job_group']) : null; _profile_img = json['profile_img'] as String?; } + late final int? _id; late final String? _nickname; late final JobGroup? _jobGroup; @@ -39,9 +40,13 @@ class DetailUser extends Equatable { jobGroup: jobGroup ?? _jobGroup, profile_img: profile_img ?? _profile_img, ); + int? get id => _id; + String get nickname => _nickname ?? ''; + JobGroup? get jobGroup => _jobGroup; + String get profile_img => _profile_img ?? ''; Map toJson() { @@ -85,6 +90,11 @@ class JobGroup { _name = name; } + JobGroup.fromJson(dynamic json) { + _id = json['id'] as int?; + _name = json['name'] as String?; + } + static List fromJsonList(List jsonList) { final result = []; for (final json in jsonList) { @@ -93,12 +103,9 @@ class JobGroup { return result; } - JobGroup.fromJson(dynamic json) { - _id = json['id'] as int?; - _name = json['name'] as String?; - } int? _id; String? _name; + JobGroup copyWith({ int? id, String? name, @@ -107,7 +114,9 @@ class JobGroup { id: id ?? _id, name: name ?? _name, ); + int? get id => _id; + String? get name => _name; Map toJson() { diff --git a/lib/provider/api/user/profile_api.dart b/lib/provider/api/user/profile_api.dart index 670df288..570b635a 100644 --- a/lib/provider/api/user/profile_api.dart +++ b/lib/provider/api/user/profile_api.dart @@ -14,7 +14,7 @@ class ProfileApi { final result = await _client.patchUri( '/users/me', body: { - 'profile_img': profileImg + 'profile_img': profileImg, }, ); return result.when( diff --git a/lib/provider/kakao/kakao.dart b/lib/provider/kakao/kakao.dart index cddce16d..6169e3f8 100644 --- a/lib/provider/kakao/kakao.dart +++ b/lib/provider/kakao/kakao.dart @@ -6,10 +6,11 @@ import 'package:ac_project_app/cubits/profile/profile_info_cubit.dart'; import 'package:ac_project_app/cubits/profile/profile_state.dart'; import 'package:ac_project_app/di/set_up_get_it.dart'; import 'package:ac_project_app/models/folder/folder.dart'; -import 'package:ac_project_app/models/link/link.dart' as MyLink; +import 'package:ac_project_app/models/link/link.dart' as my_link; +import 'package:ac_project_app/models/profile/profile.dart' as Profile; import 'package:ac_project_app/models/profile/profile_image.dart'; import 'package:ac_project_app/provider/api/folders/link_api.dart'; -import 'package:ac_project_app/provider/api/user/user_api.dart' as MyUserApi; +import 'package:ac_project_app/provider/api/user/user_api.dart' as my_user_api; import 'package:ac_project_app/provider/login/firebase_auth_remote_data_source.dart'; import 'package:ac_project_app/routes.dart'; import 'package:ac_project_app/ui/widget/bottom_toast.dart'; @@ -22,7 +23,6 @@ import 'package:flutter/services.dart'; import 'package:kakao_flutter_sdk_share/kakao_flutter_sdk_share.dart'; import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:ac_project_app/models/profile/profile.dart' as Profile; class Kakao { static Future login() async { @@ -94,7 +94,7 @@ class Kakao { } } - static Future sendKakaoLinkShare(MyLink.Link link) async { + static Future sendKakaoLinkShare(my_link.Link link) async { final defaultFeed = FeedTemplate( content: Content( title: link.title ?? '', @@ -248,7 +248,7 @@ class Kakao { if (query.keys.contains('folderId')) { final folderId = query['folderId']!; final userId = query['userId'] ?? ''; - getIt().getUsersId(userId).then((result) { + getIt().getUsersId(userId).then((result) { result.when( success: (user) { final profileInfoCubit = getIt(); diff --git a/lib/provider/share_data_provider.dart b/lib/provider/share_data_provider.dart index 425309c8..24a63ea8 100644 --- a/lib/provider/share_data_provider.dart +++ b/lib/provider/share_data_provider.dart @@ -34,7 +34,7 @@ class ShareDataProvider { 'describe': item['comment'], 'image': item['image_link'], 'folder_name': item['folder_name'], - 'created_at': item['created_at'] + 'created_at': item['created_at'], }); } @@ -57,7 +57,7 @@ class ShareDataProvider { final folder = { 'name': json['name'], 'visible': json['visible'], - 'created_at': json['created_at'] + 'created_at': json['created_at'], }; result.add(folder); } diff --git a/lib/ui/page/home/home_page.dart b/lib/ui/page/home/home_page.dart index a25bf1b7..e53767b2 100644 --- a/lib/ui/page/home/home_page.dart +++ b/lib/ui/page/home/home_page.dart @@ -38,8 +38,9 @@ class HomePage extends StatelessWidget { child: NotificationListener( onNotification: (scrollNotification) { final metrics = scrollNotification.metrics; - if (metrics.axisDirection != AxisDirection.down) + if (metrics.axisDirection != AxisDirection.down) { return false; + } if (metrics.extentAfter <= 800) { context.read().loadMore(); } @@ -56,7 +57,10 @@ class HomePage extends StatelessWidget { SliverToBoxAdapter( child: Container( margin: EdgeInsets.only( - left: 24.w, right: 24.w, top: 20.h), + left: 24.w, + right: 24.w, + top: 20.h, + ), child: GestureDetector( onTap: () => Navigator.pushNamed( context, @@ -151,7 +155,7 @@ class HomePage extends StatelessWidget { thickness: 1.w, color: ccGrey200, ), - ) + ), ], ); }, diff --git a/lib/ui/page/my_folder/my_folder_page.dart b/lib/ui/page/my_folder/my_folder_page.dart index c2fb4761..583a126a 100644 --- a/lib/ui/page/my_folder/my_folder_page.dart +++ b/lib/ui/page/my_folder/my_folder_page.dart @@ -343,9 +343,9 @@ class _MyFolderPageState extends State fontWeight: FontWeight.w500, color: greyText, ), - ) + ), ], - ) + ), ], ), if (isNotClassified) @@ -495,7 +495,9 @@ class _MyFolderPageState extends State if (currFolder.visible ?? false) { Kakao.sendFolderKakaoShare( - currFolder, profile); + currFolder, + profile, + ); } else { showPopUp( title: '폴더를 공개해 주세요', diff --git a/lib/ui/view/home_view.dart b/lib/ui/view/home_view.dart index 30f2a535..13aae0e7 100644 --- a/lib/ui/view/home_view.dart +++ b/lib/ui/view/home_view.dart @@ -5,6 +5,7 @@ import 'package:ac_project_app/cubits/folders/get_user_folders_cubit.dart'; import 'package:ac_project_app/cubits/home/get_job_list_cubit.dart'; import 'package:ac_project_app/cubits/home_view_cubit.dart'; import 'package:ac_project_app/cubits/links/links_from_selected_job_group_cubit.dart'; +import 'package:ac_project_app/cubits/links/upload_link_cubit.dart'; import 'package:ac_project_app/di/set_up_get_it.dart'; import 'package:ac_project_app/gen/assets.gen.dart'; import 'package:ac_project_app/provider/api/folders/folder_api.dart'; @@ -130,12 +131,9 @@ class _HomeViewState extends State with WidgetsBindingObserver { ), MultiBlocProvider( providers: [ - BlocProvider( - create: (_) => GetJobListCubit(), - ), - BlocProvider( - create: (_) => GetUserFoldersCubit(), - ), + BlocProvider(create: (_) => GetJobListCubit()), + BlocProvider(create: (_) => GetUserFoldersCubit()), + BlocProvider(create: (_) => UploadLinkCubit()), ], child: const HomePage(), ), diff --git a/lib/ui/view/links/link_detail_view.dart b/lib/ui/view/links/link_detail_view.dart index c65f257c..5c1e2c27 100644 --- a/lib/ui/view/links/link_detail_view.dart +++ b/lib/ui/view/links/link_detail_view.dart @@ -4,6 +4,7 @@ import 'package:ac_project_app/const/colors.dart'; import 'package:ac_project_app/cubits/folders/get_user_folders_cubit.dart'; import 'package:ac_project_app/cubits/links/detail_edit_cubit.dart'; import 'package:ac_project_app/cubits/links/edit_state.dart'; +import 'package:ac_project_app/cubits/links/upload_link_cubit.dart'; import 'package:ac_project_app/cubits/profile/profile_info_cubit.dart'; import 'package:ac_project_app/cubits/profile/profile_state.dart'; import 'package:ac_project_app/gen/assets.gen.dart'; @@ -47,12 +48,9 @@ class LinkDetailView extends StatelessWidget { return MultiBlocProvider( providers: [ - BlocProvider( - create: (_) => DetailEditCubit(link), - ), - BlocProvider( - create: (_) => GetUserFoldersCubit(), - ) + BlocProvider(create: (_) => DetailEditCubit(link)), + BlocProvider(create: (_) => GetUserFoldersCubit()), + BlocProvider(create: (_) => UploadLinkCubit()), ], child: KeyboardDismissOnTap( child: KeyboardVisibilityBuilder( @@ -111,7 +109,6 @@ class LinkDetailView extends StatelessWidget { bool linkVisible, ) { return Scaffold( - resizeToAvoidBottomInset: false, appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, diff --git a/lib/ui/view/links/my_link_view.dart b/lib/ui/view/links/my_link_view.dart index 74beb90c..857a23fe 100644 --- a/lib/ui/view/links/my_link_view.dart +++ b/lib/ui/view/links/my_link_view.dart @@ -488,7 +488,7 @@ class MyLinkView extends StatelessWidget { endIndent: 24.w, ), ), - ) + ), ], ); }, @@ -657,7 +657,7 @@ class MyLinkView extends StatelessWidget { ), ), ), - ) + ), ], ), ); diff --git a/lib/ui/view/links/search_view.dart b/lib/ui/view/links/search_view.dart index bbedf107..7c70547e 100644 --- a/lib/ui/view/links/search_view.dart +++ b/lib/ui/view/links/search_view.dart @@ -6,6 +6,7 @@ import 'package:ac_project_app/const/colors.dart'; import 'package:ac_project_app/cubits/folders/get_user_folders_cubit.dart'; import 'package:ac_project_app/cubits/home/search_links_cubit.dart'; import 'package:ac_project_app/cubits/links/link_list_state.dart'; +import 'package:ac_project_app/cubits/links/upload_link_cubit.dart'; import 'package:ac_project_app/cubits/profile/profile_info_cubit.dart'; import 'package:ac_project_app/cubits/profile/profile_state.dart'; import 'package:ac_project_app/gen/assets.gen.dart'; @@ -51,6 +52,7 @@ class _SearchViewState extends State { BlocProvider( create: (_) => GetUserFoldersCubit(), ), + BlocProvider(create: (_) => UploadLinkCubit()), ], child: GestureDetector( onTap: () { @@ -237,10 +239,12 @@ class _SearchViewState extends State { color: grey100, child: CachedNetworkImage( imageUrl: link.image ?? '', - fadeInDuration: - const Duration(milliseconds: 300), - fadeOutDuration: - const Duration(milliseconds: 300), + fadeInDuration: const Duration( + milliseconds: 300, + ), + fadeOutDuration: const Duration( + milliseconds: 300, + ), imageBuilder: (context, imageProvider) => Container( @@ -443,7 +447,7 @@ class _SearchViewState extends State { height: (18 / 14).h, color: lightGrey700, ), - ) + ), ], ), ), diff --git a/lib/ui/view/links/user_feed_view.dart b/lib/ui/view/links/user_feed_view.dart index 44011511..0cbeebb2 100644 --- a/lib/ui/view/links/user_feed_view.dart +++ b/lib/ui/view/links/user_feed_view.dart @@ -6,6 +6,7 @@ import 'package:ac_project_app/const/colors.dart'; import 'package:ac_project_app/const/strings.dart'; import 'package:ac_project_app/cubits/feed/feed_view_cubit.dart'; import 'package:ac_project_app/cubits/folders/get_user_folders_cubit.dart'; +import 'package:ac_project_app/cubits/links/upload_link_cubit.dart'; import 'package:ac_project_app/cubits/scroll/scroll_cubit.dart'; import 'package:ac_project_app/gen/assets.gen.dart'; import 'package:ac_project_app/gen/fonts.gen.dart'; @@ -38,7 +39,8 @@ class UserFeedView extends StatelessWidget { final folderId = args['folderId'] as String?; // find index from folders by folderId - final index = folders.indexWhere((element) => element.id.toString() == folderId); + final index = + folders.indexWhere((element) => element.id.toString() == folderId); if (folders.isNotEmpty && index != -1) { // index가 처음이 되는 리스트로 folders를 재정렬 @@ -49,6 +51,7 @@ class UserFeedView extends StatelessWidget { providers: [ BlocProvider(create: (_) => FeedViewCubit(folders)), BlocProvider(create: (_) => GetUserFoldersCubit()), + BlocProvider(create: (_) => UploadLinkCubit()), ], child: Scaffold( backgroundColor: Colors.white, @@ -140,7 +143,7 @@ class UserFeedView extends StatelessWidget { fontSize: 28.sp, letterSpacing: -0.6.w, ), - ) + ), ], ), ), diff --git a/lib/ui/view/profile/profile_selector.dart b/lib/ui/view/profile/profile_selector.dart index 5bfe5211..5216b281 100644 --- a/lib/ui/view/profile/profile_selector.dart +++ b/lib/ui/view/profile/profile_selector.dart @@ -212,7 +212,7 @@ class _ProfileSelectorState extends State { '완료', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16.sp), ), - ) + ), ], ); } diff --git a/lib/ui/view/report_view.dart b/lib/ui/view/report_view.dart index dfe4f29f..26ce2ff5 100644 --- a/lib/ui/view/report_view.dart +++ b/lib/ui/view/report_view.dart @@ -76,7 +76,7 @@ class _ReportViewState extends State { '완료', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16.sp), ), - ) + ), ], ), body: SingleChildScrollView( @@ -228,7 +228,7 @@ class _ReportViewState extends State { ), ), ), - ) + ), ], ), ), @@ -334,7 +334,7 @@ class _ReportViewState extends State { fontSize: 14.sp, fontWeight: FontWeight.w500, ), - ) + ), ], ), ); diff --git a/lib/ui/view/upload_view.dart b/lib/ui/view/upload_view.dart index a467e3cc..dafbad1a 100644 --- a/lib/ui/view/upload_view.dart +++ b/lib/ui/view/upload_view.dart @@ -18,7 +18,6 @@ import 'package:ac_project_app/ui/widget/buttons/bottom_sheet_button.dart'; import 'package:ac_project_app/ui/widget/dialog/center_dialog.dart'; import 'package:ac_project_app/ui/widget/loading.dart'; import 'package:ac_project_app/util/get_arguments.dart'; -import 'package:ac_project_app/util/logger.dart'; import 'package:ac_project_app/util/url_valid.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -88,11 +87,6 @@ class _UploadViewState extends State with WidgetsBindingObserver { if (url.isNotEmpty) { linkTextController.text = url; } - final isCopied = args['isCopied'] as bool? ?? false; - if (isCopied) { - buttonState = isCopied ? ButtonState.enabled : ButtonState.disabled; - } - Log.i('buttonState: ${buttonState.name}'); return MultiBlocProvider( providers: [ @@ -167,10 +161,9 @@ class _UploadViewState extends State with WidgetsBindingObserver { buildFolderList( folderContext: folderContext, state: state, - callback: (index, folderId) => - setState(() { + callback: (index, folder) => setState(() { selectedIndex = index; - selectedFolderId = folderId; + selectedFolderId = folder.id; isSavedNewFolder = false; }), selectedIndex: selectedIndex, @@ -198,7 +191,7 @@ class _UploadViewState extends State with WidgetsBindingObserver { child: LoadingWidget(), ) else - const SizedBox.shrink() + const SizedBox.shrink(), ], ), bottomSheet: buildBottomSheetButton( @@ -206,7 +199,7 @@ class _UploadViewState extends State with WidgetsBindingObserver { text: '등록완료', keyboardVisible: visible, onPressed: buttonState == ButtonState.enabled - ? () => completeRegister(context, isCopied) + ? () => completeRegister(context) : null, buttonShadow: false, ), @@ -422,8 +415,7 @@ class _UploadViewState extends State with WidgetsBindingObserver { ); } - void completeRegister(BuildContext context, bool isCopied) { - final uploadType = isCopied ? UploadType.bring : UploadType.create; + void completeRegister(BuildContext context) { setLoading(); context .read() @@ -431,7 +423,7 @@ class _UploadViewState extends State with WidgetsBindingObserver { linkTextController.text, commentTextController.text, selectedFolderId, - uploadType, + UploadType.create, ) .then((result) { if (result == UploadResultState.success) { diff --git a/lib/ui/view/user/email_login_view.dart b/lib/ui/view/user/email_login_view.dart index be4ed921..4ab3154c 100644 --- a/lib/ui/view/user/email_login_view.dart +++ b/lib/ui/view/user/email_login_view.dart @@ -183,12 +183,12 @@ class _EmailLoginViewState extends State ), ), ), - ) + ), ], ), ), ), - SizedBox(height: keyboardHeight) + SizedBox(height: keyboardHeight), ], ), ), diff --git a/lib/ui/view/user/sign_up_job_view.dart b/lib/ui/view/user/sign_up_job_view.dart index ef803054..c197ce32 100644 --- a/lib/ui/view/user/sign_up_job_view.dart +++ b/lib/ui/view/user/sign_up_job_view.dart @@ -281,7 +281,7 @@ class SignUpJobView extends StatelessWidget { ), SizedBox( height: 24.h, - ) + ), ], ), ); diff --git a/lib/ui/widget/add_folder/folder_add_title.dart b/lib/ui/widget/add_folder/folder_add_title.dart index bfbec4a9..0d22b77d 100644 --- a/lib/ui/widget/add_folder/folder_add_title.dart +++ b/lib/ui/widget/add_folder/folder_add_title.dart @@ -19,6 +19,7 @@ Container buildFolderSelectTitle( ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + verticalDirection: VerticalDirection.up, children: [ buildSubTitle(text), InkWell( @@ -29,10 +30,7 @@ Container buildFolderSelectTitle( callback: callback, ), child: Padding( - padding: EdgeInsets.symmetric( - horizontal: 8.w, - vertical: 8.h, - ), + padding: EdgeInsets.all(8.w), child: SvgPicture.asset( Assets.images.btnAdd, ), diff --git a/lib/ui/widget/add_folder/horizontal_folder_list.dart b/lib/ui/widget/add_folder/horizontal_folder_list.dart index 9bbcfd24..68dca4ea 100644 --- a/lib/ui/widget/add_folder/horizontal_folder_list.dart +++ b/lib/ui/widget/add_folder/horizontal_folder_list.dart @@ -1,12 +1,13 @@ import 'package:ac_project_app/const/colors.dart'; import 'package:ac_project_app/cubits/folders/folders_state.dart'; import 'package:ac_project_app/gen/assets.gen.dart'; +import 'package:ac_project_app/models/folder/folder.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/flutter_svg.dart'; Widget buildFolderList({ - void Function(int index, int folderId)? callback, + void Function(int index, Folder folder)? callback, int? selectedIndex, required BuildContext folderContext, required FoldersState state, @@ -23,7 +24,7 @@ Widget buildFolderList({ curve: Curves.easeInOutCubic, ); - callback?.call(folders.length - 1, folders.last.id!); + callback?.call(folders.length - 1, folders.last); } if (isLast ?? false) Future.microtask(gotoLastIndex); @@ -42,7 +43,7 @@ Widget buildFolderList({ final visible = folder.visible ?? false; return GestureDetector( onTap: () { - callback?.call(index, folder.id!); + callback?.call(index, folder); }, child: Container( margin: EdgeInsets.only( @@ -86,7 +87,8 @@ Widget buildFolderList({ width: 95.w, height: 95.h, decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(32.r)), + borderRadius: + BorderRadius.all(Radius.circular(32.r)), color: secondary400, ), ), diff --git a/lib/ui/widget/add_folder/show_add_folder_dialog.dart b/lib/ui/widget/add_folder/show_add_folder_dialog.dart index 739cceea..8893ac87 100644 --- a/lib/ui/widget/add_folder/show_add_folder_dialog.dart +++ b/lib/ui/widget/add_folder/show_add_folder_dialog.dart @@ -283,7 +283,7 @@ Padding _buildDialogBody( ), ); }, - ) + ), ], ); }, diff --git a/lib/ui/widget/bottom_toast.dart b/lib/ui/widget/bottom_toast.dart index e47acf46..4bc2fd6c 100644 --- a/lib/ui/widget/bottom_toast.dart +++ b/lib/ui/widget/bottom_toast.dart @@ -6,6 +6,7 @@ void showBottomToast( String text, { double? bottomPadding, BuildContext? context, + int duration = 4000, void Function()? callback, String? subMsg, String actionTitle = '확인하기', @@ -55,7 +56,7 @@ void showBottomToast( ], ), backgroundColor: grey900, - duration: const Duration(milliseconds: 2000), + duration: Duration(milliseconds: duration), behavior: SnackBarBehavior.floating, action: (callback == null) ? null diff --git a/lib/ui/widget/dialog/bottom_dialog.dart b/lib/ui/widget/dialog/bottom_dialog.dart index 5f9c2546..38265639 100644 --- a/lib/ui/widget/dialog/bottom_dialog.dart +++ b/lib/ui/widget/dialog/bottom_dialog.dart @@ -18,6 +18,7 @@ import 'package:ac_project_app/ui/widget/add_folder/folder_add_title.dart'; import 'package:ac_project_app/ui/widget/add_folder/horizontal_folder_list.dart'; import 'package:ac_project_app/ui/widget/bottom_toast.dart'; import 'package:ac_project_app/ui/widget/dialog/center_dialog.dart'; +import 'package:ac_project_app/ui/widget/move_to_my_folder_dialog.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -38,7 +39,7 @@ Future showMyLinkOptionsDialog( return Wrap( children: [ DecoratedBox( - decoration: _dialogDecoration(), + decoration: DialogDecoration(), child: Padding( padding: EdgeInsets.only( top: 29.h, @@ -88,7 +89,8 @@ Future showMyLinkOptionsDialog( parentContext: parentContext, callback: () => Navigator.pop(context), icon: true, - iconImage: Assets.images.icLockColor.image(width: 27.w, height: 27.w), + iconImage: Assets.images.icLockColor + .image(width: 27.w, height: 27.w), ); } }, @@ -147,7 +149,7 @@ Future showChangeFolderDialog(Link link, BuildContext parentContext) { child: BlocBuilder( builder: (foldersContext, state) { return DecoratedBox( - decoration: _dialogDecoration(), + decoration: DialogDecoration(), child: Padding( padding: EdgeInsets.only( top: 29.h, @@ -182,9 +184,9 @@ Future showChangeFolderDialog(Link link, BuildContext parentContext) { child: buildFolderList( folderContext: foldersContext, state: state, - callback: (_, folderId) { + callback: (_, folder) { getIt() - .changeFolder(link, folderId) + .changeFolder(link, folder.id!) .then((result) { Navigator.pop(context); Navigator.pop(context); @@ -230,13 +232,13 @@ Future showLinkOptionsDialog( return Wrap( children: [ DecoratedBox( - decoration: _dialogDecoration(), + decoration: DialogDecoration(), child: Padding( padding: EdgeInsets.only( top: 29.h, bottom: Platform.isAndroid - ? MediaQuery.of(context).padding.bottom - : 16.h, + ? MediaQuery.of(context).viewInsets.bottom + : 4.h, ), child: Column( children: [ @@ -267,24 +269,7 @@ Future showLinkOptionsDialog( BottomListItem( '내 폴더 담기', callback: () { - Navigator.pushNamed( - context, - Routes.upload, - arguments: { - 'url': link.url, - 'isCopied': true, - }, - ).then((value) { - Navigator.pop(context); - callback?.call(); - Navigator.pushReplacementNamed( - context, - Routes.home, - arguments: { - 'index': 2, - }, - ); - }); + moveToMyFolderDialog(parentContext, link); }, ), BottomListItem( @@ -330,7 +315,7 @@ Future showUserOptionDialog( return Wrap( children: [ DecoratedBox( - decoration: _dialogDecoration(), + decoration: DialogDecoration(), child: Padding( padding: EdgeInsets.only( top: 29.h, @@ -440,7 +425,7 @@ Widget BottomListItem(String text, {required void Function() callback}) { ); } -BoxDecoration _dialogDecoration() { +BoxDecoration DialogDecoration() { return BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( diff --git a/lib/ui/widget/move_to_my_folder_dialog.dart b/lib/ui/widget/move_to_my_folder_dialog.dart new file mode 100644 index 00000000..abb64749 --- /dev/null +++ b/lib/ui/widget/move_to_my_folder_dialog.dart @@ -0,0 +1,131 @@ +import 'package:ac_project_app/const/colors.dart'; +import 'package:ac_project_app/cubits/folders/folders_state.dart'; +import 'package:ac_project_app/cubits/folders/get_my_folders_cubit.dart'; +import 'package:ac_project_app/cubits/links/upload_link_cubit.dart'; +import 'package:ac_project_app/cubits/links/upload_result_state.dart'; +import 'package:ac_project_app/models/folder/folder.dart'; +import 'package:ac_project_app/models/link/link.dart'; +import 'package:ac_project_app/models/link/upload_type.dart'; +import 'package:ac_project_app/routes.dart'; +import 'package:ac_project_app/ui/widget/add_folder/folder_add_title.dart'; +import 'package:ac_project_app/ui/widget/add_folder/horizontal_folder_list.dart'; +import 'package:ac_project_app/ui/widget/bottom_toast.dart'; +import 'package:ac_project_app/ui/widget/dialog/bottom_dialog.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +Future moveToMyFolderDialog(BuildContext parentContext, Link link) { + return showModalBottomSheet( + backgroundColor: Colors.transparent, + context: parentContext, + isScrollControlled: true, + builder: (BuildContext context) { + return Wrap( + children: [ + BlocProvider( + create: (_) => GetFoldersCubit(excludeUnclassified: true), + child: BlocBuilder( + builder: (foldersContext, state) { + return DecoratedBox( + decoration: DialogDecoration(), + child: Padding( + padding: EdgeInsets.only( + top: 32.h, + bottom: 30.h, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildTitle(context, '폴더 선택', titleLeft: 24.w), + Container( + margin: EdgeInsets.only(top: 17.h, bottom: 20.h), + child: Divider( + height: 1.h, + thickness: 1.h, + color: grey100, + ), + ), + if (state is FolderLoadedState) + Container( + margin: EdgeInsets.only(left: 24.w), + child: buildFolderSelectTitle( + foldersContext, + '내 폴더', + state.folders, + ), + ), + Container( + margin: EdgeInsets.only(left: 24.w), + child: buildFolderList( + folderContext: foldersContext, + state: state, + callback: (_, folder) { + onSelectFolder( + parentContext, + link, + folder, + context, + ); + }, + ), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ); + }, + ); +} + +void onSelectFolder( + BuildContext parentContext, + Link link, + Folder folder, + BuildContext context, +) { + parentContext + .read() + .completeRegister( + link.url ?? '', + link.describe ?? '', + folder.id, + UploadType.bring, + ) + .then((result) { + if (result == UploadResultState.success) { + Navigator.pop(parentContext); + Navigator.pop(context); + showBottomToast( + "링크가 '${_getFolderName(folder.name ?? '')}' 폴더에 담겼어요!", + context: parentContext, + actionTitle: '이동하기', + callback: () { + Navigator.pushNamed( + parentContext, + Routes.linkDetail, + arguments: { + 'link': link, + 'isMine': true, + 'visible': folder.visible, + }, + ); + }, + ); + } + }); +} + +// if folderName length is over 6, show only 4 characters and add '...' +String _getFolderName(String folderName) { + if (folderName.length > 6) { + return '${folderName.substring(0, 6)}...'; + } else { + return folderName; + } +} diff --git a/test/util/string_utils_test.dart b/test/util/string_utils_test.dart index ee019301..a083d185 100644 --- a/test/util/string_utils_test.dart +++ b/test/util/string_utils_test.dart @@ -8,23 +8,23 @@ import 'package:intl/intl.dart'; void main() { group('hasHttpImageUrl() test', () { test('link url이 http로 시작할 때만 true이다', () { - final link1 = Link(); + const link1 = Link(); var actual = hasHttpImageUrl(link1); expect(actual, false); - final link2 = Link(image: ''); + const link2 = Link(image: ''); actual = hasHttpImageUrl(link2); expect(actual, false); - final link3 = Link(image: '_____https://'); + const link3 = Link(image: '_____https://'); actual = hasHttpImageUrl(link3); expect(actual, false); - final link4 = Link(image: 'http://'); + const link4 = Link(image: 'http://'); actual = hasHttpImageUrl(link4); expect(actual, true); - final link5 = Link(image: 'https://'); + const link5 = Link(image: 'https://'); actual = hasHttpImageUrl(link5); expect(actual, true); }); @@ -32,10 +32,7 @@ void main() { group('UTC 시간을 일정 시간 간격 별로 변환하는 makeLinkTimeString() 테스트', () { // 현재 위치의 UTC 시간 간격 계산 - final inMinutes = DateTime - .now() - .timeZoneOffset - .inMinutes; + final inMinutes = DateTime.now().timeZoneOffset.inMinutes; final hourGap = inMinutes ~/ 60; final minuteGap = inMinutes % 60; @@ -117,8 +114,7 @@ void main() { }); group('링크 제목 문자열 30자 이하로만 표현하도록 자르는 함수 테스트', () { - const textThatMoreThan30Chars = - '0123456789' + const textThatMoreThan30Chars = '0123456789' '0123456789' '0123456789' '30자가 넘는 구간'; @@ -131,8 +127,8 @@ void main() { expect( result, '0123456789' - '0123456789' - '0123456789'); + '0123456789' + '0123456789'); }); test('30자가 넘지 않는 String을 변환했을 때 그대로 리턴', () {