Skip to content

Commit 0f501e5

Browse files
authored
Merge pull request #184 from YAPP-Github/feat/#171-ready-2.0
feat: 2.0.0 μ€€λΉ„μž‘μ—…
2 parents 5e3fdd3 + 4fdf986 commit 0f501e5

File tree

32 files changed

+771
-71
lines changed

32 files changed

+771
-71
lines changed

β€ŽProjects/App/Project.swiftβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ let shareExtensionTarget: Target = .target(
2626
resources: ["ShareExtension/Resources/**"],
2727
entitlements: .file(path: .relativeToRoot("Projects/App/ShareExtension/ShareExtension.entitlements")),
2828
dependencies: [
29-
.project(target: "FeatureLogin", path: .relativeToRoot("Projects/Feature")),
29+
.project(target: "FeatureIntro", path: .relativeToRoot("Projects/Feature")),
3030
.project(target: "FeatureContentSetting", path: .relativeToRoot("Projects/Feature")),
3131
.project(target: "FeatureCategorySetting", path: .relativeToRoot("Projects/Feature"))
3232
],

β€ŽProjects/App/Resources/LaunchScreen.storyboardβ€Ž

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23086.1" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23094" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
33
<device id="retina6_12" orientation="portrait" appearance="light"/>
44
<dependencies>
55
<deployment identifier="iOS"/>
6-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23076"/>
6+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23084"/>
77
<capability name="Named colors" minToolsVersion="9.0"/>
88
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
99
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -17,18 +17,20 @@
1717
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
1818
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
1919
<subviews>
20-
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" ambiguous="YES" image="logo_pokit" translatesAutoresizingMaskIntoConstraints="NO" id="N4N-la-jgc">
20+
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="logo_pokit" translatesAutoresizingMaskIntoConstraints="NO" id="N4N-la-jgc">
2121
<rect key="frame" x="79" y="313" width="235" height="72"/>
2222
<color key="tintColor" name="text/inverseWh"/>
2323
<constraints>
24-
<constraint firstAttribute="height" constant="72" id="9zI-nL-qB4"/>
24+
<constraint firstAttribute="height" constant="72" id="ZJY-IM-p0S"/>
25+
<constraint firstAttribute="width" constant="235" id="zXd-Y5-GFp"/>
2526
</constraints>
2627
</imageView>
2728
</subviews>
2829
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
2930
<color key="backgroundColor" name="orange/700"/>
3031
<constraints>
31-
<constraint firstItem="N4N-la-jgc" firstAttribute="top" secondItem="Bcu-3y-fUS" secondAttribute="top" constant="254" id="kHx-5E-p7o"/>
32+
<constraint firstItem="N4N-la-jgc" firstAttribute="top" secondItem="Bcu-3y-fUS" secondAttribute="top" constant="254" id="5x5-8D-gix"/>
33+
<constraint firstItem="N4N-la-jgc" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="zAv-Q1-gIH"/>
3234
</constraints>
3335
</view>
3436
</viewController>
@@ -40,7 +42,7 @@
4042
<resources>
4143
<image name="logo_pokit" width="235" height="72"/>
4244
<namedColor name="orange/700">
43-
<color red="0.99607843137254903" green="0.51764705882352946" blue="0.13333333333333333" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
45+
<color red="0.99607843137254903" green="0.51764705882352946" blue="0.13333333333333333" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
4446
</namedColor>
4547
<namedColor name="text/inverseWh">
4648
<color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>

β€ŽProjects/App/ShareExtension/Sources/ShareRootFeature.swiftβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import UIKit
99
import UniformTypeIdentifiers
1010

1111
import ComposableArchitecture
12-
import FeatureLogin
12+
import FeatureIntro
1313
import FeatureContentSetting
1414
import FeatureCategorySetting
1515
import CoreKit

β€ŽProjects/App/ShareExtension/Sources/ShareRootView.swiftβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import SwiftUI
99

1010
import ComposableArchitecture
11-
import FeatureLogin
11+
import FeatureIntro
1212
import FeatureContentSetting
1313
import FeatureCategorySetting
1414
import DSKit

β€ŽProjects/App/Sources/Root/RootFeature.swiftβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import Foundation
99

1010
import ComposableArchitecture
11-
import FeatureLogin
11+
import FeatureIntro
1212
import CoreKit
1313

1414
@Reducer

β€ŽProjects/App/Sources/Root/RootView.swiftβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import SwiftUI
99

1010
import ComposableArchitecture
11-
import FeatureLogin
11+
import FeatureIntro
1212
import DSKit
1313

1414
public struct RootView: View {

β€ŽProjects/DSKit/Sources/Components/PokitHeader.swiftβ€Ž

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
import SwiftUI
99

10+
import Util
11+
1012
public struct PokitHeader<Content: View>: View {
1113
private let title: String?
1214

@@ -28,12 +30,10 @@ public struct PokitHeader<Content: View>: View {
2830
.padding(.horizontal, 20)
2931
.padding(.vertical, 12)
3032
.background(.pokit(.bg(.base)))
31-
.overlay {
32-
if let title {
33-
Text(title)
34-
.pokitFont(.title3)
35-
.foregroundStyle(.pokit(.text(.primary)))
36-
}
33+
.overlay(ifLet: title) { title in
34+
Text(title)
35+
.pokitFont(.title3)
36+
.foregroundStyle(.pokit(.text(.primary)))
3737
}
3838
}
3939
}

β€ŽProjects/DSKit/Sources/Components/PokitList.swiftβ€Ž

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,13 @@ public struct PokitList<Item: PokitSelectItem>: View {
8383
}
8484
.padding(.vertical, 12)
8585
.padding(.horizontal, 20)
86-
.background {
87-
if isSelected {
88-
Color.pokit(.bg(.primary))
89-
.matchedGeometryEffect(id: "SELECT", in: heroEffect)
90-
} else {
91-
isDisabled
92-
? Color.pokit(.bg(.disable))
93-
: Color.pokit(.bg(.base))
94-
}
86+
.background(if: isSelected) {
87+
Color.pokit(.bg(.primary))
88+
.matchedGeometryEffect(id: "SELECT", in: heroEffect)
89+
} else: {
90+
isDisabled
91+
? Color.pokit(.bg(.disable))
92+
: Color.pokit(.bg(.base))
9593
}
9694
}
9795
.animation(.pokitDissolve, value: isSelected)

β€ŽProjects/Feature/FeatureContentCard/Sources/ContentCard/ContentCardFeature.swiftβ€Ž

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,13 @@ public struct ContentCardFeature {
4848
case 메타데이터_쑰회
4949
}
5050

51+
@CasePathable
5152
public enum InnerAction: Equatable {
5253
case 메타데이터_쑰회_μˆ˜ν–‰_반영(String)
5354
case 즐겨찾기_API_반영(Bool)
5455
}
5556

57+
@CasePathable
5658
public enum AsyncAction: Equatable {
5759
case 메타데이터_쑰회_μˆ˜ν–‰
5860
case 즐겨찾기_API
@@ -113,16 +115,16 @@ private extension ContentCardFeature {
113115
case .컨텐츠_ν•­λͺ©_μΌ€λ°₯_λ²„νŠΌ_λˆŒλ €μ„λ•Œ:
114116
return .send(.delegate(.컨텐츠_ν•­λͺ©_μΌ€λ°₯_λ²„νŠΌ_λˆŒλ €μ„λ•Œ(content: state.content)))
115117
case .메타데이터_쑰회:
116-
return .send(.async(.메타데이터_쑰회_μˆ˜ν–‰))
118+
return shared(.async(.메타데이터_쑰회_μˆ˜ν–‰), state: &state)
117119
case .즐겨찾기_λ²„νŠΌ_λˆŒλ €μ„λ•Œ:
118120
guard let isFavorite = state.content.isFavorite else {
119121
return .none
120122
}
121123
UIImpactFeedbackGenerator(style: .light)
122124
.impactOccurred()
123125
return isFavorite
124-
? .send(.async(.즐겨찾기_μ·¨μ†Œ_API))
125-
: .send(.async(.즐겨찾기_API))
126+
? shared(.async(.즐겨찾기_μ·¨μ†Œ_API), state: &state)
127+
: shared(.async(.즐겨찾기_API), state: &state)
126128
}
127129
}
128130

@@ -131,7 +133,7 @@ private extension ContentCardFeature {
131133
switch action {
132134
case let .메타데이터_쑰회_μˆ˜ν–‰_반영(imageURL):
133135
state.content.thumbNail = imageURL
134-
return .send(.async(.썸넀일_μˆ˜μ •_API))
136+
return shared(.async(.썸넀일_μˆ˜μ •_API), state: &state)
135137
case .즐겨찾기_API_반영(let favorite):
136138
state.content.isFavorite = favorite
137139
return .none
@@ -164,10 +166,7 @@ private extension ContentCardFeature {
164166
return .run { [content = state.content] _ in
165167
let request = ThumbnailRequest(thumbnail: content.thumbNail)
166168

167-
try await contentClient.썸넀일_μˆ˜μ •(
168-
contentId: "\(content.id)",
169-
model: request
170-
)
169+
try await contentClient.썸넀일_μˆ˜μ •("\(content.id)", request)
171170
}
172171
}
173172
}
@@ -181,4 +180,19 @@ private extension ContentCardFeature {
181180
func handleDelegateAction(_ action: Action.DelegateAction, state: inout State) -> Effect<Action> {
182181
return .none
183182
}
183+
184+
func shared(_ action: Action, state: inout State) -> Effect<Action> {
185+
switch action {
186+
case .view(let viewAction):
187+
return handleViewAction(viewAction, state: &state)
188+
case .inner(let innerAction):
189+
return handleInnerAction(innerAction, state: &state)
190+
case .async(let asyncAction):
191+
return handleAsyncAction(asyncAction, state: &state)
192+
case .scope(let scopeAction):
193+
return handleScopeAction(scopeAction, state: &state)
194+
case .delegate(let delegateAction):
195+
return handleDelegateAction(delegateAction, state: &state)
196+
}
197+
}
184198
}
Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,87 @@
11
import ComposableArchitecture
22
import XCTest
3+
import Domain
4+
import CoreKit
35

46
@testable import FeatureContentCard
57

6-
final class FeatureContentCardTests: XCTestCase {
7-
func test() {
8+
final class SendTests: XCTestCase {
89

10+
func test_primeTest() async {
11+
let count = 10
12+
var sharedAverage: CFAbsoluteTime = 0.0
13+
for _ in 0..<count {
14+
await test_shared_λ©”μ„œλ“œ_적용(&sharedAverage)
15+
}
16+
17+
var noSharedAverage: CFAbsoluteTime = 0.0
18+
for _ in 0..<count {
19+
await test_shared_λ©”μ„œλ“œ_미적용(&noSharedAverage)
20+
}
21+
22+
print(
23+
"shared_λ©”μ„œλ“œ_적용 \(count)번 ν…ŒμŠ€νŠΈ 평균 μ†Œμš”μ‹œκ°„",
24+
sharedAverage / CFAbsoluteTime(count)
25+
)
26+
print(
27+
"shared_λ©”μ„œλ“œ_미적용 \(count)번 ν…ŒμŠ€νŠΈ 평균 μ†Œμš”μ‹œκ°„",
28+
noSharedAverage / CFAbsoluteTime(count)
29+
)
30+
}
31+
32+
@MainActor
33+
func test_shared_λ©”μ„œλ“œ_적용(_ average: inout CFAbsoluteTime) async {
34+
let store = TestStore(initialState: ContentCardFeature.State(
35+
content: ContentBaseResponse.mock(id: 0).toDomain()
36+
)) {
37+
ContentCardFeature()._printChanges(.actionLabels)
38+
} withDependencies: {
39+
$0[ContentClient.self] = .testValue
40+
let parseOGImageURL: @Sendable (
41+
_ url: URL
42+
) async throws -> String? = { _ in
43+
"https://i.ytimg.com/vi/wtSwdGJzQCQ/maxresdefault.jpg"
44+
}
45+
46+
$0[SwiftSoupClient.self].parseOGImageURL = parseOGImageURL
47+
}
48+
49+
let start = CFAbsoluteTimeGetCurrent()
50+
await store.send(.view(.메타데이터_쑰회))
51+
await store.receive(\.inner.메타데이터_쑰회_μˆ˜ν–‰_반영) {
52+
$0.content.thumbNail = "https://i.ytimg.com/vi/wtSwdGJzQCQ/maxresdefault.jpg"
53+
}
54+
let end = CFAbsoluteTimeGetCurrent()
55+
average += end - start
56+
}
57+
58+
@MainActor
59+
func test_shared_λ©”μ„œλ“œ_미적용(_ average: inout CFAbsoluteTime) async {
60+
let store = TestStore(initialState: LegacyContentCardFeature.State(
61+
content: ContentBaseResponse.mock(id: 0).toDomain()
62+
)) {
63+
LegacyContentCardFeature()._printChanges(.actionLabels)
64+
} withDependencies: {
65+
$0[ContentClient.self] = .testValue
66+
let parseOGImageURL: @Sendable (
67+
_ url: URL
68+
) async throws -> String? = { _ in
69+
"https://i.ytimg.com/vi/wtSwdGJzQCQ/maxresdefault.jpg"
70+
}
71+
72+
$0[SwiftSoupClient.self].parseOGImageURL = parseOGImageURL
73+
}
74+
75+
let start = CFAbsoluteTimeGetCurrent()
76+
await store.send(.view(.메타데이터_쑰회))
77+
await store.receive(\.async.메타데이터_쑰회_μˆ˜ν–‰)
78+
await store.receive(\.inner.메타데이터_쑰회_μˆ˜ν–‰_반영) {
79+
$0.content.thumbNail = "https://i.ytimg.com/vi/wtSwdGJzQCQ/maxresdefault.jpg"
80+
}
81+
await store.receive(\.async.썸넀일_μˆ˜μ •_API)
82+
let end = CFAbsoluteTimeGetCurrent()
83+
average += end - start
984
}
1085
}
86+
87+

0 commit comments

Comments
Β (0)