Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/suyeon'
Browse files Browse the repository at this point in the history
  • Loading branch information
youz2me committed Sep 10, 2024
2 parents c878a33 + f4876a7 commit 727fc80
Show file tree
Hide file tree
Showing 16 changed files with 281 additions and 360 deletions.
4 changes: 3 additions & 1 deletion KkuMulKum.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2214,6 +2214,7 @@
INFOPLIST_KEY_CFBundleDisplayName = "꾸물꿈";
INFOPLIST_KEY_NSCameraUsageDescription = "카메라 사용 권한이 필요합니다.";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "사진 라이브러리 접근 권한이 필요합니다.";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "꾸물꿈은 카메라 권한을 필요로 합니다. 카메라를 통해 자신의 프로필을 즉시 찍어 업로드할 수 있습니다. 허용 안함 시 일부 기능이 동작하지 않을 수 있습니다.";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
Expand Down Expand Up @@ -2255,6 +2256,7 @@
INFOPLIST_KEY_CFBundleDisplayName = "꾸물꿈";
INFOPLIST_KEY_NSCameraUsageDescription = "카메라 사용 권한이 필요합니다.";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "사진 라이브러리 접근 권한이 필요합니다.";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "꾸물꿈은 카메라 권한을 필요로 합니다. 카메라를 통해 자신의 프로필을 즉시 찍어 업로드할 수 있습니다. 허용 안함 시 일부 기능이 동작하지 않을 수 있습니다.";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
Expand All @@ -2270,7 +2272,7 @@
PRODUCT_BUNDLE_IDENTIFIER = KkuMulKum.yizihn;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = KkumulkumRelease;
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = KkumulkumRelease1;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
Expand Down
1 change: 0 additions & 1 deletion KkuMulKum/Network/DTO/ResponseBody/ResponseBodyDTO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,3 @@ struct ErrorResponse: Codable {
let code: Int
let message: String
}

161 changes: 18 additions & 143 deletions KkuMulKum/Network/Service/MeetingService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,25 @@ extension MeetingService: MeetingInfoServiceProtocol {
return try await request(with: .fetchMeetingMember(meetingID: meetingID))
}

func fetchMeetingPromiseList(
func fetchMeetingPromiseList(with meetingID: Int) -> Single<ResponseBodyDTO<MeetingPromisesModel>> {
return provider.rx.request(.fetchMeetingPromiseList(meetingID: meetingID))
.map(ResponseBodyDTO<MeetingPromisesModel>.self)
.catch { error in
print(">>> 에러 발생: \(error.localizedDescription) : \(#function) : \(Self.self)")
return .error(error)
}
}

func fetchParticipatedPromiseList(
with meetingID: Int,
isParticipant: Bool?
) async throws -> ResponseBodyDTO<MeetingPromisesModel>? {
guard let isParticipant else {
return try await request(with: .fetchMeetingPromiseList(meetingID: meetingID))
}
return try await request(with: .fetchParticipatedPromiseList(meetingID: meetingID, isParticipant: isParticipant))
isParticipant: Bool
) -> Single<ResponseBodyDTO<MeetingPromisesModel>> {
return provider.rx.request(.fetchParticipatedPromiseList(meetingID: meetingID, isParticipant: isParticipant))
.map(ResponseBodyDTO<MeetingPromisesModel>.self)
.catch { error in
print(">>> 에러 발생: \(error.localizedDescription) : \(#function) : \(Self.self)")
return .error(error)
}
}

func exitMeeting(with meetingID: Int) -> Single<ResponseBodyDTO<EmptyModel>> {
Expand Down Expand Up @@ -90,139 +101,3 @@ extension MeetingService: InviteCodeServiceProtocol {
return try await self.request(with: .joinMeeting(request: request))
}
}

final class MockMeetingInfoService: MeetingInfoServiceProtocol {
func fetchMeetingInfo(with meetingID: Int) -> ResponseBodyDTO<MeetingInfoModel>? {
let mockData = MeetingInfoModel(
meetingID: 1,
name: "웅웅난진웅",
createdAt: "2024.06.08",
metCount: 3,
invitationCode: "WD56CQ"
)

return ResponseBodyDTO(success: true, data: mockData, error: nil)
}

func fetchMeetingMemberList(with meetingID: Int) -> ResponseBodyDTO<MeetingMembersModel>? {
let mockData = MeetingMembersModel(
memberCount: 14,
members: [
Member(
memberID: 1,
name: "김진웅",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 2,
name: "김수연",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 3,
name: "이지훈",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 4,
name: "이유진",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 5,
name: "이승현",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 6,
name: "허준혁",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 7,
name: "배차은우",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 8,
name: "김윤서",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 9,
name: "정혜진",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 10,
name: "주효은",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 11,
name: "박상준",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 12,
name: "김채원",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 13,
name: "류희재",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
),
Member(
memberID: 14,
name: "김민지",
profileImageURL: "https://reqres.in/img/faces/\(Int.random(in: 1...10))-image.jpg"
)
]
)

return ResponseBodyDTO(success: true, data: mockData, error: nil)
}

func fetchMeetingPromiseList(
with meetingID: Int,
isParticipant: Bool?
) async throws -> ResponseBodyDTO<MeetingPromisesModel>? {
let mockData = MeetingPromisesModel(
promises: [
MeetingPromise(promiseID: 1,name: "꾸물 리프레시 데이",dDay: 0,time: "PM 2:00",placeName: "DMC역"),
MeetingPromise(promiseID: 2,name: "꾸물 잼얘 나이트",dDay: 10,time: "PM 6:00",placeName: "홍대입구"),
MeetingPromise(promiseID: 3,name: "친구 생일 파티",dDay: 5,time: "PM 7:00",placeName: "강남역"),
MeetingPromise(promiseID: 4,name: "주말 산책",dDay: 3,time: "AM 10:00",placeName: "서울숲"),
MeetingPromise(promiseID: 5,name: "프로젝트 미팅",dDay: 1,time: "AM 9:00",placeName: "삼성역"),
MeetingPromise(promiseID: 6,name: "독서 모임",dDay: 7,time: "PM 3:00",placeName: "합정역"),
MeetingPromise(promiseID: 7,name: "헬스클럽 모임",dDay: 2,time: "AM 8:00",placeName: "신촌역"),
MeetingPromise(promiseID: 8,name: "영화 관람",dDay: 4,time: "PM 8:00",placeName: "잠실역"),
MeetingPromise(promiseID: 9,name: "저녁 식사",dDay: 6,time: "PM 7:30",placeName: "이태원역"),
MeetingPromise(promiseID: 10,name: "아침 조깅",dDay: 14,time: "AM 6:00",placeName: "한강공원"),
MeetingPromise(promiseID: 11,name: "커피 브레이크",dDay: 8,time: "PM 4:00",placeName: "을지로입구"),
MeetingPromise(promiseID: 12,name: "스터디 그룹",dDay: 12,time: "PM 5:00",placeName: "강남역"),
MeetingPromise(promiseID: 13,name: "뮤직 페스티벌",dDay: 9,time: "PM 2:00",placeName: "난지공원"),
MeetingPromise(promiseID: 14, name: "낚시 여행", dDay: 11, time: "AM 5:00", placeName: "속초항"),
MeetingPromise(promiseID: 15, name: "가족 모임", dDay: 13, time: "PM 1:00", placeName: "광화문역")
]
)

return ResponseBodyDTO(success: true, data: mockData, error: nil)
}

func exitMeeting(with meetingID: Int) -> Single<ResponseBodyDTO<EmptyModel>> {
let falseResponse = ResponseBodyDTO<EmptyModel>(success: false, data: nil, error: nil)
return .just(falseResponse)
}
}

final class MockInviteCodeService: InviteCodeServiceProtocol {
func joinMeeting(with request: RegisterMeetingsModel) -> ResponseBodyDTO<RegisterMeetingsResponseModel>? {
let mockData = RegisterMeetingsResponseModel(
meetingID: 1
)

return ResponseBodyDTO<RegisterMeetingsResponseModel>.init(success: true, data: mockData, error: nil)
}
}
7 changes: 7 additions & 0 deletions KkuMulKum/Resource/Base/BaseViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ extension BaseViewController {
.font: UIFont.pretendard(.body03)
]

let barAppearance = UINavigationBarAppearance()
barAppearance.backgroundColor = .white
barAppearance.shadowColor = nil

navigationController?.navigationBar.standardAppearance = barAppearance
navigationController?.navigationBar.scrollEdgeAppearance = barAppearance

if !isBorderHidden {
addBorder()
}
Expand Down
6 changes: 3 additions & 3 deletions KkuMulKum/Resource/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPhotoLibraryUsageDescription</key>
<string>꾸물꿈은 카메라 권한을 필요로 합니다. 카메라를 통해 자신의 프로필을 즉시 찍어 업로드할 수 있습니다. 허용 안함 시 일부 기능이 동작하지 않을 수 있습니다.</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array/>
<array>
<string>kakao69aeef4a49d5b6772d62efdf1686994c</string>
</array>
</dict>
</array>
<key>FirebaseAppDelegateProxyEnabled</key>
Expand Down
56 changes: 20 additions & 36 deletions KkuMulKum/Source/MeetingInfo/Cell/MeetingMemberCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import SnapKit
import Then

protocol MeetingMemberCellDelegate: AnyObject {
func profileImageButtonDidTap()
func profileImageViewDidTap()
}

final class MeetingMemberCell: BaseCollectionViewCell {
private let profileImageButton = UIButton().then {
private let profileImageView: UIImageView = UIImageView().then {
$0.isUserInteractionEnabled = true
$0.layer.cornerRadius = Screen.height(64) / 2
$0.isEnabled = false
$0.clipsToBounds = true
}

Expand All @@ -28,47 +28,34 @@ final class MeetingMemberCell: BaseCollectionViewCell {
}

private weak var delegate: MeetingMemberCellDelegate?
private lazy var tapGesture = UITapGestureRecognizer(target: self, action: #selector(profileImageViewDidTap(_:)))

override func prepareForReuse() {
super.prepareForReuse()

profileImageButton.do {
var config = UIButton.Configuration.plain()
config.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)

$0.imageView?.image = nil
$0.backgroundColor = .clear
$0.isEnabled = false
}
profileImageView.image = nil
profileImageView.removeGestureRecognizer(tapGesture)

nameLabel.setText(style: .caption02, color: .gray6)
}

override func setupView() {
contentView.addSubviews(profileImageButton, nameLabel)
contentView.addSubviews(profileImageView, nameLabel)
}

override func setupAutoLayout() {
profileImageButton.snp.makeConstraints {
profileImageView.snp.makeConstraints {
$0.top.centerX.equalToSuperview()
$0.height.equalTo(Screen.height(64))
$0.width.equalTo(profileImageButton.snp.height)
$0.width.equalTo(profileImageView.snp.height)
}

nameLabel.snp.makeConstraints {
$0.top.equalTo(profileImageButton.snp.bottom).offset(4)
$0.centerX.equalTo(profileImageButton)
$0.top.equalTo(profileImageView.snp.bottom).offset(4)
$0.centerX.equalTo(profileImageView)
$0.bottom.equalToSuperview()
}
}

override func setupAction() {
profileImageButton.addTarget(
self,
action: #selector(profileImageButtonDidTap(_:)),
for: .touchUpInside
)
}
}

extension MeetingMemberCell {
Expand All @@ -91,15 +78,12 @@ private extension MeetingMemberCell {
func configureForAdd(with delegate: MeetingMemberCellDelegate) {
self.delegate = delegate

profileImageButton.do {
var config = UIButton.Configuration.plain()
config.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 0, bottom: 0, trailing: 0)

$0.configuration = config
profileImageView.do {
$0.image = .iconPlusDark.withRenderingMode(.alwaysOriginal)
$0.contentMode = .center
$0.backgroundColor = .gray1
$0.setImage(.iconPlus.withTintColor(.gray4), for: .normal)
$0.isEnabled = true
}
profileImageView.addGestureRecognizer(tapGesture)

nameLabel.setText(style: .caption02, color: .gray6)
}
Expand All @@ -110,15 +94,15 @@ private extension MeetingMemberCell {

nameLabel.setText(name ?? " ", style: .caption02, color: .gray6)

profileImageButton.kf.setImage(
profileImageView.kf.setImage(
with: imageURL,
for: .disabled,
placeholder: .imgProfile.withRenderingMode(.alwaysOriginal)
placeholder: UIImage(resource: .imgProfile).withRenderingMode(.alwaysOriginal)
)
profileImageView.contentMode = .scaleAspectFill
}

@objc
func profileImageButtonDidTap(_ sender: UIButton) {
delegate?.profileImageButtonDidTap()
func profileImageViewDidTap(_ sender: UIImageView) {
delegate?.profileImageViewDidTap()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import RxSwift
protocol MeetingInfoServiceProtocol {
func fetchMeetingInfo(with meetingID: Int) async throws -> ResponseBodyDTO<MeetingInfoModel>?
func fetchMeetingMemberList(with meetingID: Int) async throws -> ResponseBodyDTO<MeetingMembersModel>?
func fetchMeetingPromiseList(with meetingID: Int, isParticipant: Bool?) async throws -> ResponseBodyDTO<MeetingPromisesModel>?
func fetchMeetingPromiseList(with meetingID: Int) -> Single<ResponseBodyDTO<MeetingPromisesModel>>
func fetchParticipatedPromiseList(
with meetingID: Int,
isParticipant: Bool
) -> Single<ResponseBodyDTO<MeetingPromisesModel>>
func exitMeeting(with meetingID: Int) -> Single<ResponseBodyDTO<EmptyModel>>
}
4 changes: 3 additions & 1 deletion KkuMulKum/Source/MeetingInfo/View/MeetingInfoView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ final class MeetingInfoView: BaseView {
$0.setText("남은 약속을 확인해보세요", style: .body01, color: .gray7)
}

private let segmentedControl = UnderlineSegmentedControl(items: ["내가 속한 약속", "모든 약속"])
private let segmentedControl = UnderlineSegmentedControl(items: ["내가 속한 약속", "모든 약속"]).then {
$0.selectedSegmentIndex = 0
}

private let emptyDescriptionView = UIView(backgroundColor: .white).then {
$0.layer.cornerRadius = 8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ private extension MeetingInfoViewController {

output.navigateToPromiseInfo
.drive(with: self) { owner, promiseID in
guard let promiseID else { return }
guard promiseID > 0 else { return }

let pagePromiseViewController = PromiseViewController(
viewModel: PromiseViewModel(promiseID: promiseID, service: PromiseService())
Expand Down Expand Up @@ -223,7 +223,7 @@ extension MeetingInfoViewController: CustomActionSheetDelegate {
// MARK: - MeetingMemberCellDelegate

extension MeetingInfoViewController: MeetingMemberCellDelegate {
func profileImageButtonDidTap() {
func profileImageViewDidTap() {
guard let code = viewModel.meetingInvitationCode else { return }

let viewController = InvitationCodePopUpViewController(
Expand Down
Loading

0 comments on commit 727fc80

Please sign in to comment.