Skip to content

Commit

Permalink
[WEAV-80] MVI 구조 적용 (#27)
Browse files Browse the repository at this point in the history
* [WEAV-80] MVI 아키텍쳐 구조

* [Template] MVI 아키텍쳐 템플릿 추가

* [WEAV-80] MVI loading, error 추가/

* [WEAV-80] 기존 뷰 MVI 로 전환
  • Loading branch information
jisu15-kim authored Oct 8, 2024
1 parent e3af915 commit ffbacdc
Show file tree
Hide file tree
Showing 34 changed files with 1,806 additions and 219 deletions.
2 changes: 1 addition & 1 deletion Projects/Core/CommonKit/Sources/AppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public final class AppCoordinator: ObservableObject {
public func changeRootView(_ path: PathType) {
push(path)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { // 애니메이션 시간에 맞춰 조정
self.navigationStack.removeFirst()
self.navigationStack.removeSubrange(0 ..< self.navigationStack.count - 1)
}
}

Expand Down
35 changes: 35 additions & 0 deletions Projects/Core/CommonKit/Sources/Navigation+Ext.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Navigation+Ext.swift
// CoreKit
//
// Created by 김지수 on 10/3/24.
// Copyright © 2024 com.weave. All rights reserved.
//

import SwiftUI
import DesignCore

private struct NavigationViewModifier: ViewModifier {
let showLeftBackButton: Bool

func body(content: Content) -> some View {
content
.setNavigation(
showLeftBackButton: showLeftBackButton
)
{
AppCoordinator.shared.pop()
}
}
}

public extension View {
func setNavigationWithPop() -> some View {
return modifier(
NavigationViewModifier(
showLeftBackButton: true
)
)
}
}

23 changes: 23 additions & 0 deletions Projects/Core/CoreKit/Sources/ErrorModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// ErrorModel.swift
// CoreKit
//
// Created by 김지수 on 10/3/24.
// Copyright © 2024 com.weave. All rights reserved.
//

import Foundation

public struct ErrorModel {
public let title: String?
public let message: String?

public init(
title: String?,
message: String?
) {
self.title = title
self.message = message
}
}

30 changes: 30 additions & 0 deletions Projects/Core/CoreKit/Sources/MVIContainer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// MVIContainer.swift
// CoreKit
//
// Created by 김지수 on 10/3/24.
// Copyright © 2024 com.weave. All rights reserved.
//

import SwiftUI
import Combine

final public class MVIContainer<Intent, Model>: ObservableObject {
// MARK: Public
public let intent: Intent
public var model: Model

// MARK: private
private var cancellable: Set<AnyCancellable> = []

// MARK: Life cycle
public init(intent: Intent, model: Model, modelChangePublisher: ObjectWillChangePublisher) {
self.intent = intent
self.model = model

modelChangePublisher
.receive(on: RunLoop.main)
.sink(receiveValue: objectWillChange.send)
.store(in: &cancellable)
}
}
38 changes: 38 additions & 0 deletions Projects/DesignSystem/DesignCore/Sources/ErrorView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// ErrorView.swift
// DesignCore
//
// Created by 김지수 on 10/3/24.
// Copyright © 2024 com.weave. All rights reserved.
//

import SwiftUI

private struct ErrorViewModifier: ViewModifier {
var error: Error?

func body(content: Content) -> some View {
content
.overlay {
if let error {
errorView(error: error)
}
}
}

// Error View
@ViewBuilder
func errorView(error: Error) -> some View {
ZStack {
BackgroundTextureView(.init(hex: 0xF5F1EE))
Text(error.localizedDescription)
.typography(.semibold_20)
}
}
}

public extension View {
func setErrorViewIfNeeded(error: Error?) -> some View {
modifier(ErrorViewModifier(error: error))
}
}
42 changes: 42 additions & 0 deletions Projects/DesignSystem/DesignCore/Sources/LoadingView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// LoadingView.swift
// DesignCore
//
// Created by 김지수 on 10/4/24.
// Copyright © 2024 com.weave. All rights reserved.
//

import SwiftUI

private struct FullScreenLoadingOverlay: View {
var body: some View {
GeometryReader { geometry in
ZStack {
Color.black.opacity(0.2)
ProgressView()
}
.frame(width: geometry.size.width, height: geometry.size.height)
}
.ignoresSafeArea()
}
}


private struct LoadingViewModifier: ViewModifier {
let isLoading: Bool

func body(content: Content) -> some View {
content
.overlay {
if isLoading {
FullScreenLoadingOverlay()
}
}
}
}

public extension View {
func setLoading(_ isLoading: Bool) -> some View {
modifier(LoadingViewModifier(isLoading: isLoading))
}
}
Original file line number Diff line number Diff line change
@@ -1,82 +1,12 @@
//
// AuthPhoneVerifyView.swift
// DesignPreview
// VerifyCodeInputView.swift
// DesignCore
//
// Created by 김지수 on 10/1/24.
// Created by 김지수 on 10/4/24.
// Copyright © 2024 com.weave. All rights reserved.
//

import SwiftUI
import CoreKit
import DesignCore
import CommonKit

public struct AuthPhoneVerifyView: View {

@State var verifyCode = ""
@State var errorMessage: String? = "에러에여"
@FocusState private var verifyTextFieldFocused: Bool

public init() {}

public var body: some View {
VStack(spacing: 30) {
LeftAlignText("인증코드를 입력해주세요")
.typography(.semibold_24)

VerifyCodeInputView(
verifyCode: $verifyCode,
errorMessage: $errorMessage,
focused: _verifyTextFieldFocused
)

Button(
action: {

},
label: {
Text("010-1234-1234로 코드 재전송")
.typography(.regular_14)
.padding(.horizontal, 16)
.padding(.vertical, 8)
.background {
RoundedRectangle(cornerRadius: 12)
.foregroundStyle(
Color(
hex: 0x454545,
opacity: 0.06
)
)
}
}
)
.tint(DesignCore.Colors.grey300)

Spacer()
}
.onChange(of: verifyCode) {
if verifyCode.count == 6 {
AppCoordinator.shared.push(.signUp(.authAgreement))
}
}
.onAppear {
verifyTextFieldFocused = true
}
.ignoresSafeArea(.all)
.padding(.horizontal, 26)
.padding(.top, 14)
.textureBackground()
.setNavigation {
AppCoordinator.shared.pop()
}
}
}

#Preview {
NavigationView {
AuthPhoneVerifyView()
}
}

public struct VerifyCodeInputView: View {

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// AuthAgreementIntent.swift
// SignUp
//
// Created by 김지수 on 10/5/24.
// Copyright © 2024 com.weave. All rights reserved.
//

import Foundation
import CommonKit
import CoreKit

//MARK: - Intent
class AuthAgreementIntent {
private weak var model: AuthAgreementModelActionable?
private let externalData: DataModel

// MARK: Life cycle
init(
model: AuthAgreementModelActionable,
externalData: DataModel
) {
self.externalData = externalData
self.model = model
}
}

//MARK: - Intentable
extension AuthAgreementIntent {
protocol Intentable {
// content
func onTapNextButton()

// default
func onAppear()
func task() async
}

struct DataModel {}
}

//MARK: - Intentable
extension AuthAgreementIntent: AuthAgreementIntent.Intentable {
// default
func onAppear() {}

func task() async {}

// content
func onTapNextButton() {
Task {
await AppCoordinator.shared.changeRootView(
.signUp(.authGreeting)
)
}
}
}
Loading

0 comments on commit ffbacdc

Please sign in to comment.