Skip to content

Commit

Permalink
Added logic to add bookmark
Browse files Browse the repository at this point in the history
  • Loading branch information
shin-usu committed Jul 11, 2024
1 parent 62fe3e6 commit a422ae7
Show file tree
Hide file tree
Showing 16 changed files with 168 additions and 35 deletions.
4 changes: 3 additions & 1 deletion app-ios/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ let package = Package(
dependencies: [
.tca,
.theme,
.commonComponents
.commonComponents,
.kmpClient,
.kmpModule,
]
),
.testTarget(
Expand Down
4 changes: 4 additions & 0 deletions app-ios/Sources/App/RootReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ public struct RootReducer {
case .about(.view(.acknowledgementsTapped)):
state.paths.about.append(.acknowledgements)
return .none

case .timetable(.view(.timetableItemTapped)):
state.paths.timetable.append(.timetableDetail(TimetableDetailReducer.State()))
return .none

default:
return .none
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 @@ -2,7 +2,12 @@ import Dependencies

extension TimetableClient: TestDependencyKey {
public static let previewValue: Self = Self()
public static let testValue: Self = Self()

public static let testValue: Self = Self(
streamTimetable: unimplemented("TimetableClient.streamTimetable"),
streamTimetableItemWithFavorite: unimplemented("TimetableClient.streamTimetableItemWithFavorite"),
toggleBookmark: unimplemented("TimetableClient.toggleBookmark")
)
}

extension StaffClient: TestDependencyKey {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "ic_favorite.svg",
"filename" : "favorite.svg",
"idiom" : "universal"
}
],
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "ic_favorite_outline.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions app-ios/Sources/TimetableDetailFeature/SampleData.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import shared

enum SampleData {
static let title = "DroidKaigiアプリで見るアーキテクチャの変遷"
static let dateValue = "2023.09.14 / 11:20 ~ 12:00 (40分)"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,80 @@
import ComposableArchitecture
import CommonComponents
import KMPClient
import shared

@Reducer
public struct TimetableDetailReducer {
public struct TimetableDetailReducer: Sendable {
@Dependency(\.timetableClient) private var timetableClient

public init() {}

@ObservableState
public struct State: Equatable {
public init(isBookmarked: Bool = false, toast: ToastState? = nil) {
self.isBookmarked = isBookmarked
self.toast = toast
}

var isBookmarked = false
var toast: ToastState?
}

public enum Action: BindableAction {
case binding(BindingAction<State>)
case view(View)
case bookmarkResponse(Result<Void, any Error>)

public enum View {
case favoriteButtonTapped
case bookmarkButtonTapped
case shareButtonTapped
case calendarButtonTapped
case slideButtonTapped
case videoButtonTapped
}
}

public var body: some ReducerOf<Self> {
BindingReducer()
Reduce { state, action in
enum CancelID { case request }

switch action {
case .view(.favoriteButtonTapped):
state.toast = .init(text: String(localized: "TimetableDetailAddBookmark", bundle: .module))
case .view(.bookmarkButtonTapped):
return .run { @Sendable send in
do {
await send(.bookmarkResponse(.success(
try await timetableClient.toggleBookmark(id: TimetableItemId(value: ""))
)))
} catch {
await send(.bookmarkResponse(.failure(error)))
}
}
.cancellable(id: CancelID.request)

case .view(.calendarButtonTapped):
return .none

case .view(.shareButtonTapped):
return .none

case .view(.slideButtonTapped):
return .none

case .view(.videoButtonTapped):
return .none

case .bookmarkResponse(.success):
if !state.isBookmarked {
state.toast = .init(text: String(localized: "TimetableDetailAddBookmark", bundle: .module))
}
state.isBookmarked.toggle()
return .none

case let .bookmarkResponse(.failure(error)):
print(error)
return .none

case .binding:
return .none
}
Expand Down
34 changes: 20 additions & 14 deletions app-ios/Sources/TimetableDetailFeature/TimetableDetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,21 @@ public struct TimetableDetailView: View {
.frame(maxWidth: .infinity)
.ignoresSafeArea(edges: [.top])
}
.toolbarBackground(AssetColors.Surface.surface.swiftUIColor, for: .navigationBar)
}

@ViewBuilder var footer: some View {
@MainActor var footer: some View {
HStack(spacing: 8) {
Button {
// do something
store.send(.view(.shareButtonTapped))
} label: {
Group {
Image(.icShare)
}
.frame(width: 40, height: 40)
}
Button {
// do something
store.send(.view(.calendarButtonTapped))
} label: {
Group {
Image(.icAddCalendar)
Expand All @@ -53,13 +54,18 @@ public struct TimetableDetailView: View {
}
Spacer()
Button {
store.send(.view(.favoriteButtonTapped))
store.send(.view(.bookmarkButtonTapped))
} label: {
Group {
Image(.icFavorite)
if store.isBookmarked {
Image(.icFavoriteFill)
} else {
Image(.icFavoriteOutline)
}

}
.frame(width: 56, height: 56)
.background(AssetColors.Surface.surfaceContainer.swiftUIColor)
.background(AssetColors.Secondary.secondaryContainer.swiftUIColor)
.clipShape(RoundedRectangle(cornerRadius: 16))
}
}
Expand All @@ -69,7 +75,7 @@ public struct TimetableDetailView: View {
.background(AssetColors.Surface.surfaceContainer.swiftUIColor)
}

@ViewBuilder var headLine: some View {
@MainActor var headLine: some View {
VStack(alignment: .leading, spacing: 0) {
HStack(spacing: 4) {
RoomTag(.arcticFox)
Expand Down Expand Up @@ -99,11 +105,11 @@ public struct TimetableDetailView: View {
}
.padding(.bottom, 20)
}
.padding(.horizontal, 16)
.padding([.top, .horizontal], 16)
.background(AssetColors.Custom.arcticFoxContainer.swiftUIColor)
}

@ViewBuilder var detail: some View {
@MainActor var detail: some View {
VStack(alignment: .leading, spacing: 20) {
VStack(spacing: 16) {
InformationRow(
Expand Down Expand Up @@ -143,7 +149,7 @@ public struct TimetableDetailView: View {
}
}

@ViewBuilder var applicants: some View {
@MainActor var applicants: some View {
VStack(alignment: .leading, spacing: 16) {
Text(String(localized: "TimeTableDetailApplicants", bundle: .module))
.textStyle(.titleLarge)
Expand All @@ -155,15 +161,15 @@ public struct TimetableDetailView: View {
}
}

@ViewBuilder var archive: some View {
@MainActor var archive: some View {
VStack(alignment: .leading, spacing: 16) {
Text(String(localized: "TimeTableDetailArchive", bundle: .module))
.textStyle(.titleLarge)
.foregroundStyle(AssetColors.Custom.arcticFox.swiftUIColor)

HStack {
Button {
// do something
store.send(.view(.slideButtonTapped))
} label: {
VStack {
Label(
Expand All @@ -181,7 +187,7 @@ public struct TimetableDetailView: View {
.clipShape(Capsule())
}
Button {
// do something
store.send(.view(.videoButtonTapped))
} label: {
VStack {
Label(
Expand Down Expand Up @@ -209,7 +215,7 @@ public struct TimetableDetailView: View {

#Preview {
TimetableDetailView(
store: .init(initialState: .init(toast: nil)) {
store: .init(initialState: .init()) {
TimetableDetailReducer()
}
)
Expand Down
8 changes: 6 additions & 2 deletions app-ios/Sources/TimetableFeature/TimetableListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public struct TimetableView: View {
HStack {
ForEach(DayTab.allCases) { tabItem in
Button(action: {
store.send(.selectDay(tabItem))
store.send(.view(.selectDay(tabItem)))
}, label: {
//TODO: Only selected button should be green and underlined
Text(tabItem.rawValue).foregroundStyle(Color(.greenSelectColorset))
Expand Down Expand Up @@ -41,7 +41,11 @@ struct TimetableListView: View {
ScrollView{
LazyVStack {
ForEach(store.timetableItems, id: \.self) { item in
TimeGroupMiniList(contents: item)
Button {
store.send(.view(.timetableItemTapped))
} label: {
TimeGroupMiniList(contents: item)
}
}
}.scrollContentBackground(.hidden)

Expand Down
11 changes: 9 additions & 2 deletions app-ios/Sources/TimetableFeature/TimetableReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@ public struct TimetableReducer {
}

public enum Action {
case view(View)
case onAppear
case selectDay(DayTab)

public enum View {
case selectDay(DayTab)
case timetableItemTapped
}
}

public var body: some Reducer<State, Action> {
Expand All @@ -27,7 +32,9 @@ public struct TimetableReducer {
case .onAppear:
state.timetableItems = sampleData.day1Results
return .none
case .selectDay(let dayTab):
case .view(.timetableItemTapped):
return .none
case .view(.selectDay(let dayTab)):
//TODO: Replace with real data

switch dayTab {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,41 @@ import ComposableArchitecture
@testable import TimetableDetailFeature

final class TimetableDetail_iosTests: XCTestCase {
@MainActor func testExample() async throws {
let store = TestStore(initialState: TimetableDetailReducer.State()) {
@MainActor func testTappedBookmarkButton() async throws {
let isBookmarked = false
let store = TestStore(initialState: TimetableDetailReducer.State(isBookmarked: isBookmarked)) {
TimetableDetailReducer()
} withDependencies: {
$0.timetableClient.toggleBookmark = { @Sendable _ in }
}

await store.send(.favoriteButtonTapped) {
// add bookmark
await store.send(.view(.bookmarkButtonTapped))
await store.receive(\.bookmarkResponse) {
$0.isBookmarked = !isBookmarked
$0.toast = .init(text: String(localized: "TimetableDetailAddBookmark", bundle: .module))
}

// remove bookmark
await store.send(.view(.bookmarkButtonTapped))
await store.receive(\.bookmarkResponse) {
$0.isBookmarked = isBookmarked
}

}

@MainActor func testTappedBookmarkButtonFailed() async throws {
let store = TestStore(initialState: TimetableDetailReducer.State(isBookmarked: false)) {
TimetableDetailReducer()
} withDependencies: {
$0.timetableClient.toggleBookmark = { @Sendable _ in throw TimetableDetailTestError.fail }
}

await store.send(.view(.bookmarkButtonTapped))
await store.receive(\.bookmarkResponse)
}
}

enum TimetableDetailTestError: Error {
case fail
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.github.droidkaigi.confsched.compose

import android.annotation.SuppressLint
import androidx.compose.runtime.Composable
import androidx.compose.runtime.InternalComposeApi
import androidx.compose.runtime.LaunchedEffect
Expand Down Expand Up @@ -78,7 +77,7 @@ fun <T : R, R> Flow<T>.safeCollectAsRetainedState(
}
}

@SuppressLint("StateFlowValueCalledInComposition")
@Suppress("StateFlowValueCalledInComposition")
@Composable
fun <T : R, R> StateFlow<T>.safeCollectAsRetainedState(
context: CoroutineContext = EmptyCoroutineContext,
Expand Down
Loading

0 comments on commit a422ae7

Please sign in to comment.