Skip to content

Commit

Permalink
Release/1.0.8 -> main (#286)
Browse files Browse the repository at this point in the history
* feat: BottleAlert Modifier 구현

* feat: ButtonAppearanceType cancel 추가

* feat: BottleAlertView 구현

* feat: BottleAlert 버튼 속성 수정

* chore: warning Image Assets 추가

* style: BottleAlert 네이밍 수정

* feat: BottleAlert 디자인시스템 반영

* feat: ArrowListView 구현

* feat: BottleToggle 구현

* feat: ToggleListView 구현

* feat: ListContainerView 구현

* feat: ButtonListView 구현

* feat: ListView 데모 앱 추가

* feat: ArrowListView arrowButton 사이즈 변경

* feat: 화살표 클릭시 action 실행하도록 수정

* Revert "feat: 화살표 클릭시 action 실행하도록 수정"

This reverts commit 19a5277.

* feat: TextListView 추가

- Title과 SubTitle만 있는 ListView

* feat: 마이페이지 변경된 View 구현

* [Feature/#239] 강제 업데이트 구현 로직 개선 (#250)

* [chore]: 불필요한 return 삭제

* chore: needUpdateAppVersion -> invalidAppVersion 명명 수정

* feat: URLHandler 모듈 생성 및 적용

* feat: AlertSettingFeature 생성

* feat: AlertSettingView 생성

* feat: MyPageRoot 구현

* feat: MainTab MyPageRootView 화면으로 수정

* feat: 알림 설정 클릭 시 AlertSettingView 화면 전환

* feat: 알림 설정 View 구현

* feat: AlertType 구현

* feat: AlertStateRequestDTO 구현

* feat: UserAPI 구현

* feat: AlertState 구현

* feat: AlertStateResponseDTO 구현

* feat: 알림 설정 진입 시 서버로부터 받아온 값으로 화면 표시

* feat: 각 토글 변경 시 API 호출 및 디바운스 설정

* feat: AccountSettingFeature 구현

* feat: AccountSettingView 구현

* feat: 계정 관리 클릭 시 화면 전환

* feat: 로그아웃, 탈퇴하기 구현

* feat: 매칭 토글 변경 시 API 호출

* feat: 계정관리 진입 시 매칭 활성화 여부 동기화

* [Feature/#251] 연락처 차단 기능 구현 (#256)

* feat: 연락처 차단 기능 구현

* refactor: BlockContactRequestDTO의 blockContacts 프로퍼티 접근제한자 수정

* fix: 누락된 의존성 주입

* refactor: 연락처 trim 로직 개선

* [Feature/#259] 마이페이지 1:1 문의 기능 구현 (#260)

* chore: 카카오톡 채널 톡 URL 추가

* feat: 1:1 문의 버튼 클릭 시 카카오톡 채널 톡으로 이동

* style: 줄바꿈 수정

* feat: 이용약관, 개인정보처리 클릭 시 기능 구현 (#262)

* [Feature/#257] 마이페이지 앱 버전 업데이트 기능 구현 (#258)

* feat: 마이페이지 버전 체크 및 업데이트 기능 구현

* feat: 연락처 차단 로직 수정

---------

Co-authored-by: leemhyungyu <[email protected]>

* [feature/#264] 마이페이지 프로필 수정 웹뷰 연결 (#270)

* [Feature/#263] 연락처 접근 권한 허용안함 시 설정 이동 (#265)

* feat: BottleURLType 설정 URLScheme 추가

* feat: 연락처 접근 권한 미허용시 설정으로 이동

* [Feature/#266] 마이페이지 진입 시 연락처 차단 개수 동기화 (#267)

* feat: UserInfo blockedContactsCount 추가

* feat: 마이페이지 onLoad시 차단된 전화번호수 동기화

* [Feature/#268] 연락처 차단 완료 시 Toast 띄우기 (#269)

* feat: 연락처 차단 업데이트 시 Toast 띄우기

* feat: 연락처 차단 업데이트 클릭 시 Alert 추가

* chore: 빌드 넘버 1.0.8 (29)

* chore: DomainAuth 의존성 추가

* feat: ProfileEditView bottom ignoreSafeArea 추가

* [Feature/#277] 웹뷰 os type, 버전 파라미터 추가 (#279)

* [Feature/#278] 웹뷰 상단 safe area 무시하도록 수정 (#284)

* [Fix/#280] 로그인화면 백그라운드 이미지 비율 수정 (#281)

* [Fix/#282] 로그인 화면 로그인 버튼 vstack 하단 마진 수정 (#283)

* [Feature/#232] 커스텀 alert 적용 (#272)

* feat: SplashView bottleAlert 적용

* feat: PingPongDetailView bottleAlert 적용

* feat: ReportUserView bottleAlert 적용

* feat: SandBeachView bottleAlert 적용

* feat: 탈퇴하기 Alert  message 수정 (#274)

* [Feature/#275] 알림 권한 미허용 시 alert 추가 (#276)

* feat: AppDelegate 푸시 수신 상태 Notification 등록

* feat: UserClient 푸시 알림 허용 상태 로직 추가

* feat: 푸시 알림 허용 상태에 따른 알림설정 화면 로직 구현

* feat: UserClient 푸쉬알림허용상태 Publisher 구현

* feat: 푸쉬알림허용상태에 따른 로직 변경

* feat: 토글 버튼 binding 코드 개선

- 코드리뷰 반영

* feat: UserClient UserDefaultKeys enum 추가

* feat: 오탈자 수정

- pushNotificationSubject -> pushNotificationAllowStatusSubject

* chore: 빌드 넘버 1.0.8 (30)

---------

Co-authored-by: JongHoon <[email protected]>
  • Loading branch information
leemhyungyu and JongHoooon authored Sep 26, 2024
1 parent ef162e7 commit 1c1a1f5
Show file tree
Hide file tree
Showing 93 changed files with 2,542 additions and 235 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public extension ModulePath {

public extension ModulePath {
enum Domain: String, CaseIterable {
case Application
case Error
case User
case Report
Expand All @@ -64,6 +65,7 @@ public extension ModulePath {

public extension ModulePath {
enum Core: String, CaseIterable {
case URLHandler
case Toast
case KeyChainStore
case WebView
Expand Down
42 changes: 40 additions & 2 deletions Projects/App/Sources/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ final class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate {
UIApplication.shared.registerForRemoteNotifications()
UNUserNotificationCenter.current().delegate = self
Messaging.messaging().delegate = self

setNotification()
application.registerForRemoteNotifications()

store.send(.appDelegate(.didFinishLunching))
return true
}
}

// MARK: - UNUserNotificationCenterDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {
func messaging(
_ messaging: Messaging,
Expand All @@ -62,3 +62,41 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
return [.badge, .sound, .banner, .list]
}
}

// MARK: - objc funcs
private extension AppDelegate {
@objc func checkPushNotificationStatus() {
UNUserNotificationCenter.current()
.getNotificationSettings { [weak self] permission in
guard let self = self else { return }
DispatchQueue.main.async {
switch permission.authorizationStatus {
case .notDetermined:
self.store.send(.appDelegate(.pushNotificationAllowStatusDidChanged(isAllow: true)))
case .denied:
self.store.send(.appDelegate(.pushNotificationAllowStatusDidChanged(isAllow: false)))
case .authorized:
self.store.send(.appDelegate(.pushNotificationAllowStatusDidChanged(isAllow: true)))
case .provisional:
self.store.send(.appDelegate(.pushNotificationAllowStatusDidChanged(isAllow: false)))
case .ephemeral:
self.store.send(.appDelegate(.pushNotificationAllowStatusDidChanged(isAllow: true)))
@unknown default:
Log.error("Unknow Notification Status")
}
}
}
}
}

// MARK: - Private Methods
private extension AppDelegate {
func setNotification() {
NotificationCenter.default.addObserver(
self,
selector: #selector(checkPushNotificationStatus),
name: UIApplication.willEnterForegroundNotification,
object: nil
)
}
}
3 changes: 2 additions & 1 deletion Projects/Core/Network/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ let project = Project.makeModule(
factory: .init(
dependencies: [
.core(interface: .Network),
.core(interface: .Logger)
.core(interface: .Logger),
.core(implements: .KeyChainStore)
]
)
),
Expand Down
31 changes: 31 additions & 0 deletions Projects/Core/URLHandler/Interface/Sources/BottleURLType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// BottleURLType.swift
// CoreURLHandlerInterface
//
// Created by JongHoon on 9/20/24.
//

import Foundation

public enum BottleURLType {
case bottleAppStore
case bottleAppLookUp
case kakaoChannelTalk
case setting

public var url: URL {
switch self {
case .bottleAppStore:
return URL(string: Bundle.main.infoDictionary?["APP_STORE_URL"] as? String ?? "")!

case .kakaoChannelTalk:
return URL(string: Bundle.main.infoDictionary?["KAKAO_CHANNEL_TALK_URL"] as? String ?? "")!

case .bottleAppLookUp:
return URL(string: Bundle.main.infoDictionary?["APP_LOOK_UP_URL"] as? String ?? "")!

case .setting:
return URL(string: "App-prefs:root=General")!
}
}
}
19 changes: 19 additions & 0 deletions Projects/Core/URLHandler/Interface/Sources/URLHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// URLHandler.swift
// CoreURLHandlerInterface
//
// Created by JongHoon on 9/20/24.
//

import UIKit

public final class URLHandler {

public static let shared = URLHandler()

private init() { }

public func openURL(urlType: BottleURLType) {
UIApplication.shared.open(urlType.url)
}
}
40 changes: 40 additions & 0 deletions Projects/Core/URLHandler/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

let project = Project.makeModule(
name: ModulePath.Core.name+ModulePath.Core.URLHandler.rawValue,
targets: [
.core(
interface: .URLHandler,
factory: .init()
),
.core(
implements: .URLHandler,
factory: .init(
dependencies: [
.core(interface: .URLHandler)
]
)
),

.core(
testing: .URLHandler,
factory: .init(
dependencies: [
.core(interface: .URLHandler)
]
)
),
.core(
tests: .URLHandler,
factory: .init(
dependencies: [
.core(testing: .URLHandler),
.core(implements: .URLHandler)
]
)
),

]
)
1 change: 1 addition & 0 deletions Projects/Core/URLHandler/Sources/Source.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// This is for Tuist
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// This is for Tuist
11 changes: 11 additions & 0 deletions Projects/Core/URLHandler/Tests/Sources/URLHandlerTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import XCTest

final class URLHandlerTests: XCTestCase {
override func setUpWithError() throws {}

override func tearDownWithError() throws {}

func testExample() {
XCTAssertEqual(1, 1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// ApplicationClient.swift
// DomainApplicationInterface
//
// Created by JongHoon on 9/22/24.
//

import Foundation

public struct ApplicationClient {
private let _fetchCurrentAppVersion: () -> String
private let fetchLatestAppVersion: () async throws -> String
private let checkNeedApplicationUpdate: () async throws -> Bool

public init(
fetchCurrentAppVersion: @escaping () -> String,
fetchLatestAppVersion: @escaping () async throws -> String,
checkNeedApplicationUpdate: @escaping () async throws -> Bool
) {
self._fetchCurrentAppVersion = fetchCurrentAppVersion
self.fetchLatestAppVersion = fetchLatestAppVersion
self.checkNeedApplicationUpdate = checkNeedApplicationUpdate
}

public func fetchCurrentAppVersion() -> String {
_fetchCurrentAppVersion()
}

public func fetchLatestAppVersion() async throws -> String {
try await fetchLatestAppVersion()
}

public func checkNeedApplicationUpdate() async throws -> Bool {
try await checkNeedApplicationUpdate()
}
}
44 changes: 44 additions & 0 deletions Projects/Domain/Application/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin

let project = Project.makeModule(
name: ModulePath.Domain.name+ModulePath.Domain.Application.rawValue,
targets: [
.domain(
interface: .Application,
factory: .init(
dependencies: [
.core
]
)
),
.domain(
implements: .Application,
factory: .init(
dependencies: [
.domain(interface: .Application)
]
)
),

.domain(
testing: .Application,
factory: .init(
dependencies: [
.domain(interface: .Application)
]
)
),
.domain(
tests: .Application,
factory: .init(
dependencies: [
.domain(testing: .Application),
.domain(implements: .Application)
]
)
),

]
)
66 changes: 66 additions & 0 deletions Projects/Domain/Application/Sources/ApplicationClient.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// ApplicationClient.swift
// DomainApplicationInterface
//
// Created by JongHoon on 9/22/24.
//

import Foundation

import DomainApplicationInterface
import DomainErrorInterface

import CoreURLHandlerInterface
import CoreURLHandler

import Dependencies

extension ApplicationClient: DependencyKey {
static public var liveValue: ApplicationClient = .live()

static func live() -> ApplicationClient {
@Dependency(\.applicationClient) var applicationClient
return .init(
fetchCurrentAppVersion: {
let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String
return version
},
fetchLatestAppVersion: {
let appLookUpURL = BottleURLType.bottleAppLookUp.url
let (data, _) = try await URLSession.shared.data(from: appLookUpURL)
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
let results = json["results"] as? [[String: Any]],
let appStoreVersion = results.first?["version"] as? String {
return appStoreVersion
} else {
throw DomainError.unknown("fetch latest app version failed")
}
},
checkNeedApplicationUpdate: {
let currentAppVersion = applicationClient.fetchCurrentAppVersion()
let latestAppVersion = try await applicationClient.fetchLatestAppVersion()
let currentAppVersionArray = currentAppVersion.split(separator: ".").compactMap { Int($0) }
let latestAppVersionArray = latestAppVersion.split(separator: ".").compactMap { Int($0) }

let maxLength = max(currentAppVersionArray.count, latestAppVersionArray.count)

for i in 0..<maxLength {
let currentVersion = i < currentAppVersionArray.count ? currentAppVersionArray[i] : 0
let latestVersion = i < latestAppVersionArray.count ? latestAppVersionArray[i] : 0

if latestVersion > currentVersion {
return true
}
}
return false
}
)
}
}

extension DependencyValues {
public var applicationClient: ApplicationClient {
get { self[ApplicationClient.self] }
set { self[ApplicationClient.self] = newValue }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// This is for Tuist
11 changes: 11 additions & 0 deletions Projects/Domain/Application/Tests/Sources/ApplicationTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import XCTest

final class ApplicationTests: XCTestCase {
override func setUpWithError() throws {}

override func tearDownWithError() throws {}

func testExample() {
XCTAssertEqual(1, 1)
}
}
2 changes: 1 addition & 1 deletion Projects/Domain/Auth/Interface/Sources/AuthClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public struct AuthClient {
}

public func checkUpdateVersion() async throws {
return try await checkUpdateVersion()
try await checkUpdateVersion()
}
}

3 changes: 2 additions & 1 deletion Projects/Domain/Auth/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ let project = Project.makeModule(
factory: .init(
dependencies: [
.domain(interface: .Auth),
.domain(interface: .Error)
.domain(interface: .Error),
.domain(implements: .User)
]
)
),
Expand Down
2 changes: 1 addition & 1 deletion Projects/Domain/Auth/Sources/AuthClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ extension AuthClient: DependencyKey {

guard minimumBuildNumber <= buildNumber
else {
throw DomainError.AuthError.needUpdateAppVersion
throw DomainError.AuthError.invalidAppVersion
}
}
)
Expand Down
2 changes: 1 addition & 1 deletion Projects/Domain/Error/Interface/Sources/DomainError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation

public enum DomainError: Error {
public enum AuthError: Error {
case needUpdateAppVersion
case invalidAppVersion
}

case unknown(_ message: String? = nil)
Expand Down
Loading

0 comments on commit 1c1a1f5

Please sign in to comment.