Skip to content

Commit

Permalink
Merge branch 'main' into yamada-ika/run-test-on-mac
Browse files Browse the repository at this point in the history
  • Loading branch information
takahirom authored Sep 7, 2024
2 parents e0dc2f6 + 197c84a commit e259380
Show file tree
Hide file tree
Showing 41 changed files with 594 additions and 173 deletions.
4 changes: 2 additions & 2 deletions app-android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ android {
buildConfig = true
}
defaultConfig {
versionCode = 4
versionName = "1.1.0"
versionCode = 6
versionName = "1.2.0"
}
signingConfigs {
create("dev") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import androidx.activity.enableEdgeToEdge
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
Expand All @@ -22,6 +21,7 @@ import androidx.window.layout.WindowInfoTracker
import dagger.hilt.android.AndroidEntryPoint
import io.github.droidkaigi.confsched.data.di.RepositoryProvider
import io.github.droidkaigi.confsched.designsystem.theme.dotGothic16FontFamily
import io.github.droidkaigi.confsched.droidkaigiui.KaigiAppCompositionLocalProvider
import io.github.droidkaigi.confsched.droidkaigiui.compositionlocal.LocalClock
import io.github.droidkaigi.confsched.model.FontFamily.DotGothic16Regular
import io.github.droidkaigi.confsched.model.FontFamily.SystemDefault
Expand Down Expand Up @@ -90,8 +90,10 @@ class MainActivity : ComponentActivity() {
}
}

CompositionLocalProvider(
LocalClock provides clockProvider.clock(),
KaigiAppCompositionLocalProvider(
locals = arrayOf(
LocalClock provides clockProvider.clock(),
),
) {
repositoryProvider.Provide {
KaigiApp(
Expand Down
4 changes: 3 additions & 1 deletion app-ios/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,9 @@ let package = Package(
dependencies: [
.tca,
.kmpClient,
.theme
.theme,
.model,
.commonComponents,
]
),
.testTarget(
Expand Down
49 changes: 49 additions & 0 deletions app-ios/Sources/ContributorFeature/ContributorsCountItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import SwiftUI
import Theme

struct ContributorsCountItem: View {
let totalContributor: Int
let duration: Double = 1.0
@State private var tracker = 0

var body: some View {
VStack(alignment: .leading) {

Text(String(localized: "Total", bundle: .module))
.textStyle(.titleMedium)
.foregroundStyle(AssetColors.Surface.onSurfaceVariant.swiftUIColor)
.frame(maxWidth: .infinity, alignment: .leading)

HStack {
Text("\(tracker)")
.textStyle(.headlineLarge)
.foregroundStyle(AssetColors.Surface.onSurface.swiftUIColor)
.onAppear() {
animate()
}

Text(String(localized: "Person", bundle: .module))
.textStyle(.headlineSmall)
.foregroundStyle(AssetColors.Surface.onSurface.swiftUIColor)
}

Spacer()
.frame(height: 16)
Divider()
}
}

func animate() {
let interval = duration / Double(totalContributor)
Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { time in
tracker += 1
if tracker == totalContributor {
time.invalidate()
}
}
}
}

#Preview {
ContributorsCountItem(totalContributor: 112)
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ struct KmpPresenterContributorView: View {
if let existsState = state as? Exists {
ScrollView {
LazyVStack(spacing: 0) {

ContributorsCountItem(totalContributor: existsState.contributors.count)
.frame(maxWidth: .infinity)
.padding(.horizontal, 16)
.padding(.vertical, 10)

ForEach(existsState.contributors, id: \.id) { value in
let contributor = Model.Contributor(
id: Int(value.id),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,39 @@
}
}
}
},
"Person" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "persons"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "人"
}
}
}
},
"Total" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Total"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "合計"
}
}
}
}
},
"version" : "1.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ struct SwiftUIContributorView: View {
if let contributors = store.contributors {
ScrollView {
LazyVStack(spacing: 0) {

ContributorsCountItem(totalContributor: contributors.count)
.frame(maxWidth: .infinity)
.padding(.horizontal, 16)
.padding(.vertical, 10)

ForEach(contributors, id: \.id) { contributor in
ContributorListItemView(contributor: contributor) { url in
store.send(.view(.contributorButtonTapped(url)))
Expand Down
23 changes: 20 additions & 3 deletions app-ios/Sources/SponsorFeature/SponsorReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,29 @@ public struct SponsorReducer : Sendable {
var platinums = [Sponsor]()
var golds = [Sponsor]()
var supporters = [Sponsor]()
var url: IdentifiableURL?

public init() { }
}

public enum Action : Sendable {
case onAppear
public enum Action : Sendable, BindableAction {
case binding(BindingAction<State>)
case response(Result<[Sponsor], any Error>)
case view(View)

public enum View: Sendable {
case onAppear
case sponsorTapped(URL)
}
}

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

switch action {
case .onAppear:
case .view(.onAppear):
return .run { send in
do {
for try await sponsors in try sponsorsData.streamSponsors() {
Expand All @@ -39,6 +47,11 @@ public struct SponsorReducer : Sendable {
}
}
.cancellable(id: CancelID.connection)

case let .view(.sponsorTapped(url)):
state.url = IdentifiableURL(url)
return .none

case .response(.success(let sponsors)):
var platinums = [Sponsor]()
var golds = [Sponsor]()
Expand All @@ -59,9 +72,13 @@ public struct SponsorReducer : Sendable {
state.golds = golds
state.supporters = supporters
return .none

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

case .binding:
return .none
}
}
}
Expand Down
21 changes: 13 additions & 8 deletions app-ios/Sources/SponsorFeature/SponsorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import ComposableArchitecture
import SwiftUI
import Theme
import Model
import CommonComponents

public struct SponsorView: View {
private let store: StoreOf<SponsorReducer>
@State private var selectedSponsorData: Sponsor?
@Bindable private var store: StoreOf<SponsorReducer>

public init(store: StoreOf<SponsorReducer>) {
self.store = store
Expand Down Expand Up @@ -39,10 +39,14 @@ public struct SponsorView: View {
}
.background(AssetColors.Surface.surface.swiftUIColor)
.onAppear {
store.send(.onAppear)
store.send(.view(.onAppear))
}
.navigationBarTitleDisplayMode(.large)
.navigationTitle(String(localized: "Sponsor", bundle: .module))
.sheet(item: $store.url, content: { url in
SafariView(url: url.id)
.ignoresSafeArea()
})
}

@ViewBuilder
Expand All @@ -53,15 +57,16 @@ public struct SponsorView: View {
}
LazyVGrid(columns: gridItems, spacing: 12) {
ForEach(items) { item in
Button {
selectedSponsorData = item
} label: {
ZStack {
Color.white.clipShape(RoundedRectangle(cornerRadius: 12))
ZStack {
Color.white.clipShape(RoundedRectangle(cornerRadius: 12))
Button {
store.send(.view(.sponsorTapped(item.link)))
} label: {
AsyncImage(url: item.logo) {
$0.image?
.resizable()
.scaledToFit()
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
.frame(height: imageHeight)
.padding(.vertical, 6)
Expand Down
13 changes: 12 additions & 1 deletion app-ios/Tests/SponsorFeatureTests/SponsorFeatureTests.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import XCTest
import ComposableArchitecture
import Model
@testable import SponsorFeature

final class SponsorFeatureTests: XCTestCase {
Expand All @@ -20,7 +21,7 @@ final class SponsorFeatureTests: XCTestCase {
}
}
}
await store.send(.onAppear)
await store.send(.view(.onAppear))
await store.receive(\.response.success) {
$0.platinums = [
.init(id: "Hoge", logo: .init(string: "https://avatars.githubusercontent.com/u/10727543?s=200&v=4")!, link: .init(string: "https://2024.droidkaigi.jp/")!, plan: .platinum)
Expand All @@ -34,4 +35,14 @@ final class SponsorFeatureTests: XCTestCase {
}
}

@MainActor
func testSponsorTapped() async throws {
let url = URL(string: "https://github.com/DroidKaigi/conference-app-2024")!
let store = TestStore(initialState: SponsorReducer.State()) {
SponsorReducer()
}
await store.send(.view(.sponsorTapped(url))) {
$0.url = IdentifiableURL(url)
}
}
}
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ allprojects {
resolutionStrategy {
// When the fixed version is released, remove this block
// https://issuetracker.google.com/issues/341880461
force("androidx.compose.foundation:foundation:1.6.8")
force("androidx.compose.foundation:foundation:1.8.0-alpha01")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ public fun SessionsAllResponse.toTimetable(): Timetable {
} else {
apiSession.i18nDesc.toMultiLangText()
},
message = apiSession.message?.toMultiLangText(),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.github.droidkaigi.confsched.droidkaigiui

import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.ProvidedValue

@Composable
inline fun KaigiAppCompositionLocalProvider(
vararg locals: ProvidedValue<*>,
crossinline content: @Composable () -> Unit,
) {
CompositionLocalProvider(*locals) {
if (isTest()) {
ProvideAndroidContextToComposeResource()
}
content()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.github.droidkaigi.confsched.droidkaigiui

import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalInspectionMode
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.PreviewContextConfigurationEffect

@OptIn(ExperimentalResourceApi::class)
@Composable
fun ProvideAndroidContextToComposeResource() {
CompositionLocalProvider(LocalInspectionMode provides true) {
PreviewContextConfigurationEffect()
}
}
Loading

0 comments on commit e259380

Please sign in to comment.