diff --git a/SOPT-iOS/Projects/Core/Sources/Extension/UIKit+/UILabel+.swift b/SOPT-iOS/Projects/Core/Sources/Extension/UIKit+/UILabel+.swift index 646c2878c..7cd4e4990 100644 --- a/SOPT-iOS/Projects/Core/Sources/Extension/UIKit+/UILabel+.swift +++ b/SOPT-iOS/Projects/Core/Sources/Extension/UIKit+/UILabel+.swift @@ -11,7 +11,20 @@ public extension UILabel { /// 행간 조정 메서드 func setLineSpacing(lineSpacing: CGFloat) { - if let text = self.text { + // 기존에 attributedText가 존재할 경우, 덮어쓰지 않고 그대로 유지 + if let attributedText = self.attributedText { + let mutableAttributedString = NSMutableAttributedString(attributedString: attributedText) + + mutableAttributedString.enumerateAttribute(.paragraphStyle, + in: NSRange(location: 0, length: mutableAttributedString.length), + options: []) { value, range, _ in + let paragraphStyle = (value as? NSMutableParagraphStyle) ?? NSMutableParagraphStyle() + paragraphStyle.lineSpacing = lineSpacing + mutableAttributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: range) + } + + self.attributedText = mutableAttributedString + } else if let text = self.text { let attributedStr = NSMutableAttributedString(string: text) let style = NSMutableParagraphStyle() style.lineSpacing = lineSpacing @@ -118,7 +131,6 @@ public extension UILabel { attributedString.addAttributes([NSAttributedString.Key.foregroundColor: defaultColor], range: range) self.attributedText = attributedString - } catch let error { print("htmlToString 변환 에러: ", error.localizedDescription) } diff --git a/SOPT-iOS/Projects/Features/AppMyPageFeature/Sources/AppMypageScene/AppMyPageVC.swift b/SOPT-iOS/Projects/Features/AppMyPageFeature/Sources/AppMypageScene/AppMyPageVC.swift index 3800779f5..2e405abc8 100644 --- a/SOPT-iOS/Projects/Features/AppMyPageFeature/Sources/AppMypageScene/AppMyPageVC.swift +++ b/SOPT-iOS/Projects/Features/AppMyPageFeature/Sources/AppMypageScene/AppMyPageVC.swift @@ -184,6 +184,11 @@ extension AppMyPageVC { self.bindViews() self.bindViewModels() } + + public override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.setGestureDelegate() + } } extension AppMyPageVC { @@ -338,3 +343,15 @@ extension AppMyPageVC { SFSafariViewController.DataStore.default.clearWebsiteData() } } + +// MARK: - UIGestureRecognizerDelegate + +extension AppMyPageVC: UIGestureRecognizerDelegate { + private func setGestureDelegate() { + self.navigationController?.interactivePopGestureRecognizer?.delegate = self + } + + public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + return true + } +} diff --git a/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/VC/AttendanceVC.swift b/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/VC/AttendanceVC.swift index 244989c10..518525904 100644 --- a/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/VC/AttendanceVC.swift +++ b/SOPT-iOS/Projects/Features/AttendanceFeature/Sources/AttendanceScene/VC/AttendanceVC.swift @@ -28,7 +28,7 @@ public final class AttendanceVC: UIViewController, AttendanceViewControllable { static let bottomButtonHeight = 48.f static let customSpacing = 32.f - static let keyboardBottomOffset = 34.f // 피그마에 40인데 수정했음 + static let keyboardBottomOffset = 34.f } // MARK: - Properties diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/CalendarDetailScene/VC/HomeCalendarDetailVC.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/CalendarDetailScene/VC/HomeCalendarDetailVC.swift index d28daac50..7f8518cc5 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/CalendarDetailScene/VC/HomeCalendarDetailVC.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/CalendarDetailScene/VC/HomeCalendarDetailVC.swift @@ -86,6 +86,11 @@ final class HomeCalendarDetailVC: UIViewController, HomeCalendarDetailViewContro } } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.setGestureDelegate() + } + deinit { collectionView.dataSource = nil collectionView.delegate = nil @@ -196,3 +201,15 @@ extension HomeCalendarDetailVC: UICollectionViewDelegateFlowLayout, UICollection return 0 } } + +// MARK: - UIGestureRecognizerDelegate + +extension HomeCalendarDetailVC: UIGestureRecognizerDelegate { + private func setGestureDelegate() { + self.navigationController?.interactivePopGestureRecognizer?.delegate = self + } + + public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + return true + } +} diff --git a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/ViewModel/ServiceTypeExtension.swift b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/ViewModel/ServiceTypeExtension.swift index f43fabbe1..3bfc3037c 100644 --- a/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/ViewModel/ServiceTypeExtension.swift +++ b/SOPT-iOS/Projects/Features/HomeFeature/Sources/HomeScene/ViewModel/ServiceTypeExtension.swift @@ -19,7 +19,8 @@ extension ServiceType { case .review: return DSKitAsset.Assets.imgReviewLogo.image case .project: - return DSKitAsset.Assets.imgProjectLogo.image + let userType = UserDefaultKeyList.Auth.getUserType() + return userType == .visitor ? DSKitAsset.Assets.imgProjectLogo.image : DSKitAsset.Assets.imgActiveProjectLogo.image case .member: return DSKitAsset.Assets.imgUserLogo.image case .group: diff --git a/SOPT-iOS/Projects/Features/NotificationFeature/Sources/NotificationDetailScene/VC/NotificationDetailVC.swift b/SOPT-iOS/Projects/Features/NotificationFeature/Sources/NotificationDetailScene/VC/NotificationDetailVC.swift index 864965762..697aff5b3 100644 --- a/SOPT-iOS/Projects/Features/NotificationFeature/Sources/NotificationDetailScene/VC/NotificationDetailVC.swift +++ b/SOPT-iOS/Projects/Features/NotificationFeature/Sources/NotificationDetailScene/VC/NotificationDetailVC.swift @@ -111,6 +111,11 @@ public final class NotificationDetailVC: UIViewController, NotificationDetailVie self.setUI() self.setLayout() } + + public override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.setGestureDelegate() + } } // MARK: - UI & Layout @@ -196,3 +201,15 @@ extension NotificationDetailVC { self.shortCutButton.isHidden = !notification.hasLink } } + +// MARK: - UIGestureRecognizerDelegate + +extension NotificationDetailVC: UIGestureRecognizerDelegate { + private func setGestureDelegate() { + self.navigationController?.interactivePopGestureRecognizer?.delegate = self + } + + public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + return true + } +} diff --git a/SOPT-iOS/Projects/Features/NotificationFeature/Sources/NotificationListScene/VC/NotificationListVC.swift b/SOPT-iOS/Projects/Features/NotificationFeature/Sources/NotificationListScene/VC/NotificationListVC.swift index 8b4775a61..b4b7865c4 100644 --- a/SOPT-iOS/Projects/Features/NotificationFeature/Sources/NotificationListScene/VC/NotificationListVC.swift +++ b/SOPT-iOS/Projects/Features/NotificationFeature/Sources/NotificationListScene/VC/NotificationListVC.swift @@ -91,6 +91,7 @@ public final class NotificationListVC: UIViewController, NotificationListViewCon public override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.notificationListCollectionView.reloadData() + self.setGestureDelegate() } } @@ -249,3 +250,15 @@ extension NotificationListVC: UICollectionViewDelegate { } } } + +// MARK: - UIGestureRecognizerDelegate + +extension NotificationListVC: UIGestureRecognizerDelegate { + private func setGestureDelegate() { + self.navigationController?.interactivePopGestureRecognizer?.delegate = self + } + + public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + return true + } +} diff --git a/SOPT-iOS/Projects/Features/RootFeature/Sources/NotificationHelpers/NotificationHandler.swift b/SOPT-iOS/Projects/Features/RootFeature/Sources/NotificationHelpers/NotificationHandler.swift index c20905ec7..594d4c570 100644 --- a/SOPT-iOS/Projects/Features/RootFeature/Sources/NotificationHelpers/NotificationHandler.swift +++ b/SOPT-iOS/Projects/Features/RootFeature/Sources/NotificationHelpers/NotificationHandler.swift @@ -29,9 +29,6 @@ public final class NotificationHandler: NSObject, UNUserNotificationCenterDelega print("APNs 푸시 알림 페이로드: \(userInfo)") if let payload = NotificationPayload(dictionary: userInfo) { AmplitudeInstance.shared.track(eventType: .receivedPush, eventProperties: ["notificationId": payload.id, - "send_timeStamp": payload.sendAt, - "title": payload.title, - "contents": payload.content, "admin_category": payload.category ?? "없음"]) } @@ -41,11 +38,11 @@ public final class NotificationHandler: NSObject, UNUserNotificationCenterDelega @MainActor public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async { let userInfo = response.notification.request.content.userInfo + print(userInfo) print("APNs 푸시 알림 페이로드: \(userInfo)") guard let payload = NotificationPayload(dictionary: userInfo) else { return } AmplitudeInstance.shared.track(eventType: .clickPush, eventProperties: ["notificationId": payload.id, - "send_timeStamp": payload.sendAt, "leadtime": "", "contain_deeplink": payload.hasDeepLink, "deeplink_url": payload.deepLink ?? "없음"]) diff --git a/SOPT-iOS/Projects/Features/RootFeature/Sources/NotificationHelpers/NotificationPayload.swift b/SOPT-iOS/Projects/Features/RootFeature/Sources/NotificationHelpers/NotificationPayload.swift index 98e26628e..5372015a3 100644 --- a/SOPT-iOS/Projects/Features/RootFeature/Sources/NotificationHelpers/NotificationPayload.swift +++ b/SOPT-iOS/Projects/Features/RootFeature/Sources/NotificationHelpers/NotificationPayload.swift @@ -12,9 +12,6 @@ import Sentry public struct NotificationPayload: Codable { public let aps: APS public let id: String - public let title: String - public let content: String - public let sendAt: String public let category: String? public let deepLink: String? public let webLink: String? diff --git a/SOPT-iOS/Projects/Features/SoptlogFeature/Interface/Sources/SoptlogToolTipPresentable.swift b/SOPT-iOS/Projects/Features/SoptlogFeature/Interface/Sources/SoptlogToolTipPresentable.swift index 3b4f80550..b94ce1bf9 100644 --- a/SOPT-iOS/Projects/Features/SoptlogFeature/Interface/Sources/SoptlogToolTipPresentable.swift +++ b/SOPT-iOS/Projects/Features/SoptlogFeature/Interface/Sources/SoptlogToolTipPresentable.swift @@ -14,6 +14,7 @@ import Core public protocol SoptlogToolTipViewControllable: ViewControllable { } public protocol SoptlogToolTipCoordinatable { var onDismissButtonTap: (() -> Void)? { get set } + var onDimmingBackgroundTap: (() -> Void)? { get set } } public typealias SoptlogToolTipViewModelType = ViewModelType & SoptlogToolTipCoordinatable public typealias SoptlogTooltipPresentable = (vc: SoptlogToolTipViewControllable, vm: any SoptlogToolTipViewModelType) diff --git a/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/Cell/SoptlogAppServiceCVC.swift b/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/Cell/SoptlogAppServiceCVC.swift index e0c2e1f06..907d5f126 100644 --- a/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/Cell/SoptlogAppServiceCVC.swift +++ b/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/Cell/SoptlogAppServiceCVC.swift @@ -93,6 +93,8 @@ extension SoptlogAppServiceCVC { private func setStackView() { serviceTitleStackView.addArrangedSubviews(serviceLabel, infoToolTipButton) + serviceTitleStackView.setCustomSpacing(1, after: serviceLabel) + stackView.addArrangedSubviews(serviceTitleStackView, serviceImageView, serviceValue) } } diff --git a/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/Coordinator/SoptlogCoordinator.swift b/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/Coordinator/SoptlogCoordinator.swift index a91e7ff1a..6cd87d4e0 100644 --- a/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/Coordinator/SoptlogCoordinator.swift +++ b/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/Coordinator/SoptlogCoordinator.swift @@ -81,7 +81,11 @@ public final class SoptlogCoordinator: DefaultCoordinator { var soptlogToolTip = factory.makeSoptlogToolTip(frame) soptlogToolTip.vm.onDismissButtonTap = { [weak self] in - self?.rootViewController?.dismiss(animated: true ) + self?.rootViewController?.dismiss(animated: true) + } + + soptlogToolTip.vm.onDimmingBackgroundTap = { [weak self] in + self?.rootViewController?.dismiss(animated: true) } soptlogToolTip.vc.viewController.modalPresentationStyle = .overFullScreen diff --git a/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/VC/SoptlogToolTipVC.swift b/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/VC/SoptlogToolTipVC.swift index 0e77155ea..7c75343f3 100644 --- a/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/VC/SoptlogToolTipVC.swift +++ b/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/VC/SoptlogToolTipVC.swift @@ -20,6 +20,8 @@ final class SoptlogToolTipVC: UIViewController, SoptlogToolTipViewControllable { public var viewModel: SoptlogToolTipViewModel private let cancelBag = CancelBag() private let toolTipFrame: CGRect + + private var dimmingBackgroundTap = PassthroughSubject() // MARK: - UI Components @@ -55,6 +57,7 @@ final class SoptlogToolTipVC: UIViewController, SoptlogToolTipViewControllable { $0.text = I18N.Soptlog.toolTip $0.font = DSKitFontFamily.Suit.medium.font(size: 13) $0.numberOfLines = 0 + $0.setLineSpacing(lineSpacing: 4) } init(viewModel: SoptlogToolTipViewModel, toolTipFrame: CGRect) { @@ -75,6 +78,8 @@ final class SoptlogToolTipVC: UIViewController, SoptlogToolTipViewControllable { } } +// MARK: - UI & Layout + extension SoptlogToolTipVC { private func setUI() { self.view.backgroundColor = DSKitAsset.Colors.black100.color.withAlphaComponent(0.6) @@ -124,12 +129,30 @@ extension SoptlogToolTipVC { } } +// MARK: - Methods + extension SoptlogToolTipVC { private func bindViewModels() { let input = SoptlogToolTipViewModel.Input( - dismissbuttonTap: self.dismissButton.publisher(for: .touchUpInside).mapVoid().asDriver() + dismissbuttonTap: self.dismissButton.publisher(for: .touchUpInside).mapVoid().asDriver(), + dimmingBackgroundTap: self.dimmingBackgroundTap.asDriver() ) _ = viewModel.transform(from: input, cancelBag: cancelBag) } } + +// MARK: - Override Methods + +extension SoptlogToolTipVC { + /// dimming 뒷배경을 눌렀을 때, dismiss 이벤트를 전달합니다. + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + guard let touch = touches.first else { return } + let location = touch.location(in: self.view) + // toolTipView 프레임의 밖일 경우에만 dismiss + if !toolTipView.frame.contains(location) { + self.dimmingBackgroundTap.send() + } + super.touchesBegan(touches, with: event) + } +} diff --git a/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/ViewModel/SoptlogToolTipViewModel.swift b/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/ViewModel/SoptlogToolTipViewModel.swift index f13864d12..775c868c4 100644 --- a/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/ViewModel/SoptlogToolTipViewModel.swift +++ b/SOPT-iOS/Projects/Features/SoptlogFeature/Sources/SoptlogScene/ViewModel/SoptlogToolTipViewModel.swift @@ -24,6 +24,7 @@ public class SoptlogToolTipViewModel: SoptlogToolTipViewModelType { public struct Input { let dismissbuttonTap: Driver + let dimmingBackgroundTap: Driver } // MARK: - Outputs @@ -33,7 +34,7 @@ public class SoptlogToolTipViewModel: SoptlogToolTipViewModelType { // MARK: - SoptlogToolTipCoordinatable public var onDismissButtonTap: (() -> Void)? - + public var onDimmingBackgroundTap: (() -> Void)? // MARK: - initialization @@ -52,6 +53,12 @@ extension SoptlogToolTipViewModel { owner.onDismissButtonTap?() }.store(in: cancelBag) + input.dimmingBackgroundTap + .withUnretained(self) + .sink { owner, _ in + owner.onDimmingBackgroundTap?() + }.store(in: cancelBag) + return output } } diff --git a/SOPT-iOS/Projects/Features/WebFeature/Sources/SOPTWebView.swift b/SOPT-iOS/Projects/Features/WebFeature/Sources/SOPTWebView.swift index bf9ce0a12..1bba6fa0f 100644 --- a/SOPT-iOS/Projects/Features/WebFeature/Sources/SOPTWebView.swift +++ b/SOPT-iOS/Projects/Features/WebFeature/Sources/SOPTWebView.swift @@ -64,13 +64,16 @@ public final class SOPTWebView: UIViewController, SOPTWebViewControllable { self.view.backgroundColor = DSKitAsset.Colors.black100.color - self.webView.scrollView.delegate = self - self.webView.navigationDelegate = self - self.webView.uiDelegate = self downloadManager.webVC = self self.initializeViews() self.setupConstraints() self.setupNavigationButtonActions() + self.setDelegate() + } + + public override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.setGestureDelegate() } } @@ -110,6 +113,12 @@ extension SOPTWebView { self?.navigationController?.popViewController(animated: true) }.store(in: self.cancelbag) } + + private func setDelegate() { + self.webView.scrollView.delegate = self + self.webView.navigationDelegate = self + self.webView.uiDelegate = self + } } extension SOPTWebView: WKNavigationDelegate { @@ -165,3 +174,15 @@ extension SOPTWebView: WKDownloadDelegate { download.delegate = self } } + +// MARK: - UIGestureRecognizerDelegate + +extension SOPTWebView: UIGestureRecognizerDelegate { + private func setGestureDelegate() { + self.navigationController?.interactivePopGestureRecognizer?.delegate = self + } + + public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + return true + } +} diff --git a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_active_project_logo.imageset/Contents.json b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_active_project_logo.imageset/Contents.json new file mode 100644 index 000000000..8bea1346e --- /dev/null +++ b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_active_project_logo.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Frame 1171275665.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_active_project_logo.imageset/Frame 1171275665.svg b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_active_project_logo.imageset/Frame 1171275665.svg new file mode 100644 index 000000000..e9fdf2a84 --- /dev/null +++ b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_active_project_logo.imageset/Frame 1171275665.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_playground_logo.imageset/Contents.json b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_playground_logo.imageset/Contents.json index 5cdc2aad6..5e31e02e8 100644 --- a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_playground_logo.imageset/Contents.json +++ b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_playground_logo.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "Layer_1.svg", + "filename" : "Frame 1171275665@2x.svg", "idiom" : "universal" } ], diff --git a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_playground_logo.imageset/Frame 1171275665@2x.svg b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_playground_logo.imageset/Frame 1171275665@2x.svg new file mode 100644 index 000000000..3decf271b --- /dev/null +++ b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_playground_logo.imageset/Frame 1171275665@2x.svg @@ -0,0 +1,4 @@ + + + + diff --git a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_playground_logo.imageset/Layer_1.svg b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_playground_logo.imageset/Layer_1.svg deleted file mode 100644 index c1920c6cb..000000000 --- a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Home/Image/img_playground_logo.imageset/Layer_1.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - -