Skip to content

Commit

Permalink
Merge pull request #83 from DroidKaigi/MrSmart00/feature/staff
Browse files Browse the repository at this point in the history
Show Staff list from KMP datas
  • Loading branch information
MrSmart00 authored Jun 29, 2024
2 parents d73a4d0 + 3218a8e commit 8eba181
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 11 deletions.
7 changes: 6 additions & 1 deletion app-ios/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,11 @@ let package = Package(
),
.target(
name: "StaffFeature",
dependencies: [ .tca ]
dependencies: [
.tca,
.kmpClient,
.theme
]
),
.testTarget(
name: "StaffFeatureTests",
Expand Down Expand Up @@ -212,6 +216,7 @@ extension Target.Dependency {
static let sponsorFeature: Target.Dependency = "SponsorFeature"
static let contributorFeature: Target.Dependency = "ContributorFeature"
static let kmpModule: Target.Dependency = "KmpModule"
static let kmpClient: Target.Dependency = "KMPClient"
static let theme: Target.Dependency = "Theme"

static let firebaseAuth: Target.Dependency = .product(name: "FirebaseAuth", package: "firebase-ios-sdk")
Expand Down
7 changes: 6 additions & 1 deletion app-ios/Sources/KMPClient/TestKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ extension TimetableClient: TestDependencyKey {

extension StaffClient: TestDependencyKey {
public static let previewValue: Self = Self()
public static let testValue: Self = Self()
public static let testValue: Self = .init {
AsyncThrowingStream {
$0.yield([.init(id: 0, username: "testValue", profileUrl: "https://2024.droidkaigi.jp/", iconUrl: "https://avatars.githubusercontent.com/u/10727543?s=200&v=4"),])
$0.finish()
}
}
}

extension SponsorsClient: TestDependencyKey {
Expand Down
16 changes: 16 additions & 0 deletions app-ios/Sources/StaffFeature/Localizable.xcstrings
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"sourceLanguage" : "en",
"strings" : {
"Staff" : {
"localizations" : {
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "スタッフ"
}
}
}
}
},
"version" : "1.0"
}
31 changes: 31 additions & 0 deletions app-ios/Sources/StaffFeature/StaffLabel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import SwiftUI
import Theme

struct StaffLabel: View {
let name: String
let icon: URL

var body: some View {
HStack(alignment: .center, spacing: 12) {
AsyncImage(url: icon) {
$0.image?.resizable()
}
.frame(width: 52, height: 52)
.clipShape(Circle())
.overlay(
Circle()
.stroke(AssetColors.Outline.outline.swiftUIColor, lineWidth: 1)
)

Text(name)
.textStyle(.bodyLarge)
.foregroundStyle(AssetColors.Surface.onSurface.swiftUIColor)
.lineLimit(2)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}

#Preview {
StaffLabel(name: "hoge", icon: .init(string: "")!)
}
37 changes: 35 additions & 2 deletions app-ios/Sources/StaffFeature/StaffReducer.swift
Original file line number Diff line number Diff line change
@@ -1,23 +1,56 @@
import ComposableArchitecture
import Foundation
import KMPClient
import shared

struct StaffData: Equatable, Identifiable {
let id: Int
let name: String
let icon: URL
let github: URL
}

@Reducer
public struct StaffReducer {
@Dependency(\.staffClient) var staffsData

public init() { }

@ObservableState
public struct State: Equatable {
var text: String
var list: [StaffData] = []
public init() { }
}

public enum Action {
case onAppear
case response(Result<[Staff], any Error>)
}

public var body: some ReducerOf<Self> {
Reduce { state, action in
enum CancelID { case connection }

switch action {
case .onAppear:
state.text = "Staff Feature"
return .run { send in
for try await staffs in try staffsData.streamStaffs() {
await send(.response(.success(staffs)))
}
}
.cancellable(id: CancelID.connection)
case .response(.success(let staffs)):
state.list = staffs.map {
StaffData(
id: Int($0.id),
name: $0.username,
icon: URL(string: $0.iconUrl)!,
github: URL(string: $0.profileUrl)!
)
}
return .none
case .response(.failure(let error)):
print(error)
return .none
}
}
Expand Down
24 changes: 20 additions & 4 deletions app-ios/Sources/StaffFeature/StaffView.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ComposableArchitecture
import SwiftUI
import Theme

public struct StaffView: View {
private let store: StoreOf<StaffReducer>
Expand All @@ -9,13 +10,28 @@ public struct StaffView: View {
}

public var body: some View {
Text(store.text)
.onAppear {
store.send(.onAppear)
ScrollView {
LazyVStack {
ForEach(store.list, id: \.id) { staff in
Button {

} label: {
StaffLabel(name: staff.name, icon: staff.icon)
}
.padding(.vertical, 12)
}
}
.padding(16)
}
.background(AssetColors.Surface.surface.swiftUIColor)
.onAppear {
store.send(.onAppear)
}
.navigationBarTitleDisplayMode(.large)
.navigationTitle(String(localized: "Staff", bundle: .module))
}
}

#Preview {
StaffView(store: .init(initialState: .init(text: "Hoge"), reducer: { StaffReducer() }))
StaffView(store: .init(initialState: .init(), reducer: { StaffReducer() }))
}
7 changes: 4 additions & 3 deletions app-ios/Tests/StaffFeatureTests/StaffFeatureTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ final class StaffFeatureTests: XCTestCase {

@MainActor
func testExample() async throws {
let store = TestStore(initialState: StaffReducer.State(text: "HOGE")) {
let store = TestStore(initialState: StaffReducer.State()) {
StaffReducer()
}
await store.send(.onAppear) {
$0.text = "Staff Feature"
await store.send(.onAppear)
await store.receive(\.response.success) {
$0.list = [.init(id: 0, name: "testValue", icon: .init(string: "https://avatars.githubusercontent.com/u/10727543?s=200&v=4")!, github: .init(string: "https://2024.droidkaigi.jp/")!)]
}
}

Expand Down

0 comments on commit 8eba181

Please sign in to comment.