diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 000000000..65bf8baca --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,33 @@ +# .github/release.yml + +name-template: 'μ• λ‹ˆλ˜ v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' +categories: + - title: 'πŸ†• μƒˆλ‘œμš΄ κΈ°λŠ₯이 μΆ”κ°€λ˜μ—ˆμ–΄μš”!' + label: '✨ Feature' + - title: '🐞 μžμž˜ν•œ 버그λ₯Ό μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€.' + label: '🐞 Bugfix' + - title: '🫢🏻 μ•± μ‚¬μš©μ„± κ°œμ„ μ— νž˜μΌμŠ΅λ‹ˆλ‹€.' + label: '🫢🏻 Improvement' + - title: 'πŸ› οΈ 더 λ‚˜μ€ μ½”λ“œλ₯Ό μœ„ν•΄ λ…Έλ ₯ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.' + labels: + - 'πŸ”¨ Refactor' + - 'βš™οΈ Setting' + - title: 'ETC' + labels: + - "*" +change-template: '* $TITLE (#$NUMBER) by @$AUTHOR' +change-title-escapes: '\<*_&#@`' +version-resolver: + major: + labels: + - 'Major' + minor: + labels: + - 'Minor' + patch: + labels: + - 'Patch' + default: patch +template: | + $CHANGES diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 000000000..969f56c1f --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,21 @@ +name: Release Drafter + +on: + push: + branches: + - main + +permissions: + contents: read + +jobs: + update_release_draft: + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v5 + with: + config-name: release.yml + env: + GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} diff --git a/Manito/Manito.xcodeproj/project.pbxproj b/Manito/Manito.xcodeproj/project.pbxproj index a2af8c01e..0b5278e95 100644 --- a/Manito/Manito.xcodeproj/project.pbxproj +++ b/Manito/Manito.xcodeproj/project.pbxproj @@ -141,12 +141,13 @@ CB5AE3E4285AAF7400382EA3 /* RoomInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5AE3E3285AAF7400382EA3 /* RoomInfoView.swift */; }; CB5AE3E6285AB76800382EA3 /* PeopleInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5AE3E5285AB76800382EA3 /* PeopleInfoView.swift */; }; CB637A3B28595C1200FF1240 /* ParticipateRoomViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB637A3A28595C1200FF1240 /* ParticipateRoomViewController.swift */; }; + CB6637E82959CBC60050BD04 /* SkeletonView in Frameworks */ = {isa = PBXBuildFile; productRef = CB6637E72959CBC60050BD04 /* SkeletonView */; }; CB674C1C285966020063A6B7 /* InputInvitedCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB674C1B285966020063A6B7 /* InputInvitedCodeView.swift */; }; CB674C2128596A310063A6B7 /* CheckRoomViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB674C2028596A310063A6B7 /* CheckRoomViewController.swift */; }; CB7B23A828C4ECA8004A4CF3 /* Character.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB7B23A728C4ECA8004A4CF3 /* Character.swift */; }; CB85DE1F28A76F3400399109 /* SettingDeveloperInfoHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB85DE1E28A76F3400399109 /* SettingDeveloperInfoHeaderView.swift */; }; CB9592B22855C09A00847751 /* ManitoRoomCollectionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB9592B12855C09A00847751 /* ManitoRoomCollectionCell.swift */; }; - CB9592B52855D52700847751 /* CommonMissonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB9592B42855D52700847751 /* CommonMissonView.swift */; }; + CB9592B52855D52700847751 /* CommonMissionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB9592B42855D52700847751 /* CommonMissionView.swift */; }; CBA15C94285CE1A80051EDE2 /* ChooseCharacterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBA15C93285CE1A80051EDE2 /* ChooseCharacterViewController.swift */; }; CBA4D7A42856CE9F0018BDC2 /* CreateRoomCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBA4D7A32856CE9F0018BDC2 /* CreateRoomCollectionViewCell.swift */; }; CBA4D7A62856D48C0018BDC2 /* RoomStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBA4D7A52856D48C0018BDC2 /* RoomStateView.swift */; }; @@ -301,7 +302,7 @@ CB7B23A728C4ECA8004A4CF3 /* Character.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Character.swift; sourceTree = ""; }; CB85DE1E28A76F3400399109 /* SettingDeveloperInfoHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingDeveloperInfoHeaderView.swift; sourceTree = ""; }; CB9592B12855C09A00847751 /* ManitoRoomCollectionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManitoRoomCollectionCell.swift; sourceTree = ""; }; - CB9592B42855D52700847751 /* CommonMissonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonMissonView.swift; sourceTree = ""; }; + CB9592B42855D52700847751 /* CommonMissionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonMissionView.swift; sourceTree = ""; }; CBA15C93285CE1A80051EDE2 /* ChooseCharacterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChooseCharacterViewController.swift; sourceTree = ""; }; CBA4D7A32856CE9F0018BDC2 /* CreateRoomCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomCollectionViewCell.swift; sourceTree = ""; }; CBA4D7A52856D48C0018BDC2 /* RoomStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomStateView.swift; sourceTree = ""; }; @@ -322,6 +323,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CB6637E82959CBC60050BD04 /* SkeletonView in Frameworks */, 39FFE33428F457AF008442EE /* FirebaseMessaging in Frameworks */, B50B1B0428596C900080992C /* SnapKit in Frameworks */, B50B1B0728596CB10080992C /* FSCalendar in Frameworks */, @@ -390,7 +392,7 @@ path = Login; sourceTree = ""; }; - 39C957D328799A8200A04A2B /* Service */ = { + 39C957D328799A8200A04A2B /* Foundation */ = { isa = PBXGroup; children = ( 39C957D528799AB900A04A2B /* HTTPMethod.swift */, @@ -401,7 +403,7 @@ 39C957F5287D9ED000A04A2B /* NetworkRequest.swift */, B5F31C5528BFA87700F61D0F /* Requestable.swift */, ); - path = Service; + path = Foundation; sourceTree = ""; }; 39C957EA287AE45900A04A2B /* EndPoint */ = { @@ -502,7 +504,6 @@ B5F524C228519AA000614FF7 = { isa = PBXGroup; children = ( - 39FFE33528F45E44008442EE /* GoogleService-Info.plist */, B55BCEB528D99F8600AF7E45 /* Settings.bundle */, B5F524CD28519AA000614FF7 /* Manito */, B5F524CC28519AA000614FF7 /* Products */, @@ -676,6 +677,7 @@ children = ( 39E6321328BDE59C00CFC6C4 /* Manito.entitlements */, B5F524DC28519AA100614FF7 /* Info.plist */, + 39FFE33528F45E44008442EE /* GoogleService-Info.plist */, B5F524CE28519AA000614FF7 /* AppDelegate.swift */, B5F524D028519AA000614FF7 /* SceneDelegate.swift */, ); @@ -768,7 +770,7 @@ 397A241528BA519200454E4F /* Protocol */, 397A241128BA513E00454E4F /* API */, 39C957EA287AE45900A04A2B /* EndPoint */, - 39C957D328799A8200A04A2B /* Service */, + 39C957D328799A8200A04A2B /* Foundation */, B5F525472855D01200614FF7 /* Models */, ); path = Network; @@ -846,7 +848,7 @@ CB9592B32855D51100847751 /* UIComponent */ = { isa = PBXGroup; children = ( - CB9592B42855D52700847751 /* CommonMissonView.swift */, + CB9592B42855D52700847751 /* CommonMissionView.swift */, CBA4D7A52856D48C0018BDC2 /* RoomStateView.swift */, ); path = UIComponent; @@ -942,6 +944,7 @@ B50B1B0328596C900080992C /* SnapKit */, B50B1B0628596CB10080992C /* FSCalendar */, B50B1B32285AC0970080992C /* Gifu */, + CB6637E72959CBC60050BD04 /* SkeletonView */, 39FFE33328F457AF008442EE /* FirebaseMessaging */, ); productName = Manito; @@ -976,6 +979,7 @@ B50B1B0228596C900080992C /* XCRemoteSwiftPackageReference "SnapKit" */, B50B1B0528596CB10080992C /* XCRemoteSwiftPackageReference "FSCalendar" */, B50B1B31285AC0970080992C /* XCRemoteSwiftPackageReference "Gifu" */, + CB6637E62959CBC60050BD04 /* XCRemoteSwiftPackageReference "SkeletonView" */, 39FFE33228F457AF008442EE /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, ); productRefGroup = B5F524CC28519AA000614FF7 /* Products */; @@ -1113,7 +1117,7 @@ B5F31BB028BE1CA700F61D0F /* UserDefaultStorage.swift in Sources */, B5F31BB228BE1CD700F61D0F /* UserDefaultHandler.swift in Sources */, 39CD581D28C4C03C00496E91 /* DetailDoneProtocol.swift in Sources */, - CB9592B52855D52700847751 /* CommonMissonView.swift in Sources */, + CB9592B52855D52700847751 /* CommonMissionView.swift in Sources */, CBA4D7A42856CE9F0018BDC2 /* CreateRoomCollectionViewCell.swift in Sources */, 39C95802287DACC300A04A2B /* RoomEndPoint.swift in Sources */, CB4C77E628C0D4EB007A1AD2 /* MainAPI.swift in Sources */, @@ -1319,7 +1323,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2; + MARKETING_VERSION = 1.2.1; PRODUCT_BUNDLE_IDENTIFIER = com.TeamFirefighter.Manito; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1356,7 +1360,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2; + MARKETING_VERSION = 1.2.1; PRODUCT_BUNDLE_IDENTIFIER = com.TeamFirefighter.Manito; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1422,6 +1426,14 @@ minimumVersion = 3.0.0; }; }; + CB6637E62959CBC60050BD04 /* XCRemoteSwiftPackageReference "SkeletonView" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Juanpe/SkeletonView.git"; + requirement = { + branch = main; + kind = branch; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -1445,6 +1457,11 @@ package = B50B1B31285AC0970080992C /* XCRemoteSwiftPackageReference "Gifu" */; productName = Gifu; }; + CB6637E72959CBC60050BD04 /* SkeletonView */ = { + isa = XCSwiftPackageProductDependency; + package = CB6637E62959CBC60050BD04 /* XCRemoteSwiftPackageReference "SkeletonView" */; + productName = SkeletonView; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = B5F524C328519AA000614FF7 /* Project object */; diff --git a/Manito/Manito.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Manito/Manito.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 2411f728a..a5052b187 100644 --- a/Manito/Manito.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Manito/Manito.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -117,6 +117,15 @@ "version" : "2.1.1" } }, + { + "identity" : "skeletonview", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Juanpe/SkeletonView.git", + "state" : { + "branch" : "main", + "revision" : "0f5eaf82e82441690d38abfc4118c961f113881c" + } + }, { "identity" : "snapkit", "kind" : "remoteSourceControl", diff --git a/Manito/Manito/Global/Base/BaseViewController.swift b/Manito/Manito/Global/Base/BaseViewController.swift index a87229e84..e1eb4f8a2 100644 --- a/Manito/Manito/Global/Base/BaseViewController.swift +++ b/Manito/Manito/Global/Base/BaseViewController.swift @@ -49,8 +49,8 @@ class BaseViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - render() - configUI() + setupLayout() + configureUI() setupBackButton() hidekeyboardWhenTappedAround() setupNavigationBar() @@ -66,11 +66,11 @@ class BaseViewController: UIViewController { setupInteractivePopGestureRecognizer() } - func render() { + func setupLayout() { // Override Layout } - func configUI() { + func configureUI() { view.backgroundColor = .backgroundGrey } diff --git a/Manito/GoogleService-Info.plist b/Manito/Manito/Global/Supports/GoogleService-Info.plist similarity index 100% rename from Manito/GoogleService-Info.plist rename to Manito/Manito/Global/Supports/GoogleService-Info.plist diff --git a/Manito/Manito/Network/Service/APIEnvironment.swift b/Manito/Manito/Network/Foundation/APIEnvironment.swift similarity index 100% rename from Manito/Manito/Network/Service/APIEnvironment.swift rename to Manito/Manito/Network/Foundation/APIEnvironment.swift diff --git a/Manito/Manito/Network/Service/APIService.swift b/Manito/Manito/Network/Foundation/APIService.swift similarity index 100% rename from Manito/Manito/Network/Service/APIService.swift rename to Manito/Manito/Network/Foundation/APIService.swift diff --git a/Manito/Manito/Network/Service/Endpointable.swift b/Manito/Manito/Network/Foundation/Endpointable.swift similarity index 100% rename from Manito/Manito/Network/Service/Endpointable.swift rename to Manito/Manito/Network/Foundation/Endpointable.swift diff --git a/Manito/Manito/Network/Service/HTTPMethod.swift b/Manito/Manito/Network/Foundation/HTTPMethod.swift similarity index 100% rename from Manito/Manito/Network/Service/HTTPMethod.swift rename to Manito/Manito/Network/Foundation/HTTPMethod.swift diff --git a/Manito/Manito/Network/Service/NetworkError.swift b/Manito/Manito/Network/Foundation/NetworkError.swift similarity index 100% rename from Manito/Manito/Network/Service/NetworkError.swift rename to Manito/Manito/Network/Foundation/NetworkError.swift diff --git a/Manito/Manito/Network/Service/NetworkRequest.swift b/Manito/Manito/Network/Foundation/NetworkRequest.swift similarity index 100% rename from Manito/Manito/Network/Service/NetworkRequest.swift rename to Manito/Manito/Network/Foundation/NetworkRequest.swift diff --git a/Manito/Manito/Network/Service/Requestable.swift b/Manito/Manito/Network/Foundation/Requestable.swift similarity index 100% rename from Manito/Manito/Network/Service/Requestable.swift rename to Manito/Manito/Network/Foundation/Requestable.swift diff --git a/Manito/Manito/Network/Models/Room.swift b/Manito/Manito/Network/Models/Room.swift index cefd0a792..c527cdb24 100644 --- a/Manito/Manito/Network/Models/Room.swift +++ b/Manito/Manito/Network/Models/Room.swift @@ -39,6 +39,28 @@ struct Room: Decodable { } } + var canStart: Bool { + if let count = participants?.count, + let date = roomInformation?.startDate?.stringToDate { + let isMinimumUserCount = count >= 4 + return isMinimumUserCount && date.isToday + } else { + return false + } + } + + var roomDTO: RoomDTO { + if let roomInformation { + let dto = RoomDTO(title: roomInformation.title ?? "", + capacity: roomInformation.capacity ?? 0, + startDate: roomInformation.startDate ?? "", + endDate: roomInformation.endDate ?? "") + return dto + } else { + return RoomDTO(title: "", capacity: 0, startDate: "", endDate: "") + } + } + enum CodingKeys: String, CodingKey { case roomInformation = "room" case participants @@ -61,6 +83,14 @@ struct Friend: Decodable { struct Participants: Decodable { let count: Int? let members: [User]? + + var membersNickname: [String] { + if let nicknames = members { + return nicknames.map { $0.nickname ?? "" } + } else { + return [] + } + } } // MARK: - Member @@ -81,6 +111,24 @@ struct RoomInfo: Decodable { return "" } } + + var isAlreadyPastDate: Bool { + if let date = startDate?.stringToDate { + return date.distance(to: Date()) > 86400 + } else { + return false + } + } + + var isStart: Bool { + if let date = startDate?.stringToDate { + let isStartDate = date.distance(to: Date()) < 86400 + let isPast = date.distance(to: Date()) > 86400 + return !isPast && isStartDate + } else { + return false + } + } } struct Mission: Codable { diff --git a/Manito/Manito/Screens/CheckRoom/CheckRoomViewController.swift b/Manito/Manito/Screens/CheckRoom/CheckRoomViewController.swift index 544ae3e28..6844db072 100644 --- a/Manito/Manito/Screens/CheckRoom/CheckRoomViewController.swift +++ b/Manito/Manito/Screens/CheckRoom/CheckRoomViewController.swift @@ -73,7 +73,7 @@ class CheckRoomViewController: BaseViewController { setupViewController() } - override func render() { + override func setupLayout() { view.addSubview(roomInfoImageView) roomInfoImageView.snp.makeConstraints { $0.center.equalToSuperview() @@ -110,7 +110,7 @@ class CheckRoomViewController: BaseViewController { } } - override func configUI() { + override func configureUI() { view.backgroundColor = .black.withAlphaComponent(0.7) } diff --git a/Manito/Manito/Screens/ChooseCharacter/ChooseCharacterViewController.swift b/Manito/Manito/Screens/ChooseCharacter/ChooseCharacterViewController.swift index 363593e4f..2c8edb1fc 100644 --- a/Manito/Manito/Screens/ChooseCharacter/ChooseCharacterViewController.swift +++ b/Manito/Manito/Screens/ChooseCharacter/ChooseCharacterViewController.swift @@ -127,7 +127,7 @@ class ChooseCharacterViewController: BaseViewController { // MARK: - life cycle - override func render() { + override func setupLayout() { view.addSubview(closeButton) closeButton.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide).inset(9) diff --git a/Manito/Manito/Screens/CreateNickName/CreateNickNameViewController.swift b/Manito/Manito/Screens/CreateNickName/CreateNickNameViewController.swift index 8c781ba02..626970359 100644 --- a/Manito/Manito/Screens/CreateNickName/CreateNickNameViewController.swift +++ b/Manito/Manito/Screens/CreateNickName/CreateNickNameViewController.swift @@ -90,7 +90,7 @@ class CreateNickNameViewController: BaseViewController { } } - override func render() { + override func setupLayout() { view.addSubview(titleLabel) titleLabel.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide).inset(66) @@ -191,8 +191,8 @@ class CreateNickNameViewController: BaseViewController { // MARK: - Configure - override func configUI() { - super.configUI() + override func configureUI() { + super.configureUI() } } diff --git a/Manito/Manito/Screens/CreateRoom/CreateRoomViewController.swift b/Manito/Manito/Screens/CreateRoom/CreateRoomViewController.swift index d88b4a9fe..4887b5f49 100644 --- a/Manito/Manito/Screens/CreateRoom/CreateRoomViewController.swift +++ b/Manito/Manito/Screens/CreateRoom/CreateRoomViewController.swift @@ -88,7 +88,7 @@ class CreateRoomViewController: BaseViewController { setupNotificationCenter() } - override func render() { + override func setupLayout() { view.addSubview(titleLabel) titleLabel.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide).inset(66) @@ -148,8 +148,8 @@ class CreateRoomViewController: BaseViewController { // MARK: - Configure - override func configUI() { - super.configUI() + override func configureUI() { + super.configureUI() navigationController?.navigationBar.isHidden = true } diff --git a/Manito/Manito/Screens/Detail-Ing/DetailIngViewController.swift b/Manito/Manito/Screens/Detail-Ing/DetailIngViewController.swift index df467f4ab..fce9e6cb2 100644 --- a/Manito/Manito/Screens/Detail-Ing/DetailIngViewController.swift +++ b/Manito/Manito/Screens/Detail-Ing/DetailIngViewController.swift @@ -116,7 +116,7 @@ class DetailIngViewController: BaseViewController { renderGuideArea() } - override func render() { + override func setupLayout() { view.addSubview(manitoOpenButton) manitoOpenButton.snp.makeConstraints { $0.bottom.equalTo(view.safeAreaLayoutGuide).inset(7) @@ -146,8 +146,8 @@ class DetailIngViewController: BaseViewController { } } - override func configUI() { - super.configUI() + override func configureUI() { + super.configureUI() setupFont() setupViewLayer() setupStatusLabel() diff --git a/Manito/Manito/Screens/Detail-Ing/DetailngCodebaseViewController.swift b/Manito/Manito/Screens/Detail-Ing/DetailngCodebaseViewController.swift index 66207105d..ad9e56d41 100644 --- a/Manito/Manito/Screens/Detail-Ing/DetailngCodebaseViewController.swift +++ b/Manito/Manito/Screens/Detail-Ing/DetailngCodebaseViewController.swift @@ -244,7 +244,7 @@ final class DetailingCodebaseViewController: BaseViewController { requestRoomInfo() } - override func render() { + override func setupLayout() { view.addSubview(titleLabel) titleLabel.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide).inset(19) diff --git a/Manito/Manito/Screens/Detail-Ing/FriendListViewController.swift b/Manito/Manito/Screens/Detail-Ing/FriendListViewController.swift index 2cecf7817..02fd96b40 100644 --- a/Manito/Manito/Screens/Detail-Ing/FriendListViewController.swift +++ b/Manito/Manito/Screens/Detail-Ing/FriendListViewController.swift @@ -36,8 +36,8 @@ final class FriendListViewController: BaseViewController { setupDelegation() } - override func configUI() { - super.configUI() + override func configureUI() { + super.configureUI() friendListCollectionView.backgroundColor = .clear } diff --git a/Manito/Manito/Screens/Detail-Ing/MemoryViewController.swift b/Manito/Manito/Screens/Detail-Ing/MemoryViewController.swift index 244f7be4a..7f7c36d41 100644 --- a/Manito/Manito/Screens/Detail-Ing/MemoryViewController.swift +++ b/Manito/Manito/Screens/Detail-Ing/MemoryViewController.swift @@ -116,7 +116,7 @@ final class MemoryViewController: BaseViewController { // MARK: - life cycle - override func render() { + override func setupLayout() { view.addSubview(segmentControl) segmentControl.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide).inset(30) @@ -179,8 +179,8 @@ final class MemoryViewController: BaseViewController { } } - override func configUI() { - super.configUI() + override func configureUI() { + super.configureUI() setupAction() } @@ -292,8 +292,7 @@ extension MemoryViewController: UICollectionViewDataSource { content: memory?.memoriesWithManitto?.messages?[indexPath.item].content) } cell.didTappedImage = { [weak self] image in - let viewController = LetterImageViewController() - viewController.imageView.image = image + let viewController = LetterImageViewController(image: image) viewController.modalPresentationStyle = .fullScreen viewController.modalTransitionStyle = .crossDissolve self?.present(viewController, animated: true) diff --git a/Manito/Manito/Screens/Detail-Wait/DetailEditViewController.swift b/Manito/Manito/Screens/Detail-Wait/DetailEditViewController.swift index a3499ec6a..9f09850ee 100644 --- a/Manito/Manito/Screens/Detail-Wait/DetailEditViewController.swift +++ b/Manito/Manito/Screens/Detail-Wait/DetailEditViewController.swift @@ -11,58 +11,32 @@ import FSCalendar import SnapKit final class DetailEditViewController: BaseViewController { - private let detailWaitService: DetailWaitAPI = DetailWaitAPI(apiService: APIService()) - var didTappedChangeButton: (() -> ())? - private let roomIndex: Int - private let roomTitle: String + enum EditMode { case date case information } - var editMode: EditMode - var currentUserCount = 0 - var sliderValue = 10 - var startDateText = "" { - didSet { - calendarView.startDateText = startDateText - calendarView.setupDateRange() - } - } - var endDateText = "" { - didSet { - calendarView.endDateText = endDateText - calendarView.setupDateRange() - } - } - // MARK: - property + // MARK: - ui component - private lazy var cancelButton: UIButton = { + private let cancelButton: UIButton = { let button = UIButton(type: .system) - let buttonAction = UIAction { [weak self] _ in - self?.dismiss(animated: true) - } button.setTitle(TextLiteral.cancel, for: .normal) button.setTitleColor(.white, for: .normal) button.titleLabel?.font = .font(.regular, ofSize: 16) - button.addAction(buttonAction, for: .touchUpInside) return button }() - private let topIndicator: UIView = { + private let topIndicatorView: UIView = { let view = UIView() view.backgroundColor = .white.withAlphaComponent(0.8) view.layer.cornerRadius = 1.5 return view }() - private lazy var changeButton: UIButton = { + private let changeButton: UIButton = { let button = UIButton(type: .system) - let buttonAction = UIAction { [weak self] _ in - self?.didTapChangeButton() - } button.setTitle(TextLiteral.change, for: .normal) button.setTitleColor(.subBlue, for: .normal) button.titleLabel?.font = .font(.regular, ofSize: 16) - button.addAction(buttonAction, for: .touchUpInside) return button }() private let titleLabel: UILabel = { @@ -78,7 +52,7 @@ final class DetailEditViewController: BaseViewController { label.textColor = .white return label }() - private lazy var calendarView = CalendarView() + private let calendarView: CalendarView = CalendarView() private let tipLabel: UILabel = { let label = UILabel() label.text = TextLiteral.maxMessage @@ -86,7 +60,7 @@ final class DetailEditViewController: BaseViewController { label.font = .font(.regular, ofSize: 14) return label }() - private lazy var setMemberLabel: UILabel = { + private let setMemberLabel: UILabel = { let label = UILabel() label.text = TextLiteral.detailEditViewControllerSetMember label.font = .font(.regular, ofSize: 18) @@ -95,14 +69,14 @@ final class DetailEditViewController: BaseViewController { }() private lazy var minMemberLabel: UILabel = { let label = UILabel() - label.text = "\(Int(memberSlider.minimumValue))인" + label.text = "\(Int(self.memberSlider.minimumValue))인" label.font = .font(.regular, ofSize: 16) label.textColor = .white return label }() private lazy var maxMemberLabel: UILabel = { let label = UILabel() - label.text = "\(Int(memberSlider.maximumValue))인" + label.text = "\(Int(self.memberSlider.maximumValue))인" label.font = .font(.regular, ofSize: 16) label.textColor = .white return label @@ -113,21 +87,42 @@ final class DetailEditViewController: BaseViewController { slider.maximumValue = 15 slider.maximumTrackTintColor = .darkGrey003 slider.minimumTrackTintColor = .red001 - slider.value = Float(sliderValue) + slider.value = Float(self.sliderValue) slider.isContinuous = true slider.setThumbImage(ImageLiterals.imageSliderThumb, for: .normal) - slider.addTarget(self, action: #selector(changeMemberCount(sender:)), for: .valueChanged) return slider }() private lazy var memberCountLabel: UILabel = { let label = UILabel() - label.text = "\(sliderValue)" + TextLiteral.per + label.text = "\(self.sliderValue)" + TextLiteral.per label.font = .font(.regular, ofSize: 24) label.textColor = .white return label }() - - // MARK: - life cycle + + // MARK: - property + + private let detailWaitService: DetailWaitAPI = DetailWaitAPI(apiService: APIService()) + var didTappedChangeButton: (() -> ())? + private let roomIndex: Int + private let roomTitle: String + var editMode: EditMode + var currentUserCount: Int = 0 + var sliderValue: Int = 10 + var startDateText: String = "" { + didSet { + self.calendarView.startDateText = startDateText + self.calendarView.setupDateRange() + } + } + var endDateText: String = "" { + didSet { + self.calendarView.endDateText = endDateText + self.calendarView.setupDateRange() + } + } + + // MARK: - init init(editMode: EditMode, roomIndex: Int, title: String) { self.editMode = editMode @@ -144,128 +139,136 @@ final class DetailEditViewController: BaseViewController { print("\(#file) is dead") } - // MARK: - life cycle + // MARK: - override - override func configUI() { - super.configUI() + override func viewDidLoad() { + super.viewDidLoad() + self.setupCalendarChangeButton() + self.setupCancleButton() + self.setupChangeButton() + self.setupMemberSlider() + } + + override func configureUI() { + super.configureUI() self.navigationController?.isNavigationBarHidden = true self.presentationController?.delegate = self - isModalInPresentation = true - setupChangedButton() + self.isModalInPresentation = true } - override func render() { - view.addSubview(cancelButton) - cancelButton.snp.makeConstraints { + override func setupLayout() { + self.view.addSubview(self.cancelButton) + self.cancelButton.snp.makeConstraints { $0.top.equalToSuperview().inset(24) $0.leading.equalToSuperview().inset(29) $0.width.height.equalTo(44) } - view.addSubview(changeButton) - changeButton.snp.makeConstraints { + self.view.addSubview(self.changeButton) + self.changeButton.snp.makeConstraints { $0.top.equalToSuperview().inset(24) $0.trailing.equalToSuperview().inset(29) $0.width.height.equalTo(44) } - view.addSubview(topIndicator) - topIndicator.snp.makeConstraints { + self.view.addSubview(self.topIndicatorView) + self.topIndicatorView.snp.makeConstraints { $0.top.equalToSuperview().inset(8) $0.centerX.equalToSuperview() $0.width.equalTo(40) $0.height.equalTo(3) } - view.addSubview(titleLabel) - titleLabel.snp.makeConstraints { + self.view.addSubview(self.titleLabel) + self.titleLabel.snp.makeConstraints { $0.centerX.equalToSuperview() - $0.centerY.equalTo(cancelButton.snp.centerY) + $0.centerY.equalTo(self.cancelButton.snp.centerY) } - view.addSubview(startSettingLabel) - startSettingLabel.snp.makeConstraints { - $0.top.equalTo(cancelButton.snp.bottom).offset(51) + self.view.addSubview(self.startSettingLabel) + self.startSettingLabel.snp.makeConstraints { + $0.top.equalTo(self.cancelButton.snp.bottom).offset(51) $0.leading.equalToSuperview().inset(Size.leadingTrailingPadding) } - view.addSubview(calendarView) - calendarView.snp.makeConstraints { - $0.top.equalTo(startSettingLabel.snp.bottom).offset(30) + self.view.addSubview(self.calendarView) + self.calendarView.snp.makeConstraints { + $0.top.equalTo(self.startSettingLabel.snp.bottom).offset(30) $0.leading.trailing.equalToSuperview().inset(Size.leadingTrailingPadding) $0.height.equalTo(400) } - view.addSubview(tipLabel) - tipLabel.snp.makeConstraints { - $0.top.equalTo(calendarView.snp.bottom).offset(8) + self.view.addSubview(tipLabel) + self.tipLabel.snp.makeConstraints { + $0.top.equalTo(self.calendarView.snp.bottom).offset(8) $0.trailing.equalToSuperview().inset(25) } - if editMode == .information { - view.addSubview(setMemberLabel) - setMemberLabel.snp.makeConstraints { - $0.top.equalTo(calendarView.snp.bottom).offset(60) + if self.editMode == .information { + self.view.addSubview(self.setMemberLabel) + self.setMemberLabel.snp.makeConstraints { + $0.top.equalTo(self.calendarView.snp.bottom).offset(60) $0.leading.equalToSuperview().inset(Size.leadingTrailingPadding) } - view.addSubview(minMemberLabel) - minMemberLabel.snp.makeConstraints { - $0.top.equalTo(setMemberLabel.snp.bottom).offset(30) + self.view.addSubview(self.minMemberLabel) + self.minMemberLabel.snp.makeConstraints { + $0.top.equalTo(self.setMemberLabel.snp.bottom).offset(30) $0.leading.equalToSuperview().inset(24) } - view.addSubview(memberSlider) - memberSlider.snp.makeConstraints { - $0.leading.equalTo(minMemberLabel.snp.trailing).offset(5) + self.view.addSubview(self.memberSlider) + self.memberSlider.snp.makeConstraints { + $0.leading.equalTo(self.minMemberLabel.snp.trailing).offset(5) $0.height.equalTo(45) - $0.centerY.equalTo(minMemberLabel.snp.centerY) + $0.centerY.equalTo(self.minMemberLabel.snp.centerY) } - view.addSubview(maxMemberLabel) - maxMemberLabel.snp.makeConstraints { - $0.top.equalTo(setMemberLabel.snp.bottom).offset(30) - $0.leading.equalTo(memberSlider.snp.trailing).offset(5) + self.view.addSubview(self.maxMemberLabel) + self.maxMemberLabel.snp.makeConstraints { + $0.top.equalTo(self.setMemberLabel.snp.bottom).offset(30) + $0.leading.equalTo(self.memberSlider.snp.trailing).offset(5) $0.trailing.equalToSuperview().inset(24) } - view.addSubview(memberCountLabel) - memberCountLabel.snp.makeConstraints { + self.view.addSubview(self.memberCountLabel) + self.memberCountLabel.snp.makeConstraints { $0.centerX.equalToSuperview() - $0.centerY.equalTo(setMemberLabel.snp.centerY) + $0.centerY.equalTo(self.setMemberLabel.snp.centerY) } } } + + // MARK: - func - // MARK: - API + private func setupCancleButton() { + let action = UIAction { [weak self] _ in + self?.dismiss(animated: true) + } + self.cancelButton.addAction(action, for: .touchUpInside) + } - private func putChangeRoomInfo(roomDto: RoomDTO) { - Task { - do { - let status = try await detailWaitService.editRoomInfo(roomId: "\(roomIndex)", roomInfo: roomDto) - if status == 204 { - ToastView.showToast(message: "λ°© 정보 μˆ˜μ • μ™„λ£Œ", controller: self) - didTappedChangeButton?() - dismiss(animated: true) - } - } catch NetworkError.serverError { - print("server Error") - } catch NetworkError.encodingError { - print("encoding Error") - } catch NetworkError.clientError(let message) { - print("client Error: \(String(describing: message))") - } + private func setupChangeButton() { + let action = UIAction { [weak self] _ in + self?.didTapChangeButton() } + self.changeButton.addAction(action, for: .touchUpInside) + } + + private func setupMemberSlider() { + let valueChangeAction = UIAction { [weak self] action in + guard let sender = action.sender as? UISlider else { return } + self?.changeMemberCount(sender: sender) + } + self.memberSlider.addAction(valueChangeAction, for: .valueChanged) } - - // MARK: - func private func presentationControllerDidAttemptToDismissAlert() { - guard calendarView.isFirstTap else { - dismiss(animated: true) + guard self.calendarView.isFirstTap else { + self.dismiss(animated: true) return } - showDiscardChangAlert() + self.showDiscardChangAlert() } private func showDiscardChangAlert() { @@ -274,11 +277,13 @@ final class DetailEditViewController: BaseViewController { let actions: [((UIAlertAction) -> Void)?] = [{ [weak self] _ in self?.dismiss(animated: true) }, nil] - makeActionSheet(actionTitles: actionTitles, actionStyle: actionStyle, actions: actions) + makeActionSheet(actionTitles: actionTitles, + actionStyle: actionStyle, + actions: actions) } - private func setupChangedButton() { - calendarView.changeButtonState = { [weak self] value in + private func setupCalendarChangeButton() { + self.calendarView.changeButtonState = { [weak self] value in self?.changeButton.isEnabled = value self?.changeButton.setTitleColor(.subBlue, for: .normal) self?.changeButton.setTitleColor(.grey002, for: .disabled) @@ -286,34 +291,56 @@ final class DetailEditViewController: BaseViewController { } private func didTapChangeButton() { - let dto = RoomDTO(title: roomTitle, - capacity: Int(memberSlider.value), - startDate: "20\(calendarView.getTempStartDate())", - endDate: "20\(calendarView.getTempEndDate())") - switch editMode { + let dto = RoomDTO(title: self.roomTitle, + capacity: Int(self.memberSlider.value), + startDate: "20\(self.calendarView.getTempStartDate())", + endDate: "20\(self.calendarView.getTempEndDate())") + switch self.editMode { case .date: - putChangeRoomInfo(roomDto: dto) + self.putChangeRoomInfo(roomDto: dto) case .information: - if currentUserCount <= sliderValue { - putChangeRoomInfo(roomDto: dto) + if self.currentUserCount <= self.sliderValue { + self.putChangeRoomInfo(roomDto: dto) } else { - makeAlert(title: TextLiteral.detailEditViewControllerChangeRoomInfoAlertTitle, message: TextLiteral.detailEditViewControllerChangeRoomInfoAlertMessage) + self.makeAlert(title: TextLiteral.detailEditViewControllerChangeRoomInfoAlertTitle, + message: TextLiteral.detailEditViewControllerChangeRoomInfoAlertMessage) } } } - // MARK: - selector - - @objc private func changeMemberCount(sender: UISlider) { - sliderValue = Int(sender.value) - memberCountLabel.text = String(Int(sender.value)) + TextLiteral.per - memberCountLabel.font = .font(.regular, ofSize: 24) - memberCountLabel.textColor = .white + private func changeMemberCount(sender: UISlider) { + self.sliderValue = Int(sender.value) + self.memberCountLabel.text = String(Int(sender.value)) + TextLiteral.per + self.memberCountLabel.font = .font(.regular, ofSize: 24) + self.memberCountLabel.textColor = .white + } + + // MARK: - network + + private func putChangeRoomInfo(roomDto: RoomDTO) { + Task { + do { + let status = try await self.detailWaitService.editRoomInfo(roomId: "\(roomIndex)", + roomInfo: roomDto) + if status == 204 { + ToastView.showToast(message: "λ°© 정보 μˆ˜μ • μ™„λ£Œ", + controller: self) + self.didTappedChangeButton?() + self.dismiss(animated: true) + } + } catch NetworkError.serverError { + print("server Error") + } catch NetworkError.encodingError { + print("encoding Error") + } catch NetworkError.clientError(let message) { + print("client Error: \(String(describing: message))") + } + } } } extension DetailEditViewController: UIAdaptivePresentationControllerDelegate { func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) { - presentationControllerDidAttemptToDismissAlert() + self.presentationControllerDidAttemptToDismissAlert() } } diff --git a/Manito/Manito/Screens/Detail-Wait/DetailWaitViewController.swift b/Manito/Manito/Screens/Detail-Wait/DetailWaitViewController.swift index 602ff26af..2443ec176 100644 --- a/Manito/Manito/Screens/Detail-Wait/DetailWaitViewController.swift +++ b/Manito/Manito/Screens/Detail-Wait/DetailWaitViewController.swift @@ -10,66 +10,23 @@ import UIKit import SnapKit final class DetailWaitViewController: BaseViewController { - private var room: Room? - private let detailWaitService: DetailWaitAPI = DetailWaitAPI(apiService: APIService()) - private let roomIndex: Int - var roomInformation: ParticipatingRoom? - private var roomInfo: RoomDTO? - private var userArr: [String] = [] { - didSet { - renderTableView() - } - } - private var detectStartableStatus: ((Bool) -> ())? - private var memberType = UserStatus.member { - didSet { - settingButton.menu = setExitButtonMenu() - setupTitleViewGesture() - } - } private enum UserStatus: CaseIterable { case owner case member - var alertText: AlertText { + var alertText: (title: String, + message: String, + okTitle: String) { switch self { case .owner: - return .delete + return (title: TextLiteral.datailWaitViewControllerDeleteTitle, + message: TextLiteral.datailWaitViewControllerDeleteMessage, + okTitle: TextLiteral.delete) case .member: - return .exit - } - } - } - - private enum AlertText { - case delete - case exit - - var title: String { - switch self { - case .delete: - return TextLiteral.datailWaitViewControllerDeleteTitle - case .exit: - return TextLiteral.datailWaitViewControllerExitTitle - } - } - - var message: String { - switch self { - case .delete: - return TextLiteral.datailWaitViewControllerDeleteMessage - case .exit: - return TextLiteral.datailWaitViewControllerExitMessage - } - } - - var okTitle: String { - switch self { - case .delete: - return TextLiteral.delete - case .exit: - return TextLiteral.leave + return (title: TextLiteral.datailWaitViewControllerExitTitle, + message: TextLiteral.datailWaitViewControllerExitMessage, + okTitle: TextLiteral.leave) } } } @@ -88,15 +45,14 @@ final class DetailWaitViewController: BaseViewController { } } - // MARK: - property + // MARK: - ui component - private lazy var settingButton: UIButton = { + private let moreButton: UIButton = { let button = MoreButton() - button.menu = setExitButtonMenu() button.showsMenuAsPrimaryAction = true return button }() - private let titleView = DetailWaitTitleView() + private let titleView: DetailWaitTitleView = DetailWaitTitleView() private let togetherFriendLabel: UILabel = { let label = UILabel() label.text = TextLiteral.togetherFriend @@ -109,34 +65,29 @@ final class DetailWaitViewController: BaseViewController { imageView.image = ImageLiterals.imgNi return imageView }() - private lazy var comeInLabel: UILabel = { + private let userCountLabel: UILabel = { let label = UILabel() label.textColor = .white label.font = .font(.regular, ofSize: 14) return label }() - private lazy var copyButton: UIButton = { + private let copyButton: UIButton = { let button = UIButton(type: .system) - let buttonAction = UIAction { [weak self] _ in - if let code = self?.room?.invitation?.code { - ToastView.showToast(code: code ,message: TextLiteral.detailWaitViewControllerCopyCode, controller: self ?? UIViewController()) - } - } button.setTitle(TextLiteral.copyCode, for: .normal) button.setTitleColor(.subBlue, for: .normal) button.titleLabel?.font = .font(.regular, ofSize: 16) - button.addAction(buttonAction, for: .touchUpInside) return button }() - private let listTable: UITableView = { - let table = UITableView() - table.layer.cornerRadius = 10 - table.isScrollEnabled = false - return table + private let listTableView: UITableView = { + let tableView = UITableView() + tableView.layer.cornerRadius = 10 + tableView.isScrollEnabled = false + tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") + return tableView }() private lazy var startButton: UIButton = { let button = MainButton() - detectStartableStatus = { value in + self.detectStartableStatus = { value in if value { button.title = ButtonText.start.status button.isDisabled = false @@ -151,11 +102,31 @@ final class DetailWaitViewController: BaseViewController { } return button }() + + // MARK: - property + + private var room: Room? + private let detailWaitService: DetailWaitAPI = DetailWaitAPI(apiService: APIService()) + private let roomIndex: Int + var roomInformation: ParticipatingRoom? + private var roomInfo: RoomDTO? + private var userArr: [String] = [] { + didSet { + self.setupLayoutTableView() + } + } + private var detectStartableStatus: ((Bool) -> ())? + private var memberType = UserStatus.member { + didSet { + self.moreButton.menu = self.setExitButtonMenu() + self.setupTitleViewGesture() + } + } // MARK: - init init(index: Int) { - roomIndex = index + self.roomIndex = index super.init() } @@ -171,161 +142,80 @@ final class DetailWaitViewController: BaseViewController { override func viewDidLoad() { super.viewDidLoad() - requestWaitRoomInfo() - setupDelegation() - setupNotificationCenter() + self.requestWaitRoomInfo() + self.setupDelegation() + self.setupNotificationCenter() + self.setupCopyButton() } + + // MARK: - override - override func render() { - view.addSubview(titleView) - titleView.snp.makeConstraints { + override func setupLayout() { + self.view.addSubview(self.titleView) + self.titleView.snp.makeConstraints { $0.leading.trailing.equalToSuperview().inset(Size.leadingTrailingPadding) $0.top.equalToSuperview().offset(100) $0.height.equalTo(86) } - view.addSubview(togetherFriendLabel) - togetherFriendLabel.snp.makeConstraints { + self.view.addSubview(self.togetherFriendLabel) + self.togetherFriendLabel.snp.makeConstraints { $0.leading.equalToSuperview().inset(Size.leadingTrailingPadding) $0.top.equalTo(titleView.snp.bottom).offset(44) } - view.addSubview(imgNiView) - imgNiView.snp.makeConstraints { - $0.centerY.equalTo(togetherFriendLabel.snp.centerY) - $0.leading.equalTo(togetherFriendLabel.snp.trailing).offset(7) + self.view.addSubview(self.imgNiView) + self.imgNiView.snp.makeConstraints { + $0.centerY.equalTo(self.togetherFriendLabel.snp.centerY) + $0.leading.equalTo(self.togetherFriendLabel.snp.trailing).offset(7) $0.width.height.equalTo(30) } - view.addSubview(comeInLabel) - comeInLabel.snp.makeConstraints { - $0.leading.equalTo(imgNiView.snp.trailing) - $0.centerY.equalTo(imgNiView.snp.centerY) + self.view.addSubview(self.userCountLabel) + self.userCountLabel.snp.makeConstraints { + $0.leading.equalTo(self.imgNiView.snp.trailing) + $0.centerY.equalTo(self.imgNiView.snp.centerY) } - view.addSubview(copyButton) - copyButton.snp.makeConstraints { + self.view.addSubview(self.copyButton) + self.copyButton.snp.makeConstraints { $0.trailing.equalToSuperview().inset(Size.leadingTrailingPadding) - $0.centerY.equalTo(togetherFriendLabel.snp.centerY) + $0.centerY.equalTo(self.togetherFriendLabel.snp.centerY) } - view.addSubview(startButton) - startButton.snp.makeConstraints { + self.view.addSubview(self.startButton) + self.startButton.snp.makeConstraints { $0.leading.trailing.equalToSuperview().inset(Size.leadingTrailingPadding) $0.bottom.equalToSuperview().inset(65) $0.height.equalTo(60) } } - override func configUI() { - super.configUI() - setupSettingButton() - } - - // MARK: - API - - private func requestWaitRoomInfo() { - Task { - do { - let data = try await detailWaitService.getWaitingRoomInfo(roomId: "\(roomIndex)") - if let roomInfo = data { - guard let title = roomInfo.roomInformation?.title, - let state = roomInfo.roomInformation?.state, - let members = roomInfo.participants?.members, - let isAdmin = roomInfo.admin else { return } - self.room = data - titleView.setStartState(state: state) - userArr = members.map { $0.nickname ?? "" } - memberType = isAdmin ? .owner : .member - self.roomInfo = RoomDTO(title: title, - capacity: data?.roomInformation?.capacity ?? 15, - startDate: data?.roomInformation?.startDate ?? "", - endDate: data?.roomInformation?.endDate ?? "") - isPastStartDate() - setStartButton() - DispatchQueue.main.async { - self.comeInLabel.text = data?.userCount - self.titleView.setRoomTitleLabelText(text: title) - self.titleView.setDurationDateLabel(text: roomInfo.roomInformation?.dateRange ?? "") - } - } - } catch NetworkError.serverError { - print("server Error") - } catch NetworkError.encodingError { - print("encoding Error") - } catch NetworkError.clientError(let message) { - print("client Error: \(String(describing: message))") - } - } - } - - private func requestStartManitto() { - Task { - do { - let data = try await detailWaitService.startManitto(roomId: "\(roomIndex)") - if let manittee = data { - let storyboard = UIStoryboard(name: "Interaction", bundle: nil) - guard let viewController = storyboard.instantiateViewController(withIdentifier: SelectManittoViewController.className) as? SelectManittoViewController else { return } - guard let nickname = manittee.nickname else { return } - viewController.modalPresentationStyle = .fullScreen - viewController.manitteeName = nickname - viewController.roomId = roomInformation?.id?.description - present(viewController, animated: true) - } - } catch NetworkError.serverError { - print("server Error") - } catch NetworkError.encodingError { - print("encoding Error") - } catch NetworkError.clientError(let message) { - print("client Error: \(String(describing: message))") - } - } - } - - private func requestDeleteRoom() { - Task { - do { - let status = try await detailWaitService.deleteRoom(roomId: "\(roomIndex)") - if status == 204 { - navigationController?.popViewController(animated: true) - } - } catch NetworkError.serverError { - print("server Error") - } catch NetworkError.encodingError { - print("encoding Error") - } catch NetworkError.clientError(let message) { - print("client Error: \(String(describing: message))") - } - } - } - - private func requestDeleteLeaveRoom() { - Task { - do { - let status = try await detailWaitService.deleteLeaveRoom(roomId: "\(roomIndex)") - if status == 204 { - navigationController?.popViewController(animated: true) - } - } catch NetworkError.serverError { - print("server Error") - } catch NetworkError.encodingError { - print("encoding Error") - } catch NetworkError.clientError(let message) { - print("client Error: \(String(describing: message))") - } - } + override func configureUI() { + super.configureUI() + self.setupSettingButton() } // MARK: - func private func setupDelegation() { - listTable.delegate = self - listTable.dataSource = self - listTable.register(UITableViewCell.self, forCellReuseIdentifier: "cell") + self.listTableView.delegate = self + self.listTableView.dataSource = self + } + + private func setupCopyButton() { + let action = UIAction { [weak self] _ in + if let code = self?.room?.invitation?.code { + ToastView.showToast(code: code, + message: TextLiteral.detailWaitViewControllerCopyCode, + controller: self ?? UIViewController()) + } + } + copyButton.addAction(action, for: .touchUpInside) } private func presentDetailEditViewController(startString: String, endString: String, isDateEdit: Bool) { - guard let title = titleView.roomTitleLabel.text else { return } + guard let title = self.titleView.roomTitleLabel.text else { return } let viewController = DetailEditViewController(editMode: isDateEdit ? .date : .information, roomIndex: roomIndex, title: title) @@ -338,117 +228,111 @@ final class DetailWaitViewController: BaseViewController { viewController.sliderValue = capacity viewController.startDateText = startString viewController.endDateText = endString - present(viewController, animated: true, completion: nil) + self.present(viewController, animated: true, completion: nil) } - // MARK: - private func - private func setupSettingButton() { - let rightOffsetSettingButton = super.removeBarButtonItemOffset(with: settingButton, offsetX: -10) + let rightOffsetSettingButton = super.removeBarButtonItemOffset(with: moreButton, + offsetX: -10) let settingButton = super.makeBarButtonItem(with: rightOffsetSettingButton) - navigationItem.rightBarButtonItem = settingButton + self.navigationItem.rightBarButtonItem = settingButton } private func setExitButtonMenu() -> UIMenu { - switch memberType { - case .owner: - let menu = UIMenu(options: [], children: [ - UIAction(title: TextLiteral.modifiedRoomInfo, handler: { [weak self] _ in - self?.presentEditRoomView() - }), - UIAction(title: TextLiteral.detailWaitViewControllerDeleteRoom, handler: { [weak self] _ in - self?.makeRequestAlert(title: UserStatus.owner.alertText.title, message: UserStatus.owner.alertText.message, okTitle: UserStatus.owner.alertText.okTitle, okAction: { _ in - self?.requestDeleteRoom() - }) - })]) - return menu - case .member: - let menu = UIMenu(options: [], children: [ - UIAction(title: TextLiteral.detailWaitViewControllerLeaveRoom, handler: { [weak self] _ in - self?.makeRequestAlert(title: UserStatus.member.alertText.title, message: UserStatus.member.alertText.message, okTitle: UserStatus.member.alertText.okTitle, okAction: { _ in - self?.requestDeleteLeaveRoom() - }) - }) - ]) - return menu - } + let children: [UIAction] = memberType == .owner + ? [UIAction(title: TextLiteral.modifiedRoomInfo, handler: { [weak self] _ in + self?.presentEditRoomView() + }),UIAction(title: TextLiteral.detailWaitViewControllerDeleteRoom, handler: { [weak self] _ in + self?.makeRequestAlert(title: UserStatus.owner.alertText.title, + message: UserStatus.owner.alertText.message, + okTitle: UserStatus.owner.alertText.okTitle, + okAction: { _ in + self?.requestDeleteRoom() + + }) + + }) + ] + : [UIAction(title: TextLiteral.detailWaitViewControllerLeaveRoom, handler: { [weak self] _ in + self?.makeRequestAlert(title: UserStatus.member.alertText.title, + message: UserStatus.member.alertText.message, + okTitle: UserStatus.member.alertText.okTitle, + okAction: { _ in + self?.requestDeleteLeaveRoom() + }) + })] + let menu = UIMenu(children: children) + return menu } private func presentEditRoomView() { - guard let startDate = room?.roomInformation?.startDate?.stringToDate else { return } - let isAlreadyPastDate = startDate.distance(to: Date()) > 86400 - - if isAlreadyPastDate { - editInfoFromDefaultDate() + guard let roomInformation = self.room?.roomInformation else { return } + if roomInformation.isAlreadyPastDate { + self.editInfoFromDefaultDate(isDateEdit: false) } else { - editInfoFromCurrentDate() + self.editInfoFromCurrentDate() } } - private func editInfoFromDefaultDate() { + private func editInfoFromDefaultDate(isDateEdit: Bool) { let fiveDaysInterval: TimeInterval = 86400 * 4 let defaultStartDate = Date().dateToString let defaultEndDate = (Date() + fiveDaysInterval).dateToString - self.presentDetailEditViewController(startString: defaultStartDate, endString: defaultEndDate, isDateEdit: false) + self.presentDetailEditViewController(startString: defaultStartDate, + endString: defaultEndDate, + isDateEdit: isDateEdit) } private func editInfoFromCurrentDate() { - guard let startDate = room?.roomInformation?.startDate, - let endDate = room?.roomInformation?.endDate else { return } - self.presentDetailEditViewController(startString: startDate, endString: endDate, isDateEdit: false) + guard let startDate = self.room?.roomInformation?.startDate, + let endDate = self.room?.roomInformation?.endDate else { return } + self.presentDetailEditViewController(startString: startDate, + endString: endDate, + isDateEdit: false) } private func setupNotificationCenter() { - NotificationCenter.default.addObserver(self, selector: #selector(didTapEnterButton), name: .createRoomInvitedCode, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(self.didTapEnterButton), name: .createRoomInvitedCode, object: nil) } private func isPastStartDate() { - guard let startDate = room?.roomInformation?.startDate?.stringToDate else { return } - let isPast = startDate.distance(to: Date()) > 86400 - let isToday = startDate.distance(to: Date()) < 86400 - let canStart = !isPast && isToday - if !canStart { + guard let isStart = self.room?.roomInformation?.isStart else { return } + if !isStart { switch memberType { case .owner: let action: ((UIAlertAction) -> ()) = { [weak self] _ in - let fiveDaysInterval: TimeInterval = 86400 * 4 - let startDate = Date().dateToString - let endDate = (Date() + fiveDaysInterval).dateToString - self?.presentDetailEditViewController(startString: startDate, endString: endDate, isDateEdit: true) + self?.editInfoFromDefaultDate(isDateEdit: true) } - makeAlert(title: TextLiteral.detailWaitViewControllerPastAlertTitle, message: TextLiteral.detailWaitViewControllerPastOwnerAlertMessage, okAction: action) + self.makeAlert(title: TextLiteral.detailWaitViewControllerPastAlertTitle, + message: TextLiteral.detailWaitViewControllerPastOwnerAlertMessage, + okAction: action) case .member: - makeAlert(title: TextLiteral.detailWaitViewControllerPastAlertTitle, message: TextLiteral.detailWaitViewControllerPastAlertMessage) + self.makeAlert(title: TextLiteral.detailWaitViewControllerPastAlertTitle, + message: TextLiteral.detailWaitViewControllerPastAlertMessage) } } } private func setStartButton() { if memberType == .owner { - guard let startDate = room?.roomInformation?.startDate?.stringToDate, - let todayDate = Date().dateToString.stringToDate, - let userCount = room?.participants?.count else { return } - - let isToday = startDate.distance(to: todayDate).isZero - let isMinimumUserCount = userCount >= 4 - - detectStartableStatus?(isToday && isMinimumUserCount) + guard let canStart = self.room?.canStart else { return } + self.detectStartableStatus?(canStart) } else { - detectStartableStatus?(false) + self.detectStartableStatus?(false) } } - private func renderTableView() { + private func setupLayoutTableView() { DispatchQueue.main.async { - self.listTable.reloadData() - self.view.addSubview(self.listTable) + self.listTableView.reloadData() + self.view.addSubview(self.listTableView) var tableHeight = self.userArr.count * 44 if tableHeight > 400 { tableHeight = 400 - self.listTable.isScrollEnabled = true + self.listTableView.isScrollEnabled = true } - self.listTable.snp.makeConstraints { + self.listTableView.snp.makeConstraints { $0.top.equalTo(self.togetherFriendLabel.snp.bottom).offset(30) $0.leading.trailing.equalToSuperview().inset(Size.leadingTrailingPadding) $0.centerX.equalToSuperview() @@ -458,17 +342,27 @@ final class DetailWaitViewController: BaseViewController { } private func setupTitleViewGesture() { - if memberType == .owner { - let tapGesture = UITapGestureRecognizer(target: self, action: #selector(presentEditViewController)) - titleView.addGestureRecognizer(tapGesture) + if self.memberType == .owner { + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.presentEditViewController)) + self.titleView.addGestureRecognizer(tapGesture) } } + + private func presentSelectManittoViewController(nickname: String) { + let storyboard = UIStoryboard(name: "Interaction", bundle: nil) + guard let viewController = storyboard.instantiateViewController(withIdentifier: SelectManittoViewController.className) as? SelectManittoViewController else { return } + viewController.modalPresentationStyle = .fullScreen + viewController.manitteeName = nickname + viewController.roomId = self.roomInformation?.id?.description + self.present(viewController, animated: true) + } // MARK: - selector - @objc private func didTapEnterButton() { - guard let roomInfo = roomInfo, - let code = room?.invitation?.code - else { return } + + @objc + private func didTapEnterButton() { + guard let roomInfo = self.roomInfo, + let code = self.room?.invitation?.code else { return } let viewController = InvitedCodeViewController(roomInfo: RoomDTO(title: roomInfo.title, capacity: roomInfo.capacity, startDate: roomInfo.startDate, @@ -477,17 +371,107 @@ final class DetailWaitViewController: BaseViewController { viewController.roomInfo = roomInfo viewController.modalPresentationStyle = .overCurrentContext viewController.modalTransitionStyle = .crossDissolve - present(viewController, animated: true) + self.present(viewController, animated: true) } - @objc private func presentEditViewController() { - guard let startDate = room?.roomInformation?.startDate, - let endDate = room?.roomInformation?.endDate else { return } - self.presentDetailEditViewController(startString: startDate, endString: endDate, isDateEdit: false) + @objc + private func presentEditViewController() { + guard let startDate = self.room?.roomInformation?.startDate, + let endDate = self.room?.roomInformation?.endDate else { return } + self.presentDetailEditViewController(startString: startDate, + endString: endDate, + isDateEdit: false) } - @objc private func changeStartButton() { - setStartButton() + @objc + private func changeStartButton() { + self.setStartButton() + } + + // MARK: - network + + private func requestWaitRoomInfo() { + Task { + do { + let data = try await self.detailWaitService.getWaitingRoomInfo(roomId: "\(roomIndex)") + if let roomInfo = data { + guard let title = roomInfo.roomInformation?.title, + let state = roomInfo.roomInformation?.state, + let participants = roomInfo.participants, + let isAdmin = roomInfo.admin else { return } + self.room = roomInfo + self.userArr = participants.membersNickname + self.memberType = isAdmin ? .owner : .member + self.roomInfo = roomInfo.roomDTO + self.setStartButton() + DispatchQueue.main.async { + self.isPastStartDate() + self.titleView.setStartState(state: state) + self.userCountLabel.text = roomInfo.userCount + self.titleView.setRoomTitleLabelText(text: title) + self.titleView.setDurationDateLabel(text: roomInfo.roomInformation?.dateRange ?? "") + } + } + } catch NetworkError.serverError { + print("server Error") + } catch NetworkError.encodingError { + print("encoding Error") + } catch NetworkError.clientError(let message) { + print("client Error: \(String(describing: message))") + } + } + } + + private func requestStartManitto() { + Task { + do { + let data = try await self.detailWaitService.startManitto(roomId: "\(roomIndex)") + if let manittee = data { + guard let nickname = manittee.nickname else { return } + self.presentSelectManittoViewController(nickname: nickname) + } + } catch NetworkError.serverError { + print("server Error") + } catch NetworkError.encodingError { + print("encoding Error") + } catch NetworkError.clientError(let message) { + print("client Error: \(String(describing: message))") + } + } + } + + private func requestDeleteRoom() { + Task { + do { + let status = try await self.detailWaitService.deleteRoom(roomId: "\(roomIndex)") + if status == 204 { + self.navigationController?.popViewController(animated: true) + } + } catch NetworkError.serverError { + print("server Error") + } catch NetworkError.encodingError { + print("encoding Error") + } catch NetworkError.clientError(let message) { + print("client Error: \(String(describing: message))") + } + } + } + + private func requestDeleteLeaveRoom() { + Task { + do { + let status = try await self.detailWaitService.deleteLeaveRoom(roomId: "\(roomIndex)") + if status == 204 { + self.navigationController?.popViewController(animated: true) + } + } catch NetworkError.serverError { + print("server Error") + } catch NetworkError.encodingError { + print("encoding Error") + } catch NetworkError.clientError(let message) { + print("client Error: \(String(describing: message))") + } + } } } @@ -499,12 +483,12 @@ extension DetailWaitViewController: UITableViewDelegate { extension DetailWaitViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return userArr.count + return self.userArr.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = listTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell - cell.textLabel?.text = userArr[indexPath.row] + let cell = self.listTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell + cell.textLabel?.text = self.userArr[indexPath.row] cell.textLabel?.font = .font(.regular, ofSize: 17) cell.backgroundColor = .darkGrey003 cell.selectionStyle = .none diff --git a/Manito/Manito/Screens/Detail-Wait/UIComponent/CalendarView.swift b/Manito/Manito/Screens/Detail-Wait/UIComponent/CalendarView.swift index 606a6371e..13c09f43a 100644 --- a/Manito/Manito/Screens/Detail-Wait/UIComponent/CalendarView.swift +++ b/Manito/Manito/Screens/Detail-Wait/UIComponent/CalendarView.swift @@ -10,16 +10,7 @@ import UIKit import FSCalendar import SnapKit -class CalendarView: UIView { - private var selectStartDate = Date() - private let oneDayInterval: TimeInterval = 86400 - private let sevenDaysInterval: TimeInterval = 604800 - var changeButtonState: ((Bool) -> ())? - var startDateText = "" - var endDateText = "" - private var tempStartDateText = "" - private var tempEndDateText = "" - var isFirstTap = false +final class CalendarView: UIView { private enum CalendarMoveType { case previous @@ -35,24 +26,16 @@ class CalendarView: UIView { } } - // MARK: - property + // MARK: - ui component - private lazy var previousButton: UIButton = { + private let previousButton: UIButton = { let button = UIButton() - let action = UIAction { [weak self] _ in - self?.changeMonth(with: CalendarMoveType.previous) - } button.setImage(ImageLiterals.icBack, for: .normal) - button.addAction(action, for: .touchUpInside) return button }() - private lazy var nextButton: UIButton = { + private let nextButton: UIButton = { let button = UIButton() - let action = UIAction { [weak self] _ in - self?.changeMonth(with: CalendarMoveType.next) - } button.setImage(ImageLiterals.icRight, for: .normal) - button.addAction(action, for: .touchUpInside) return button }() private var calendar: FSCalendar = { @@ -74,159 +57,194 @@ class CalendarView: UIView { calendar.appearance.todayColor = .clear return calendar }() + + // MARK: - property + + private var selectStartDate: Date = Date() + private let oneDayInterval: TimeInterval = 86400 + private let sevenDaysInterval: TimeInterval = 604800 + var changeButtonState: ((Bool) -> ())? + var startDateText: String = "" + var endDateText: String = "" + private var tempStartDateText: String = "" + private var tempEndDateText: String = "" + var isFirstTap: Bool = false // MARK: - init override init(frame: CGRect) { super.init(frame: frame) - render() - setupDelegation() - setupDateRange() + self.setupLayout() + self.setupDelegation() + self.setupDateRange() + self.setupPreviousButton() + self.setupNextButton() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + // MARK: - func - private func render() { - self.addSubview(calendar) - calendar.snp.makeConstraints { + private func setupLayout() { + self.addSubview(self.calendar) + self.calendar.snp.makeConstraints { $0.edges.equalToSuperview() } - self.addSubview(previousButton) - previousButton.snp.makeConstraints { + self.addSubview(self.previousButton) + self.previousButton.snp.makeConstraints { $0.top.equalToSuperview().inset(5) $0.leading.equalToSuperview().inset(70) } - self.addSubview(nextButton) - nextButton.snp.makeConstraints { + self.addSubview(self.nextButton) + self.nextButton.snp.makeConstraints { $0.top.equalToSuperview().inset(5) $0.trailing.equalToSuperview().inset(72) } } + private func setupPreviousButton() { + let action = UIAction { [weak self] _ in + self?.changeMonth(with: .previous) + } + self.previousButton.addAction(action, for: .touchUpInside) + } + private func setupNextButton() { + let action = UIAction { [weak self] _ in + self?.changeMonth(with: CalendarMoveType.next) + } + self.nextButton.addAction(action, for: .touchUpInside) + } + func setupButtonState() { - let hasDate = tempStartDateText != "" && tempEndDateText != "" - changeButtonState?(hasDate) + let hasDate = self.tempStartDateText != "" && self.tempEndDateText != "" + self.changeButtonState?(hasDate) } - // MARK: - func - private func setupDelegation() { - calendar.delegate = self - calendar.dataSource = self + self.calendar.delegate = self + self.calendar.dataSource = self } private func changeMonth(with type: CalendarMoveType) { let todayCalendar = Calendar.current - let currentPage = calendar.currentPage + let currentPage = self.calendar.currentPage var dateComponents = DateComponents() dateComponents.month = type.month guard let changedCurrentPage = todayCalendar.date(byAdding: dateComponents, to: currentPage) else { return } - calendar.setCurrentPage(changedCurrentPage, animated: true) + self.calendar.setCurrentPage(changedCurrentPage, animated: true) } func setupDateRange() { - guard let startDate = startDateText.stringToDate else { return } - guard let endDate = endDateText.stringToDate else { return } - setupCalendarRange(startDate: startDate, endDate: endDate) + guard let startDate = self.startDateText.stringToDate else { return } + guard let endDate = self.endDateText.stringToDate else { return } + self.setupCalendarRange(startDate: startDate, endDate: endDate) } private func setupCalendarRange(startDate: Date, endDate: Date) { - calendar.select(startDate) - calendar.select(endDate) - setDateRange() + self.calendar.select(startDate) + self.calendar.select(endDate) + self.setDateRange() } func setDateRange() { - guard countDateRange() <= 7 else { return } + guard self.countDateRange() <= 7 else { return } - let isFirstClickPastDate = calendar.selectedDates[0] < calendar.selectedDates[1] + let isFirstClickPastDate = self.calendar.selectedDates[0] < self.calendar.selectedDates[1] if isFirstClickPastDate { - setSelecteDate(startIndex: 0, endIndex: 1) + self.setSelecteDate(startIndex: 0, + endIndex: 1) } else { - setSelecteDate(startIndex: 1, endIndex: 0) + self.setSelecteDate(startIndex: 1, + endIndex: 0) } } func setSelecteDate(startIndex: Int, endIndex: Int) { - var startDate = calendar.selectedDates[startIndex] - while startDate < calendar.selectedDates[endIndex] { - guard let addDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate) else { return } - calendar.select(addDate) - startDate += oneDayInterval + var startDate = self.calendar.selectedDates[startIndex] + while startDate < self.calendar.selectedDates[endIndex] { + guard let addDate = Calendar.current.date(byAdding: .day, + value: 1, + to: startDate) else { return } + self.calendar.select(addDate) + startDate += self.oneDayInterval } - tempStartDateText = calendar.selectedDates[startIndex].dateToString - tempEndDateText = calendar.selectedDates[endIndex].dateToString + self.tempStartDateText = self.calendar.selectedDates[startIndex].dateToString + self.tempEndDateText = self.calendar.selectedDates[endIndex].dateToString } func countDateRange() -> Int { - let isFirstClickPastDate = calendar.selectedDates[0] < calendar.selectedDates[1] - let selectdDate = isFirstClickPastDate ? calendar.selectedDates[1].timeIntervalSince(calendar.selectedDates[0]) : calendar.selectedDates[0].timeIntervalSince(calendar.selectedDates[1]) + let isFirstClickPastDate = self.calendar.selectedDates[0] < self.calendar.selectedDates[1] + let selectdDate = isFirstClickPastDate + ? self.calendar.selectedDates[1].timeIntervalSince(self.calendar.selectedDates[0]) + : self.calendar.selectedDates[0].timeIntervalSince(self.calendar.selectedDates[1]) let dateRangeCount = selectdDate / 86400 return Int(dateRangeCount) + 1 } func getTempStartDate() -> String { - return tempStartDateText + return self.tempStartDateText } func getTempEndDate() -> String { - return tempEndDateText + return self.tempEndDateText } } extension CalendarView: FSCalendarDelegate { func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) { - isFirstTap = true + self.isFirstTap = true let isCreatedRoomOnlySelectedStartDate = calendar.selectedDates.count == 1 let isSelectedDateRange = calendar.selectedDates.count == 2 let isReclickedStartDate = calendar.selectedDates.count > 2 if isCreatedRoomOnlySelectedStartDate { - selectStartDate = date - calendar.select(selectStartDate) + self.selectStartDate = date + calendar.select(self.selectStartDate) calendar.reloadData() } else if isSelectedDateRange { - tempEndDateText = date.dateToString - if countDateRange() > 7 { + self.tempEndDateText = date.dateToString + if self.countDateRange() > 7 { calendar.deselect(date) - viewController?.makeAlert(title: TextLiteral.calendarViewAlertMaxTitle, message: TextLiteral.maxMessage) + self.viewController?.makeAlert(title: TextLiteral.calendarViewAlertMaxTitle, + message: TextLiteral.maxMessage) } else { - setDateRange() + self.setDateRange() calendar.reloadData() } } else if isReclickedStartDate { - tempStartDateText = date.dateToString - tempEndDateText = "" + self.tempStartDateText = date.dateToString + self.tempEndDateText = "" (calendar.selectedDates).forEach { calendar.deselect($0) } - selectStartDate = date - calendar.select(selectStartDate) + self.selectStartDate = date + calendar.select(self.selectStartDate) calendar.reloadData() } - setupButtonState() + self.setupButtonState() } func calendar(_ calendar: FSCalendar, didDeselect date: Date, at monthPosition: FSCalendarMonthPosition) { - tempEndDateText = "" - isFirstTap = true + self.tempEndDateText = "" + self.isFirstTap = true (calendar.selectedDates).forEach { calendar.deselect($0) } - selectStartDate = date + self.selectStartDate = date calendar.select(date) calendar.reloadData() - setupButtonState() + self.setupButtonState() } func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool { - if date < Date() - oneDayInterval { - viewController?.makeAlert(title: TextLiteral.calendarViewAlertPastTitle, message: TextLiteral.calendarViewAlertPastMessage) + if date < Date() - self.oneDayInterval { + self.viewController?.makeAlert(title: TextLiteral.calendarViewAlertPastTitle, + message: TextLiteral.calendarViewAlertPastMessage) return false } else { return true @@ -234,8 +252,8 @@ extension CalendarView: FSCalendarDelegate { } func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, titleDefaultColorFor date: Date) -> UIColor? { - let isBeforeToday = date < Date() - oneDayInterval - let isAWeekBeforeAfter = date < selectStartDate + sevenDaysInterval && date > selectStartDate - sevenDaysInterval + let isBeforeToday = date < Date() - self.oneDayInterval + let isAWeekBeforeAfter = date < self.selectStartDate + self.sevenDaysInterval && date > self.selectStartDate - self.sevenDaysInterval let isDoneSelectedDate = calendar.selectedDates.count > 2 if isBeforeToday { return .grey004.withAlphaComponent(0.4) diff --git a/Manito/Manito/Screens/Detail-Wait/UIComponent/DetailWaitTitleView.swift b/Manito/Manito/Screens/Detail-Wait/UIComponent/DetailWaitTitleView.swift index 6ddef56b4..a909fce63 100644 --- a/Manito/Manito/Screens/Detail-Wait/UIComponent/DetailWaitTitleView.swift +++ b/Manito/Manito/Screens/Detail-Wait/UIComponent/DetailWaitTitleView.swift @@ -28,7 +28,7 @@ final class DetailWaitTitleView: UIView { } } - // MARK: - property + // MARK: - ui component private(set) var roomTitleLabel: UILabel = { let label = UILabel() @@ -75,67 +75,67 @@ final class DetailWaitTitleView: UIView { override init(frame: CGRect) { super.init(frame: frame) - render() + self.setupLayout() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + // MARK: - func - private func render() { - self.addSubview(roomTitleLabel) - roomTitleLabel.snp.makeConstraints { + private func setupLayout() { + self.addSubview(self.roomTitleLabel) + self.roomTitleLabel.snp.makeConstraints { $0.leading.top.equalToSuperview() } - self.addSubview(startStautsLabel) - startStautsLabel.snp.makeConstraints { - $0.centerY.equalTo(roomTitleLabel.snp.centerY) - $0.leading.equalTo(roomTitleLabel.snp.trailing).offset(10) + self.addSubview(self.startStautsLabel) + self.startStautsLabel.snp.makeConstraints { + $0.centerY.equalTo(self.roomTitleLabel.snp.centerY) + $0.leading.equalTo(self.roomTitleLabel.snp.trailing).offset(10) $0.width.equalTo(66) $0.height.equalTo(23) } - self.addSubview(durationView) - durationView.snp.makeConstraints { - $0.top.equalTo(roomTitleLabel.snp.bottom).offset(30) + self.addSubview(self.durationView) + self.durationView.snp.makeConstraints { + $0.top.equalTo(self.roomTitleLabel.snp.bottom).offset(30) $0.trailing.leading.equalToSuperview() $0.height.equalTo(36) } - durationView.addSubview(durationLabel) - durationLabel.snp.makeConstraints { + self.durationView.addSubview(self.durationLabel) + self.durationLabel.snp.makeConstraints { $0.leading.equalToSuperview().inset(20) $0.centerY.equalToSuperview() } - durationView.addSubview(durationDateLabel) - durationDateLabel.snp.makeConstraints { + self.durationView.addSubview(self.durationDateLabel) + self.durationDateLabel.snp.makeConstraints { $0.trailing.equalToSuperview().inset(40) $0.centerY.equalToSuperview() } } - // MARK: - func - func setStartState(state: String) { switch state { case "PRE": - startStautsLabel.text = StartStatus.waiting.status + self.startStautsLabel.text = StartStatus.waiting.status case "PROCESSING": - startStautsLabel.text = StartStatus.starting.status + self.startStautsLabel.text = StartStatus.starting.status case "POST": - startStautsLabel.text = StartStatus.complete.status + self.startStautsLabel.text = StartStatus.complete.status default: - startStautsLabel.text = StartStatus.waiting.status + self.startStautsLabel.text = StartStatus.waiting.status } } func setRoomTitleLabelText(text: String) { - roomTitleLabel.text = text + self.roomTitleLabel.text = text } func setDurationDateLabel(text: String) { - durationDateLabel.text = text + self.durationDateLabel.text = text } } diff --git a/Manito/Manito/Screens/Interaction/OpenManittoPopupViewController.swift b/Manito/Manito/Screens/Interaction/OpenManittoPopupViewController.swift index deee98ccd..18cda66c2 100644 --- a/Manito/Manito/Screens/Interaction/OpenManittoPopupViewController.swift +++ b/Manito/Manito/Screens/Interaction/OpenManittoPopupViewController.swift @@ -18,7 +18,8 @@ final class OpenManittoPopupViewController: BaseViewController { private lazy var typingLabel: UILabel = { let label = UILabel() label.numberOfLines = 2 - label.font = .font(.regular, ofSize: 30) + label.font = .font(.regular, ofSize: 24) + label.adjustsFontSizeToFitWidth = true label.textAlignment = .center return label }() @@ -62,7 +63,7 @@ final class OpenManittoPopupViewController: BaseViewController { setTypingAnimation() } - override func render() { + override func setupLayout() { view.addSubview(popupView) popupView.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide).inset(UIScreen.main.bounds.size.height * 0.15) @@ -80,7 +81,7 @@ final class OpenManittoPopupViewController: BaseViewController { typingLabel.snp.makeConstraints { $0.top.equalToSuperview().inset(popupView.frame.height * 0.36) $0.centerX.equalToSuperview() - $0.leading.trailing.equalToSuperview().inset(10) + $0.leading.trailing.equalToSuperview().inset(24) } popupView.addSubview(openMentLabel) @@ -90,7 +91,7 @@ final class OpenManittoPopupViewController: BaseViewController { } } - override func configUI() { + override func configureUI() { view.backgroundColor = .black.withAlphaComponent(0.8) } diff --git a/Manito/Manito/Screens/Interaction/OpenManittoViewController.swift b/Manito/Manito/Screens/Interaction/OpenManittoViewController.swift index 1f547bc65..0d1bb950f 100644 --- a/Manito/Manito/Screens/Interaction/OpenManittoViewController.swift +++ b/Manito/Manito/Screens/Interaction/OpenManittoViewController.swift @@ -85,7 +85,7 @@ final class OpenManittoViewController: BaseViewController { requestWithFriends(roomId: roomId) } - override func render() { + override func setupLayout() { view.addSubview(titleLabel) titleLabel.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide).inset(57) diff --git a/Manito/Manito/Screens/Interaction/SelectManittoViewController.swift b/Manito/Manito/Screens/Interaction/SelectManittoViewController.swift index da6ffb454..743f7f5cb 100644 --- a/Manito/Manito/Screens/Interaction/SelectManittoViewController.swift +++ b/Manito/Manito/Screens/Interaction/SelectManittoViewController.swift @@ -64,8 +64,8 @@ final class SelectManittoViewController: BaseViewController { setupGifImage() } - override func configUI() { - super.configUI() + override func configureUI() { + super.configureUI() informationLabel.font = .font(.regular, ofSize: 20) nameLabel.font = .font(.regular, ofSize: 30) diff --git a/Manito/Manito/Screens/InvitedCode/InvitedCodeViewController.swift b/Manito/Manito/Screens/InvitedCode/InvitedCodeViewController.swift index 6b4cd0ed4..1bcc2d2ca 100644 --- a/Manito/Manito/Screens/InvitedCode/InvitedCodeViewController.swift +++ b/Manito/Manito/Screens/InvitedCode/InvitedCodeViewController.swift @@ -103,7 +103,7 @@ class InvitedCodeViewController: BaseViewController { // MARK: - configure - override func render() { + override func setupLayout() { view.addSubview(invitedImageView) invitedImageView.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide).inset(142) @@ -153,7 +153,7 @@ class InvitedCodeViewController: BaseViewController { } } - override func configUI() { + override func configureUI() { view.backgroundColor = .black.withAlphaComponent(0.8) } } diff --git a/Manito/Manito/Screens/Letter/CreateLetterViewController.swift b/Manito/Manito/Screens/Letter/CreateLetterViewController.swift index 7150e0b7e..2c6db87cf 100644 --- a/Manito/Manito/Screens/Letter/CreateLetterViewController.swift +++ b/Manito/Manito/Screens/Letter/CreateLetterViewController.swift @@ -13,7 +13,7 @@ final class CreateLetterViewController: BaseViewController { var createLetter: (() -> ())? - // MARK: - property + // MARK: - ui component private let indicatorView: UIView = { let view = UIView() @@ -45,9 +45,11 @@ final class CreateLetterViewController: BaseViewController { return scrollView }() private let scrollContentView = UIView() - private lazy var missionView = IndividualMissionView(mission: mission) private let letterTextView = LetterTextView() private let letterPhotoView = LetterPhotoView() + private lazy var missionView = IndividualMissionView(mission: self.mission) + + // MARK: - property private let letterSevice: LetterAPI = LetterAPI(apiService: APIService()) var manitteeId: String @@ -75,62 +77,64 @@ final class CreateLetterViewController: BaseViewController { override func viewDidLoad() { super.viewDidLoad() - checkSendButtonEnabled() - setupNavigationItem() - setupButtonAction() + self.checkSendButtonEnabled() + self.setupNavigationItem() + self.setupButtonAction() } + + // MARK: - override - override func render() { - view.addSubview(indicatorView) - indicatorView.snp.makeConstraints { + override func setupLayout() { + self.view.addSubview(self.indicatorView) + self.indicatorView.snp.makeConstraints { $0.top.equalToSuperview().inset(9) $0.centerX.equalToSuperview() $0.height.equalTo(3) $0.width.equalTo(40) } - view.addSubview(scrollView) - scrollView.snp.makeConstraints { - $0.top.equalTo(view.safeAreaLayoutGuide) + self.view.addSubview(self.scrollView) + self.scrollView.snp.makeConstraints { + $0.top.equalTo(self.view.safeAreaLayoutGuide) $0.leading.trailing.bottom.equalToSuperview() } - scrollView.addSubview(scrollContentView) - scrollContentView.snp.makeConstraints { + self.scrollView.addSubview(self.scrollContentView) + self.scrollContentView.snp.makeConstraints { $0.edges.equalToSuperview() - $0.width.equalTo(scrollView.snp.width) + $0.width.equalTo(self.scrollView.snp.width) } - scrollContentView.addSubview(missionView) - missionView.snp.makeConstraints { + self.scrollContentView.addSubview(self.missionView) + self.missionView.snp.makeConstraints { $0.top.equalToSuperview().offset(25) $0.leading.trailing.equalToSuperview().inset(Size.leadingTrailingPadding) $0.height.equalTo(100) } - scrollContentView.addSubview(letterTextView) - letterTextView.snp.makeConstraints { - $0.top.equalTo(missionView.snp.bottom).offset(32) + self.scrollContentView.addSubview(self.letterTextView) + self.letterTextView.snp.makeConstraints { + $0.top.equalTo(self.missionView.snp.bottom).offset(32) $0.leading.trailing.equalToSuperview().inset(Size.leadingTrailingPadding) } - scrollContentView.addSubview(letterPhotoView) - letterPhotoView.snp.makeConstraints { - $0.top.equalTo(letterTextView.snp.bottom).offset(22) + self.scrollContentView.addSubview(self.letterPhotoView) + self.letterPhotoView.snp.makeConstraints { + $0.top.equalTo(self.letterTextView.snp.bottom).offset(22) $0.leading.trailing.equalToSuperview().inset(Size.leadingTrailingPadding) $0.bottom.equalToSuperview().inset(105) } } - override func configUI() { - super.configUI() + override func configureUI() { + super.configureUI() - navigationController?.presentationController?.delegate = self - isModalInPresentation = true + self.navigationController?.presentationController?.delegate = self + self.isModalInPresentation = true } override func setupNavigationBar() { - guard let navigationBar = navigationController?.navigationBar else { return } + guard let navigationBar = self.navigationController?.navigationBar else { return } let appearance = UINavigationBarAppearance() let font = UIFont.font(.regular, ofSize: 16) @@ -145,36 +149,36 @@ final class CreateLetterViewController: BaseViewController { navigationBar.compactAppearance = appearance navigationBar.scrollEdgeAppearance = appearance - title = TextLiteral.createLetterViewControllerTitle + self.title = TextLiteral.createLetterViewControllerTitle } // MARK: - func private func checkSendButtonEnabled() { - letterTextView.applySendButtonEnabled = { [weak self] in + self.letterTextView.applySendButtonEnabled = { [weak self] in self?.changeButtonEnabledState() } - letterPhotoView.applySendButtonEnabled = { [weak self] in + self.letterPhotoView.applySendButtonEnabled = { [weak self] in self?.changeButtonEnabledState() } } private func changeButtonEnabledState() { - let hasText = letterTextView.letterTextView.hasText - let hasImage = letterPhotoView.importPhotosButton.imageView?.image != ImageLiterals.btnCamera + let hasText = self.letterTextView.letterTextView.hasText + let hasImage = self.letterPhotoView.importPhotosButton.imageView?.image != ImageLiterals.btnCamera let canEnabled = hasText || hasImage - sendButton.isEnabled = canEnabled + self.sendButton.isEnabled = canEnabled } private func setupNavigationItem() { - let cancelButton = makeBarButtonItem(with: cancelButton) - let sendButton = makeBarButtonItem(with: sendButton) + let cancelButton = self.makeBarButtonItem(with: cancelButton) + let sendButton = self.makeBarButtonItem(with: sendButton) sendButton.isEnabled = false - navigationItem.leftBarButtonItem = cancelButton - navigationItem.rightBarButtonItem = sendButton + self.navigationItem.leftBarButtonItem = cancelButton + self.navigationItem.rightBarButtonItem = sendButton } private func setupButtonAction() { @@ -188,19 +192,19 @@ final class CreateLetterViewController: BaseViewController { self?.dismiss(animated: true) } - cancelButton.addAction(cancelAction, for: .touchUpInside) - sendButton.addAction(sendAction, for: .touchUpInside) + self.cancelButton.addAction(cancelAction, for: .touchUpInside) + self.sendButton.addAction(sendAction, for: .touchUpInside) } private func presentationControllerDidAttemptToDismissAction() { - let hasText = letterTextView.letterTextView.hasText - let hasImage = letterPhotoView.importPhotosButton.imageView?.image != ImageLiterals.btnCamera + let hasText = self.letterTextView.letterTextView.hasText + let hasImage = self.letterPhotoView.importPhotosButton.imageView?.image != ImageLiterals.btnCamera guard hasText || hasImage else { - dismiss(animated: true, completion: nil) + self.dismiss(animated: true, completion: nil) return } - presentActionSheet() + self.presentActionSheet() } private func presentActionSheet() { @@ -208,9 +212,9 @@ final class CreateLetterViewController: BaseViewController { self?.resignFirstResponder() self?.dismiss(animated: true, completion: nil) } - makeActionSheet(actionTitles: [TextLiteral.destructive, TextLiteral.cancel], - actionStyle: [.destructive, .cancel], - actions: [dismissAction, nil]) + self.makeActionSheet(actionTitles: [TextLiteral.destructive, TextLiteral.cancel], + actionStyle: [.destructive, .cancel], + actions: [dismissAction, nil]) } // MARK: - network @@ -218,31 +222,31 @@ final class CreateLetterViewController: BaseViewController { private func dispatchLetter(roomId: String) { Task { do { - if let content = letterTextView.letterTextView.text, - let image = letterPhotoView.importPhotosButton.imageView?.image, + if let content = self.letterTextView.letterTextView.text, + let image = self.letterPhotoView.importPhotosButton.imageView?.image, image != ImageLiterals.btnCamera { guard let jpegData = image.jpegData(compressionQuality: 0.3) else { return } - let dto = LetterDTO(manitteeId: manitteeId, messageContent: content) + let dto = LetterDTO(manitteeId: self.manitteeId, messageContent: content) - let status = try await letterSevice.dispatchLetter(roomId: roomId, image: jpegData, letter: dto) + let status = try await self.letterSevice.dispatchLetter(roomId: roomId, image: jpegData, letter: dto) if status == 201 { self.createLetter?() } - } else if let content = letterTextView.letterTextView.text { - let dto = LetterDTO(manitteeId: manitteeId, messageContent: content) + } else if let content = self.letterTextView.letterTextView.text { + let dto = LetterDTO(manitteeId: self.manitteeId, messageContent: content) - let status = try await letterSevice.dispatchLetter(roomId: roomId, letter: dto) + let status = try await self.letterSevice.dispatchLetter(roomId: roomId, letter: dto) if status == 201 { self.createLetter?() } - } else if let image = letterPhotoView.importPhotosButton.imageView?.image, + } else if let image = self.letterPhotoView.importPhotosButton.imageView?.image, image != ImageLiterals.btnCamera { guard let jpegData = image.jpegData(compressionQuality: 0.3) else { return } - let dto = LetterDTO(manitteeId: manitteeId) + let dto = LetterDTO(manitteeId: self.manitteeId) - let status = try await letterSevice.dispatchLetter(roomId: roomId, image: jpegData, letter: dto) + let status = try await self.letterSevice.dispatchLetter(roomId: roomId, image: jpegData, letter: dto) if status == 201 { self.createLetter?() @@ -261,6 +265,6 @@ final class CreateLetterViewController: BaseViewController { // MARK: - UIAdaptivePresentationControllerDelegate extension CreateLetterViewController: UIAdaptivePresentationControllerDelegate { func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) { - presentationControllerDidAttemptToDismissAction() + self.presentationControllerDidAttemptToDismissAction() } } diff --git a/Manito/Manito/Screens/Letter/LetterImageViewController.swift b/Manito/Manito/Screens/Letter/LetterImageViewController.swift index 42a16d591..72d90d2a0 100644 --- a/Manito/Manito/Screens/Letter/LetterImageViewController.swift +++ b/Manito/Manito/Screens/Letter/LetterImageViewController.swift @@ -12,17 +12,28 @@ import SnapKit final class LetterImageViewController: BaseViewController { - // MARK: - property + // MARK: - ui component - private let scrollView = UIScrollView() private lazy var closeButton: UIButton = { let button = UIButton(type: .system) button.setImage(ImageLiterals.btnXmark, for: .normal) button.tintColor = .grey001 - button.addTarget(self, action: #selector(didTapCloseButton), for: .touchUpInside) + button.addTarget(self, action: #selector(self.didTapCloseButton), for: .touchUpInside) return button }() - let imageView: UIImageView = { + private lazy var scrollView: UIScrollView = { + let scrollView = UIScrollView() + scrollView.frame = view.bounds + scrollView.delegate = self + scrollView.zoomScale = 1.0 + scrollView.minimumZoomScale = 1.0 + scrollView.maximumZoomScale = 3.0 + scrollView.contentInsetAdjustmentBehavior = .never + scrollView.showsVerticalScrollIndicator = false + scrollView.showsHorizontalScrollIndicator = false + return scrollView + }() + private let imageView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .scaleAspectFit imageView.isUserInteractionEnabled = true @@ -33,52 +44,56 @@ final class LetterImageViewController: BaseViewController { button.setImage(ImageLiterals.icSave, for: .normal) return button }() + + // MARK: - init + + init(image: UIImage) { + self.imageView.image = image + super.init() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + print("\(#file) is dead") + } - // MARK: - life cycle + // MARK: - override - override func render() { - view.addSubview(scrollView) - scrollView.addSubview(imageView) - view.addSubview(closeButton) - closeButton.snp.makeConstraints { - $0.top.equalTo(view.safeAreaLayoutGuide).inset(23) - $0.leading.equalTo(view.safeAreaLayoutGuide).inset(17) + override func setupLayout() { + self.view.addSubview(self.scrollView) + self.scrollView.addSubview(self.imageView) + + self.view.addSubview(self.closeButton) + self.closeButton.snp.makeConstraints { + $0.top.equalTo(self.view.safeAreaLayoutGuide).inset(23) + $0.leading.equalTo(self.view.safeAreaLayoutGuide).inset(17) $0.width.height.equalTo(44) } - view.addSubview(downloadButton) - downloadButton.snp.makeConstraints { - $0.top.equalTo(view.safeAreaLayoutGuide).inset(23) - $0.trailing.equalTo(view.safeAreaLayoutGuide).inset(17) + self.view.addSubview(self.downloadButton) + self.downloadButton.snp.makeConstraints { + $0.top.equalTo(self.view.safeAreaLayoutGuide).inset(23) + $0.trailing.equalTo(self.view.safeAreaLayoutGuide).inset(17) } } - override func configUI() { - setupScrollView() - setupImageView() - setImagePinchGesture() - setupButtonAction() - } - - private func setupScrollView() { - scrollView.frame = view.bounds - scrollView.delegate = self - scrollView.zoomScale = 1.0 - scrollView.minimumZoomScale = 1.0 - scrollView.maximumZoomScale = 3.0 - scrollView.contentInsetAdjustmentBehavior = .never - scrollView.showsVerticalScrollIndicator = false - scrollView.showsHorizontalScrollIndicator = false + override func configureUI() { + self.setupImageView() + self.setImagePinchGesture() + self.setupButtonAction() } private func setupImageView() { - imageView.frame = scrollView.bounds - imageView.contentMode = .scaleAspectFit + self.imageView.frame = self.scrollView.bounds + self.imageView.contentMode = .scaleAspectFit } private func setImagePinchGesture() { - let pinch = UIPinchGestureRecognizer(target: self, action: #selector(didPinchImage(_:))) - view.addGestureRecognizer(pinch) + let pinch = UIPinchGestureRecognizer(target: self, action: #selector(self.didPinchImage(_:))) + self.view.addGestureRecognizer(pinch) } private func setupButtonAction() { @@ -91,7 +106,7 @@ final class LetterImageViewController: BaseViewController { PHPhotoLibrary.shared().performChanges({ PHAssetChangeRequest.creationRequestForAsset(from: image) - }, completionHandler: { (success, error) in + }) { (success, error) in DispatchQueue.main.async { if success { self?.makeAlert(title: TextLiteral.letterImageViewControllerSuccessTitle, @@ -102,9 +117,9 @@ final class LetterImageViewController: BaseViewController { message: TextLiteral.letterImageViewControllerErrorMessage) } } - }) + } } - downloadButton.addAction(downloadAction, for: .touchUpInside) + self.downloadButton.addAction(downloadAction, for: .touchUpInside) } // MARK: - selector @@ -116,7 +131,7 @@ final class LetterImageViewController: BaseViewController { @objc private func didPinchImage(_ pinch: UIPinchGestureRecognizer) { - imageView.transform = imageView.transform.scaledBy(x: pinch.scale, y: pinch.scale) + self.imageView.transform = self.imageView.transform.scaledBy(x: pinch.scale, y: pinch.scale) pinch.scale = 1 } } @@ -128,8 +143,8 @@ extension LetterImageViewController: UIScrollViewDelegate { func scrollViewDidZoom(_ scrollView: UIScrollView) { if scrollView.zoomScale > 1 { - guard let image = imageView.image else { return } - guard let zoomView = viewForZooming(in: scrollView) else { return } + guard let image = self.imageView.image else { return } + guard let zoomView = self.viewForZooming(in: scrollView) else { return } let widthRatio = zoomView.frame.width / image.size.width let heightRatio = zoomView.frame.height / image.size.height diff --git a/Manito/Manito/Screens/Letter/LetterViewController+MailCompose.swift b/Manito/Manito/Screens/Letter/LetterViewController+MailCompose.swift index b858129c0..b3a9b7ee6 100644 --- a/Manito/Manito/Screens/Letter/LetterViewController+MailCompose.swift +++ b/Manito/Manito/Screens/Letter/LetterViewController+MailCompose.swift @@ -34,7 +34,7 @@ extension LetterViewController: MFMailComposeViewControllerDelegate { composeVC.setSubject("[μ‹ κ³  κ΄€λ ¨ 문의]") composeVC.setMessageBody(messageBody, isHTML: false) - self.present(composeVC, animated: true, completion: nil) + self.present(composeVC, animated: true) } else { self.showSendMailErrorAlert() @@ -43,15 +43,12 @@ extension LetterViewController: MFMailComposeViewControllerDelegate { private func showSendMailErrorAlert() { let sendMailErrorAlert = UIAlertController(title: "메일 전솑 μ‹€νŒ¨", message: "아이폰 이메일 섀정을 ν™•μΈν•˜κ³  λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.", preferredStyle: .alert) - let confirmAction = UIAlertAction(title: "확인", style: .default) { - (action) in - print("확인") - } + let confirmAction = UIAlertAction(title: "확인", style: .default) sendMailErrorAlert.addAction(confirmAction) - self.present(sendMailErrorAlert, animated: true, completion: nil) + self.present(sendMailErrorAlert, animated: true) } func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) { - controller.dismiss(animated: true, completion: nil) + controller.dismiss(animated: true) } } diff --git a/Manito/Manito/Screens/Letter/LetterViewController.swift b/Manito/Manito/Screens/Letter/LetterViewController.swift index dd1dab1d6..f1241603f 100644 --- a/Manito/Manito/Screens/Letter/LetterViewController.swift +++ b/Manito/Manito/Screens/Letter/LetterViewController.swift @@ -34,33 +34,29 @@ final class LetterViewController: BaseViewController { } } - private enum Size { + private enum InternalSize { + static let cellWidth: CGFloat = UIScreen.main.bounds.size.width - Size.leadingTrailingPadding * 2 static let headerHeight: CGFloat = 66.0 - static let collectionHorizontalSpacing: CGFloat = 20.0 - static let collectionVerticalSpacing: CGFloat = 18.0 - static let cellTopSpacing: CGFloat = 16.0 - static let cellBottomSpacing: CGFloat = 35.0 - static let cellHorizontalSpacing: CGFloat = 16.0 - static let cellWidth: CGFloat = UIScreen.main.bounds.size.width - collectionHorizontalSpacing * 2 static let imageHeight: CGFloat = 204.0 - static let collectionInset = UIEdgeInsets(top: collectionVerticalSpacing, - left: collectionHorizontalSpacing, - bottom: collectionVerticalSpacing, - right: collectionHorizontalSpacing) + static let cellInset: UIEdgeInsets = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 35.0, right: 16.0) + static let collectionInset: UIEdgeInsets = UIEdgeInsets(top: 18.0, + left: Size.leadingTrailingPadding, + bottom: 18.0, + right: Size.leadingTrailingPadding) } - // MARK: - property + // MARK: - ui component private let collectionViewFlowLayout: UICollectionViewFlowLayout = { let flowLayout = UICollectionViewFlowLayout() flowLayout.scrollDirection = .vertical - flowLayout.sectionInset = Size.collectionInset + flowLayout.sectionInset = InternalSize.collectionInset flowLayout.minimumLineSpacing = 33 flowLayout.sectionHeadersPinToVisibleBounds = true return flowLayout }() private lazy var listCollectionView: UICollectionView = { - let collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewFlowLayout) + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: self.collectionViewFlowLayout) collectionView.backgroundColor = .clear collectionView.dataSource = self collectionView.delegate = self @@ -72,40 +68,39 @@ final class LetterViewController: BaseViewController { withReuseIdentifier: LetterHeaderView.className) return collectionView }() - private lazy var sendLetterView = SendLetterView() + private let emptyLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 2 + label.font = .font(.regular, ofSize: 16) + label.text = TextLiteral.letterViewControllerEmptyViewTo + label.isHidden = true + label.textColor = .grey003 + label.textAlignment = .center + label.addLabelSpacing(lineSpacing: 16) + return label + }() + private lazy var sendLetterView: SendLetterView = SendLetterView() + + // MARK: - property private var letterState: LetterState { didSet { - reloadCollectionView(with: self.letterState) - setupEmptyLabel() + self.reloadCollectionView(with: self.letterState) + self.setupEmptyLabel() } } - private var letterList: [Message] = [] { didSet { - listCollectionView.reloadData() - setupEmptyView() + self.listCollectionView.reloadData() + self.setupEmptyView() } } - private let letterSevice: LetterAPI = LetterAPI(apiService: APIService()) private var manitteeId: String? private var roomId: String private var roomState: String private var mission: String - private let emptyLabel: UILabel = { - let label = UILabel() - label.numberOfLines = 2 - label.font = .font(.regular, ofSize: 16) - label.text = TextLiteral.letterViewControllerEmptyViewTo - label.isHidden = true - label.textColor = .grey003 - label.addLabelSpacing(lineSpacing: 16) - label.textAlignment = .center - return label - }() - // MARK: - init init(roomState: String, roomId: String, mission: String, letterState: LetterState) { @@ -128,91 +123,94 @@ final class LetterViewController: BaseViewController { override func viewDidLoad() { super.viewDidLoad() - setupButtonAction() - setupGuideArea() - renderGuideArea() - hideGuideViewWhenTappedAround() + self.setupButtonAction() + self.setupGuideArea() + self.renderGuideArea() + self.hideGuideViewWhenTappedAround() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - setupLargeTitle() + self.setupLargeTitle() + } + + override func viewWillDisappear(_ animated: Bool) { + self.guideBoxImageView.isHidden = true } + + // MARK: - override - override func render() { - view.addSubview(listCollectionView) - listCollectionView.snp.makeConstraints { - $0.edges.equalTo(view.safeAreaLayoutGuide) + override func setupLayout() { + self.view.addSubview(self.listCollectionView) + self.listCollectionView.snp.makeConstraints { + $0.edges.equalTo(self.view.safeAreaLayoutGuide) } - view.addSubview(guideButton) - guideButton.snp.makeConstraints { + self.view.addSubview(self.guideButton) + self.guideButton.snp.makeConstraints { $0.width.height.equalTo(44) } - - if roomState != "POST" { - view.addSubview(sendLetterView) - sendLetterView.snp.makeConstraints { - $0.leading.trailing.bottom.equalTo(view.safeAreaLayoutGuide) - } - } - view.addSubview(emptyLabel) - emptyLabel.snp.makeConstraints { + + self.view.addSubview(self.emptyLabel) + self.emptyLabel.snp.makeConstraints { $0.center.equalToSuperview() } + + if self.roomState != "POST" { + self.view.addSubview(self.sendLetterView) + self.sendLetterView.snp.makeConstraints { + $0.leading.trailing.bottom.equalTo(self.view.safeAreaLayoutGuide) + } + } } - override func configUI() { - super.configUI() - reloadCollectionView(with: self.letterState) - setupEmptyLabel() + override func configureUI() { + super.configureUI() + self.reloadCollectionView(with: self.letterState) + self.setupEmptyLabel() } override func setupNavigationBar() { super.setupNavigationBar() - let guideButton = makeBarButtonItem(with: guideButton) - - navigationItem.rightBarButtonItem = guideButton - title = TextLiteral.letterViewControllerTitle + + let guideButton = self.makeBarButtonItem(with: self.guideButton) + self.navigationItem.rightBarButtonItem = guideButton + self.title = TextLiteral.letterViewControllerTitle } override func setupGuideArea() { super.setupGuideArea() - guideButton.setImage(ImageLiterals.icLetterInfo, for: .normal) - setupGuideText(title: TextLiteral.letterViewControllerGuideTitle, text: TextLiteral.letterViewControllerGuideText) + self.guideButton.setImage(ImageLiterals.icLetterInfo, for: .normal) + self.setupGuideText(title: TextLiteral.letterViewControllerGuideTitle, text: TextLiteral.letterViewControllerGuideText) } override func renderGuideArea() { - if let view = navigationController?.view { - view.addSubview(guideBoxImageView) - guideBoxImageView.snp.makeConstraints { - $0.top.equalTo(view.safeAreaLayoutGuide.snp.top).inset(35) - $0.trailing.equalTo(view.snp.trailing).inset(Size.collectionHorizontalSpacing + 8) + if let navigationView = self.navigationController?.view { + navigationView.addSubview(self.guideBoxImageView) + self.guideBoxImageView.snp.makeConstraints { + $0.top.equalTo(navigationView.safeAreaLayoutGuide.snp.top).inset(35) + $0.trailing.equalTo(navigationView.snp.trailing).inset(Size.leadingTrailingPadding + 8) $0.width.equalTo(270) $0.height.equalTo(90) } } - guideBoxImageView.addSubview(guideLabel) - guideLabel.snp.makeConstraints { + self.guideBoxImageView.addSubview(self.guideLabel) + self.guideLabel.snp.makeConstraints { $0.top.equalToSuperview().inset(20) $0.leading.trailing.equalToSuperview().inset(15) } } - - override func viewWillDisappear(_ animated: Bool) { - guideBoxImageView.isHidden = true - } - + // MARK: - func private func setupLargeTitle() { - navigationController?.navigationBar.prefersLargeTitles = true - navigationItem.largeTitleDisplayMode = .automatic + self.navigationController?.navigationBar.prefersLargeTitles = true + self.navigationItem.largeTitleDisplayMode = .automatic } private func setupEmptyView() { - emptyLabel.isHidden = !letterList.isEmpty + self.emptyLabel.isHidden = !self.letterList.isEmpty } private func setupButtonAction() { @@ -229,30 +227,30 @@ final class LetterViewController: BaseViewController { } self.present(navigationController, animated: true, completion: nil) } - sendLetterView.sendLetterButton.addAction(presentSendButtonAction, - for: .touchUpInside) + self.sendLetterView.sendLetterButton.addAction(presentSendButtonAction, + for: .touchUpInside) } private func reloadCollectionView(with state: LetterState) { let isReceivedState = (state == .received) let bottomInset: CGFloat = (isReceivedState ? 0 : 73) - let topPoint = listCollectionView.adjustedContentInset.top + 1 + let topPoint = self.listCollectionView.adjustedContentInset.top + 1 - sendLetterView.isHidden = isReceivedState - listCollectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: bottomInset, right: 0) - listCollectionView.setContentOffset(CGPoint(x: 0, y: -topPoint), animated: false) - listCollectionView.collectionViewLayout.invalidateLayout() + self.sendLetterView.isHidden = isReceivedState + self.listCollectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: bottomInset, right: 0) + self.listCollectionView.setContentOffset(CGPoint(x: 0, y: -topPoint), animated: false) + self.listCollectionView.collectionViewLayout.invalidateLayout() switch state { case .sent: - fetchSendLetter(roomId: roomId) + self.fetchSendLetter(roomId: self.roomId) case .received: - fetchReceviedLetter(roomId: roomId) + self.fetchReceviedLetter(roomId: self.roomId) } } private func calculateContentHeight(text: String) -> CGFloat { - let width = UIScreen.main.bounds.size.width - Size.collectionHorizontalSpacing * 2 - Size.cellHorizontalSpacing * 2 + let width = UIScreen.main.bounds.size.width - Size.leadingTrailingPadding * 2 - InternalSize.cellInset.left * 2 let label = UILabel(frame: CGRect(origin: .zero, size: CGSize(width: width, height: .greatestFiniteMagnitude))) @@ -265,25 +263,25 @@ final class LetterViewController: BaseViewController { } private func hideGuideViewWhenTappedAround() { - let navigationTap = UITapGestureRecognizer(target: self, action: #selector(dismissGuideView)) - let viewTap = UITapGestureRecognizer(target: self, action: #selector(dismissGuideView)) + let navigationTap = UITapGestureRecognizer(target: self, action: #selector(self.dismissGuideView)) + let viewTap = UITapGestureRecognizer(target: self, action: #selector(self.dismissGuideView)) navigationTap.cancelsTouchesInView = false viewTap.cancelsTouchesInView = false - navigationController?.view.addGestureRecognizer(navigationTap) - view.addGestureRecognizer(viewTap) + self.navigationController?.view.addGestureRecognizer(navigationTap) + self.view.addGestureRecognizer(viewTap) } private func setupEmptyLabel() { - emptyLabel.text = letterState.labelText - emptyLabel.isHidden = true + self.emptyLabel.text = self.letterState.labelText + self.emptyLabel.isHidden = true } // MARK: - selector @objc private func dismissGuideView() { - if !guideButton.isTouchInside { - guideBoxImageView.isHidden = true + if !self.guideButton.isTouchInside { + self.guideBoxImageView.isHidden = true } } @@ -292,12 +290,12 @@ final class LetterViewController: BaseViewController { private func fetchSendLetter(roomId: String) { Task { do { - let letterContent = try await letterSevice.fetchSendLetter(roomId: roomId) + let letterContent = try await self.letterSevice.fetchSendLetter(roomId: roomId) if let content = letterContent { dump(content) - manitteeId = content.manittee?.id - letterList = content.messages + self.manitteeId = content.manittee?.id + self.letterList = content.messages } } catch NetworkError.serverError { print("serverError") @@ -310,11 +308,11 @@ final class LetterViewController: BaseViewController { private func fetchReceviedLetter(roomId: String) { Task { do { - let letterContent = try await letterSevice.fetchReceiveLetter(roomId: roomId) + let letterContent = try await self.letterSevice.fetchReceiveLetter(roomId: roomId) if let content = letterContent { dump(content) - letterList = content.messages + self.letterList = content.messages } } catch NetworkError.serverError { print("serverError") @@ -328,19 +326,18 @@ final class LetterViewController: BaseViewController { // MARK: - UICollectionViewDataSource extension LetterViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return letterList.count + return self.letterList.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell: LetterCollectionViewCell = collectionView.dequeueReusableCell(forIndexPath: indexPath) - cell.setLetterData(with: letterList[indexPath.item], isHidden: letterState.isHidden) + cell.setLetterData(with: self.letterList[indexPath.item], isHidden: self.letterState.isHidden) cell.didTappedReport = { [weak self] in self?.sendReportMail(userNickname: UserDefaultStorage.nickname ?? "", content: self?.letterList[indexPath.item].content ?? "κΈ€ λ‚΄μš© μ—†μŒ") } cell.didTappedImage = { [weak self] image in - let viewController = LetterImageViewController() - viewController.imageView.image = image + let viewController = LetterImageViewController(image: image) viewController.modalPresentationStyle = .fullScreen viewController.modalTransitionStyle = .crossDissolve self?.present(viewController, animated: true) @@ -351,12 +348,14 @@ extension LetterViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { switch kind { case UICollectionView.elementKindSectionHeader: - guard let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: LetterHeaderView.className, for: indexPath) as? LetterHeaderView else { + guard let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, + withReuseIdentifier: LetterHeaderView.className, + for: indexPath) as? LetterHeaderView else { assert(false, "do not have reusable view") return UICollectionReusableView() } - headerView.segmentControlIndex = letterState.rawValue + headerView.segmentControlIndex = self.letterState.rawValue headerView.changeSegmentControlIndex = { [weak self] index in guard let letterStatus = LetterState.init(rawValue: index) else { return } self?.letterState = letterStatus @@ -373,27 +372,27 @@ extension LetterViewController: UICollectionViewDataSource { // MARK: - UICollectionViewDelegateFlowLayout extension LetterViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - var heights = [Size.cellTopSpacing, Size.cellBottomSpacing] + var heights = [InternalSize.cellInset.top, InternalSize.cellInset.bottom] - if let content = letterList[indexPath.item].content { - heights += [calculateContentHeight(text: content)] + if let content = self.letterList[indexPath.item].content { + heights += [self.calculateContentHeight(text: content)] } - if letterList[indexPath.item].imageUrl != nil { - heights += [Size.imageHeight] + if self.letterList[indexPath.item].imageUrl != nil { + heights += [InternalSize.imageHeight] } - return CGSize(width: Size.cellWidth, height: heights.reduce(0, +)) + return CGSize(width: InternalSize.cellWidth, height: heights.reduce(0, +)) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - return CGSize(width: UIScreen.main.bounds.size.width, height: Size.headerHeight) + return CGSize(width: UIScreen.main.bounds.size.width, height: InternalSize.headerHeight) } } // MARK: - UICollectionViewDelegate extension LetterViewController: UICollectionViewDelegate { func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { - guideBoxImageView.isHidden = true + self.guideBoxImageView.isHidden = true } } diff --git a/Manito/Manito/Screens/Login/LoginViewController.swift b/Manito/Manito/Screens/Login/LoginViewController.swift index e13074190..960ed85bf 100644 --- a/Manito/Manito/Screens/Login/LoginViewController.swift +++ b/Manito/Manito/Screens/Login/LoginViewController.swift @@ -35,7 +35,7 @@ final class LoginViewController: BaseViewController { // MARK: - func - override func render() { + override func setupLayout() { view.addSubview(logoImageView) logoImageView.snp.makeConstraints { $0.centerX.equalToSuperview() diff --git a/Manito/Manito/Screens/Main/Cell/ManitoRoomCollectionCell.swift b/Manito/Manito/Screens/Main/Cell/ManitoRoomCollectionCell.swift index d98edae63..dd31fc33f 100644 --- a/Manito/Manito/Screens/Main/Cell/ManitoRoomCollectionCell.swift +++ b/Manito/Manito/Screens/Main/Cell/ManitoRoomCollectionCell.swift @@ -7,6 +7,7 @@ import UIKit +import SkeletonView import SnapKit final class ManitoRoomCollectionViewCell: BaseCollectionViewCell { @@ -48,26 +49,26 @@ final class ManitoRoomCollectionViewCell: BaseCollectionViewCell { // MARK: - life cycle override func render() { - addSubview(imageView) + contentView.addSubview(imageView) imageView.snp.makeConstraints { $0.top.leading.equalToSuperview().inset(9) $0.width.height.equalTo(30) } - addSubview(memberLabel) + contentView.addSubview(memberLabel) memberLabel.snp.makeConstraints { $0.top.equalToSuperview().inset(14) $0.leading.equalTo(imageView.snp.trailing).offset(4) } - addSubview(roomLabel) + contentView.addSubview(roomLabel) roomLabel.snp.makeConstraints { $0.top.equalTo(imageView.snp.bottom).offset(20) $0.centerX.equalToSuperview() $0.leading.trailing.equalToSuperview().inset(17) } - addSubview(roomStateView) + contentView.addSubview(roomStateView) roomStateView.snp.makeConstraints { $0.top.equalTo(roomLabel.snp.bottom).offset(24) $0.leading.equalToSuperview().inset(12) @@ -75,7 +76,7 @@ final class ManitoRoomCollectionViewCell: BaseCollectionViewCell { $0.height.equalTo(24) } - addSubview(dateLabel) + contentView.addSubview(dateLabel) dateLabel.snp.makeConstraints { $0.bottom.equalToSuperview().inset(12) $0.centerX.equalToSuperview() @@ -85,5 +86,15 @@ final class ManitoRoomCollectionViewCell: BaseCollectionViewCell { override func configUI() { backgroundColor = .darkGrey002.withAlphaComponent(0.8) makeBorderLayer(color: UIColor.white.withAlphaComponent(0.5)) + + [self, imageView, roomLabel, roomStateView].forEach { + $0.isSkeletonable = true + } + + roomLabel.numberOfLines = 2 + + imageView.skeletonCornerRadius = 15 + roomLabel.linesCornerRadius = 4 + roomStateView.skeletonCornerRadius = 4 } } diff --git a/Manito/Manito/Screens/Main/MainViewController.swift b/Manito/Manito/Screens/Main/MainViewController.swift index 83a637b05..1b93fe44c 100644 --- a/Manito/Manito/Screens/Main/MainViewController.swift +++ b/Manito/Manito/Screens/Main/MainViewController.swift @@ -8,6 +8,7 @@ import UIKit import Gifu +import SkeletonView import SnapKit final class MainViewController: BaseViewController { @@ -23,6 +24,8 @@ final class MainViewController: BaseViewController { left: collectionHorizontalSpacing, bottom: collectionVerticalSpacing, right: collectionHorizontalSpacing) + static let commonMissionViewWidth: CGFloat = UIScreen.main.bounds.size.width - 40 + static let commonMissionViewHeight: CGFloat = commonMissionViewWidth * 0.6 } private enum RoomStatus: String { @@ -42,6 +45,8 @@ final class MainViewController: BaseViewController { } } + private let skeletonAnimation = SkeletonAnimationBuilder().makeSlidingAnimation(withDirection: .leftRight) + private let refreshControl = UIRefreshControl() // MARK: - property @@ -56,8 +61,7 @@ final class MainViewController: BaseViewController { return button }() private let imgStar = UIImageView(image: ImageLiterals.imgStar) - private let commonMissionImageView = UIImageView(image: ImageLiterals.imgCommonMisson) - private let commonMissionView = CommonMissonView() + private let commonMissionView = CommonMissionView() private let menuTitle: UILabel = { let label = UILabel() label.text = TextLiteral.mainViewControllerMenuTitle @@ -84,6 +88,7 @@ final class MainViewController: BaseViewController { forCellWithReuseIdentifier: ManitoRoomCollectionViewCell.className) collectionView.register(cell: CreateRoomCollectionViewCell.self, forCellWithReuseIdentifier: CreateRoomCollectionViewCell.className) + collectionView.isSkeletonable = true return collectionView }() private let maCharacterImageView = GIFImageView() @@ -104,6 +109,7 @@ final class MainViewController: BaseViewController { setupGuideArea() renderGuideArea() setupRefreshControl() + setupSkeletonView() } override func viewWillAppear(_ animated: Bool) { @@ -112,7 +118,7 @@ final class MainViewController: BaseViewController { requestManittoRoomList() } - override func render() { + override func setupLayout() { view.addSubview(maCharacterImageView) maCharacterImageView.snp.makeConstraints { $0.leading.equalToSuperview().inset(70) @@ -140,23 +146,17 @@ final class MainViewController: BaseViewController { $0.leading.equalToSuperview().inset(13) $0.top.equalTo(view.safeAreaLayoutGuide).offset(30) } - - view.addSubview(commonMissionImageView) - commonMissionImageView.snp.makeConstraints { - $0.leading.trailing.equalToSuperview().inset(24) - $0.height.equalTo(commonMissionImageView.snp.width).multipliedBy(0.61) - $0.top.equalTo(imgStar.snp.bottom) - } - - commonMissionImageView.addSubview(commonMissionView) + // FIXME: μ’Œμš°νŒ¨λ”© 20값을 μ£ΌλŠ”λ° SizeλΌλŠ” λ³€μˆ˜λͺ…이 κ²ΉμΉ¨ + view.addSubview(commonMissionView) commonMissionView.snp.makeConstraints { - $0.center.equalToSuperview() - $0.leading.trailing.equalToSuperview().inset(30) + $0.top.equalTo(imgStar.snp.bottom) + $0.leading.trailing.equalToSuperview().inset(20) + $0.height.equalTo(Size.commonMissionViewHeight) } view.addSubview(menuTitle) menuTitle.snp.makeConstraints { - $0.top.equalTo(commonMissionImageView.snp.bottom).offset(50) + $0.top.equalTo(commonMissionView.snp.bottom).offset(50) $0.leading.equalToSuperview().offset(16) } @@ -168,8 +168,8 @@ final class MainViewController: BaseViewController { view.addSubview(guideButton) guideButton.snp.makeConstraints { - $0.top.equalTo(commonMissionImageView.snp.top).offset(27) - $0.trailing.equalTo(commonMissionView.snp.trailing) + $0.top.equalTo(commonMissionView.snp.top).offset(30) + $0.trailing.equalTo(commonMissionView.snp.trailing).inset(30) $0.width.height.equalTo(44) } } @@ -213,6 +213,15 @@ final class MainViewController: BaseViewController { listCollectionView.refreshControl = refreshControl } + private func setupSkeletonView() { + listCollectionView.showAnimatedGradientSkeleton(usingGradient: .init(colors: [.grey003, .darkGrey002]), animation: skeletonAnimation, transition: .none) + } + + private func stopSkeletonView() { + self.listCollectionView.stopSkeletonAnimation() + self.listCollectionView.hideSkeleton(reloadDataAfter: true, transition: .crossDissolve(0.5)) + } + // MARK: - API private func requestCommonMission() { @@ -238,6 +247,8 @@ final class MainViewController: BaseViewController { if let manittoList = data { rooms = manittoList.participatingRooms listCollectionView.reloadData() + + self.stopSkeletonView() } } catch NetworkError.serverError { print("serverError") @@ -321,6 +332,17 @@ final class MainViewController: BaseViewController { } } +// MARK: - SkeletonCollectionViewDelegate, SkeletonCollectionViewDataSource +extension MainViewController: SkeletonCollectionViewDelegate, SkeletonCollectionViewDataSource { + func collectionSkeletonView(_ skeletonView: UICollectionView, cellIdentifierForItemAt indexPath: IndexPath) -> ReusableCellIdentifier { + return ManitoRoomCollectionViewCell.className + } + + func collectionSkeletonView(_ skeletonView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return 8 + } +} + // MARK: - UICollectionViewDataSource extension MainViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { diff --git a/Manito/Manito/Screens/Main/UIComponent/CommonMissonView.swift b/Manito/Manito/Screens/Main/UIComponent/CommonMissionView.swift similarity index 67% rename from Manito/Manito/Screens/Main/UIComponent/CommonMissonView.swift rename to Manito/Manito/Screens/Main/UIComponent/CommonMissionView.swift index abe8f6102..05157d0b9 100644 --- a/Manito/Manito/Screens/Main/UIComponent/CommonMissonView.swift +++ b/Manito/Manito/Screens/Main/UIComponent/CommonMissionView.swift @@ -1,5 +1,5 @@ // -// CommonMissonView.swift +// CommonMissionView.swift // Manito // // Created by COBY_PRO on 2022/06/12. @@ -9,10 +9,11 @@ import UIKit import SnapKit -final class CommonMissonView: UIView { +final class CommonMissionView: UIView { // MARK: - property + private let commonMissionImageView = UIImageView(image: ImageLiterals.imgCommonMisson) private let title: UILabel = { let label = UILabel() label.text = TextLiteral.commonMissionViewTitle @@ -43,16 +44,21 @@ final class CommonMissonView: UIView { // MARK: - life cycle private func render() { + self.addSubview(commonMissionImageView) + commonMissionImageView.snp.makeConstraints { + $0.edges.equalToSuperview() + } + self.addSubview(title) title.snp.makeConstraints { - $0.top.centerX.equalToSuperview() + $0.top.equalToSuperview().inset(56) + $0.centerX.equalToSuperview() } self.addSubview(mission) mission.snp.makeConstraints { - $0.top.equalTo(self.title.snp.bottom).offset(23) - $0.bottom.leading.trailing.equalToSuperview() - $0.height.equalTo(56) + $0.top.equalTo(title.snp.bottom).offset(40) + $0.leading.trailing.equalToSuperview() } } } diff --git a/Manito/Manito/Screens/ParticipateRoom/ParticipateRoomViewController.swift b/Manito/Manito/Screens/ParticipateRoom/ParticipateRoomViewController.swift index 85dae17ee..31a78df7a 100644 --- a/Manito/Manito/Screens/ParticipateRoom/ParticipateRoomViewController.swift +++ b/Manito/Manito/Screens/ParticipateRoom/ParticipateRoomViewController.swift @@ -57,7 +57,7 @@ final class ParticipateRoomViewController: BaseViewController { setupNotificationCenter() } - override func render() { + override func setupLayout() { view.addSubview(closeButton) closeButton.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide).inset(9) diff --git a/Manito/Manito/Screens/Setting/ChangeNickNameViewController.swift b/Manito/Manito/Screens/Setting/ChangeNickNameViewController.swift index dd134e60f..e76161c9f 100644 --- a/Manito/Manito/Screens/Setting/ChangeNickNameViewController.swift +++ b/Manito/Manito/Screens/Setting/ChangeNickNameViewController.swift @@ -71,7 +71,7 @@ class ChangeNickNameViewController: BaseViewController { setupLargeTitle() } - override func render() { + override func setupLayout() { view.addSubview(nameTextField) nameTextField.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide).inset(66) @@ -178,8 +178,8 @@ class ChangeNickNameViewController: BaseViewController { // MARK: - Configure - override func configUI() { - super.configUI() + override func configureUI() { + super.configureUI() } override func setupNavigationBar() { diff --git a/Manito/Manito/Screens/Setting/SettingViewController.swift b/Manito/Manito/Screens/Setting/SettingViewController.swift index 18aa9a10e..52e4966e3 100644 --- a/Manito/Manito/Screens/Setting/SettingViewController.swift +++ b/Manito/Manito/Screens/Setting/SettingViewController.swift @@ -54,7 +54,7 @@ class SettingViewController: BaseViewController { navigationController?.navigationBar.prefersLargeTitles = false } - override func render() { + override func setupLayout() { view.addSubview(imageRow) imageRow.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide) @@ -73,8 +73,8 @@ class SettingViewController: BaseViewController { // MARK: - Configure - override func configUI() { - super.configUI() + override func configureUI() { + super.configureUI() } override func setupNavigationBar() { diff --git a/Manito/Manito/Screens/SettingDeveloperInfo/SettingDeveloperInfoViewController.swift b/Manito/Manito/Screens/SettingDeveloperInfo/SettingDeveloperInfoViewController.swift index 68b6a7c22..a37ded00b 100644 --- a/Manito/Manito/Screens/SettingDeveloperInfo/SettingDeveloperInfoViewController.swift +++ b/Manito/Manito/Screens/SettingDeveloperInfo/SettingDeveloperInfoViewController.swift @@ -108,7 +108,7 @@ final class SettingDeveloperInfoViewController: BaseViewController { setupLargeTitle() } - override func render() { + override func setupLayout() { view.addSubview(listCollectionView) listCollectionView.snp.makeConstraints { $0.top.equalTo(view.safeAreaLayoutGuide).offset(30)