Skip to content

Commit

Permalink
Merge branch 'main' into separate-signin
Browse files Browse the repository at this point in the history
  • Loading branch information
bpedryc committed Jan 3, 2024
2 parents b8dbcb0 + 4f4f82b commit fab2ccf
Show file tree
Hide file tree
Showing 12 changed files with 145 additions and 60 deletions.
2 changes: 1 addition & 1 deletion app/src/main/kotlin/co/touchlab/kampkit/android/MainApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class MainApp : Application() {
viewModel {
BreedsViewModel(get(), get { parametersOf("BreedsViewModel") })
}
viewModel {params ->
viewModel { params ->
BreedDetailsViewModel(
params.get(), get(), get { parametersOf("BreedDetailsViewModel") }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.TweenSpec
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.*
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
Expand All @@ -23,30 +20,53 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.touchlab.kampkit.android.R
import co.touchlab.kampkit.domain.breed.Breed
import co.touchlab.kampkit.ui.breedDetails.BreedDetailsViewModel
import co.touchlab.kermit.Logger
import co.touchlab.kampkit.ui.breedDetails.BreedDetailsViewState

@Composable
fun BreedDetailsScreen(
viewModel: BreedDetailsViewModel,
log: Logger
) {
fun BreedDetailsScreen(viewModel: BreedDetailsViewModel) {
val state by viewModel.detailsState.collectAsStateWithLifecycle()
val error = state.error
Box(Modifier.fillMaxSize()) {
state.error?.let { error ->
Text(error, Modifier.align(Alignment.Center), color = Color.Red)
when {
state.isLoading -> Loading()
error != null -> Error(error)
else -> DetailsContents(
state = state,
onFavoriteClick = viewModel::onFavoriteClick
)
}
if (state.error == null) {
Row(Modifier.align(Alignment.Center)) {
Text(state.breed.name)
Spacer(Modifier.width(4.dp))
FavoriteIcon(
breed = state.breed,
onClick = viewModel::onFavoriteClick
)
}
}
}

@Composable
private fun BoxScope.DetailsContents(
state: BreedDetailsViewState,
onFavoriteClick: () -> Unit
) {
Row(Modifier.align(Alignment.Center)) {
Text(state.breed?.name ?: "")
Spacer(Modifier.width(4.dp))
state.breed?.let { breed ->
FavoriteIcon(
breed = breed,
onClick = onFavoriteClick
)
}
}
}

@Composable
private fun BoxScope.Error(error: String) {
Text(
text = error,
color = Color.Red,
modifier = Modifier.align(Alignment.Center)
)
}

@Composable
fun BoxScope.Loading() {
CircularProgressIndicator(Modifier.align(Alignment.Center))
}

@Composable
Expand Down
19 changes: 10 additions & 9 deletions app/src/main/kotlin/co/touchlab/kampkit/android/ui/BreedsScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
Expand Down Expand Up @@ -99,7 +100,7 @@ fun BreedsScreenContent(
}

@Composable
fun Empty() {
private fun Empty() {
Column(
modifier = Modifier
.fillMaxSize()
Expand All @@ -112,20 +113,20 @@ fun Empty() {
}

@Composable
fun Error(error: String) {
private fun Error(error: String) {
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = error)
Text(text = error, color = Color.Red)
}
}

@Composable
fun Success(
private fun Success(
successData: List<Breed>,
onBreedClick: (breedId: Long) -> Unit
) {
Expand Down Expand Up @@ -158,15 +159,15 @@ fun DogRow(breed: Breed, onClick: (Breed) -> Unit) {

@Composable
fun FavoriteIcon(breed: Breed) {
if (!breed.favorite) {
if (breed.favorite) {
Image(
painter = painterResource(id = R.drawable.ic_favorite_border_24px),
contentDescription = stringResource(R.string.favorite_breed, breed.name)
painter = painterResource(id = R.drawable.ic_favorite_24px),
contentDescription = stringResource(R.string.unfavorite_breed, breed.name)
)
} else {
Image(
painter = painterResource(id = R.drawable.ic_favorite_24px),
contentDescription = stringResource(R.string.unfavorite_breed, breed.name)
painter = painterResource(id = R.drawable.ic_favorite_border_24px),
contentDescription = stringResource(R.string.favorite_breed, breed.name)
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import org.koin.androidx.compose.koinViewModel
import org.koin.core.parameter.parametersOf

private const val BREEDS = "breeds"

private const val BREED_DETAILS = "breedDetails"
private const val BREED_ID_ARG = "breedId"

Expand All @@ -39,7 +38,6 @@ fun MainNavCoordinator() {
val breedId = it.arguments?.getLong(BREED_ID_ARG)
BreedDetailsScreen(
viewModel = koinViewModel { parametersOf(breedId) },
log = get { parametersOf("BreedDetailsScreen") }
)
}
}
Expand Down
25 changes: 25 additions & 0 deletions ios/KaMPKitiOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,30 @@
path = Breeds;
sourceTree = "<group>";
};
579753BDA8BAA9A5A399C611 /* bartlomiejpedryc.xcuserdatad */ = {
isa = PBXGroup;
children = (
57975F3C51683ABE14191024 /* xcschemes */,
);
path = bartlomiejpedryc.xcuserdatad;
sourceTree = "<group>";
};
5797556592C6669DF1E7702C /* xcuserdata */ = {
isa = PBXGroup;
children = (
579753BDA8BAA9A5A399C611 /* bartlomiejpedryc.xcuserdatad */,
);
name = xcuserdata;
path = KaMPKitiOS.xcodeproj/xcuserdata;
sourceTree = "<group>";
};
57975F3C51683ABE14191024 /* xcschemes */ = {
isa = PBXGroup;
children = (
);
path = xcschemes;
sourceTree = "<group>";
};
6278498AD96A4D949D39BF44 /* Frameworks */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -158,6 +182,7 @@
F1465EFE23AA94BF0055F7C3 /* Products */,
DF9BBECBCD175B90105DA8D9 /* Pods */,
6278498AD96A4D949D39BF44 /* Frameworks */,
5797556592C6669DF1E7702C /* xcuserdata */,
);
sourceTree = "<group>";
};
Expand Down
23 changes: 23 additions & 0 deletions ios/KaMPKitiOS.xcworkspace/xcshareddata/swiftpm/Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"pins" : [
{
"identity" : "kmp-nativecoroutines",
"kind" : "remoteSourceControl",
"location" : "https://github.com/rickclephas/KMP-NativeCoroutines.git",
"state" : {
"revision" : "a1269d3052fcc32d3861eaea32b715d58a46fe32",
"version" : "1.0.0-ALPHA-9"
}
},
{
"identity" : "rxswift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ReactiveX/RxSwift.git",
"state" : {
"revision" : "9dcaa4b333db437b0fbfaf453fad29069044a8b4",
"version" : "6.6.0"
}
}
],
"version" : 2
}
25 changes: 18 additions & 7 deletions ios/KaMPKitiOS/BreedDetails/BreedDetailsScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,27 @@ struct BreedDetailsScreen: View {
var viewModel: BreedDetailsViewModel

var body: some View {
BreedDetailsContent(
breedName: viewModel.detailsState.breed.name,
isBreedFavorite: viewModel.detailsState.breed.favorite,
onFavoriteClick: { viewModel.onFavoriteClick() }
)
let state = viewModel.state
ZStack {
if let error = state.error {
Text(error)
}
if state.error == nil && state.isLoading {
ProgressView()
}
if let breed = state.breed, state.error == nil, !state.isLoading {
BreedDetailsContent(
breedName: breed.name,
isBreedFavorite: breed.favorite,
onFavoriteClick: { viewModel.onFavoriteClick() }
)
}
}
.onAppear(perform: {
viewModel.activate()
viewModel.subscribeState()
})
.onDisappear(perform: {
viewModel.deactivate()
viewModel.unsubscribeState()
})
}
}
Expand Down
26 changes: 12 additions & 14 deletions ios/KaMPKitiOS/BreedDetails/BreedDetailsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,33 @@ import shared
import KMPNativeCoroutinesCombine

class BreedDetailsViewModel: ObservableObject {
private var viewModelDelegate: BreedDetailsViewModelDelegate

@Published var state: BreedDetailsViewState = BreedDetailsViewState.companion.default()

private var viewModelDelegate: BreedDetailsViewModelDelegate
private var cancellables = [AnyCancellable]()
init(breedId: Int64) {
self.viewModelDelegate = KotlinDependencies.shared.getBreedDetailsViewModel(breedId: breedId)
}

@Published
var detailsState: BreedDetailsViewState = BreedDetailsViewState.companion.default()

private var cancellables = [AnyCancellable]()

func onFavoriteClick() {
viewModelDelegate.onFavoriteClick()
deinit {
viewModelDelegate.clear()
}
func activate() {

func subscribeState() {
createPublisher(for: viewModelDelegate.detailsStateFlow)
.sink { _ in } receiveValue: { [weak self] (detailsState: BreedDetailsViewState) in
self?.detailsState = detailsState
self?.state = detailsState
}
.store(in: &cancellables)
}

func deactivate() {
func unsubscribeState() {
cancellables.forEach { $0.cancel() }
cancellables.removeAll()
}

deinit {
viewModelDelegate.clear()
func onFavoriteClick() {
viewModelDelegate.onFavoriteClick()
}
}
4 changes: 2 additions & 2 deletions ios/KaMPKitiOS/Breeds/BreedsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class BreedsViewModel: ObservableObject {
private var viewModelDelegate: BreedsViewModelDelegate = KotlinDependencies.shared.getBreedsViewModel()
private var cancellables = [AnyCancellable]()
init(navCoordinator: BreedsNavCoordinator) {
self.navCoordinator = navCoordinator
}
self.navCoordinator = navCoordinator
}

deinit {
viewModelDelegate.clear()
Expand Down
9 changes: 9 additions & 0 deletions ios/Pods/Pods.xcodeproj/project.pbxproj

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package co.touchlab.kampkit.domain.breed

data class Breed(
val id: Long = 0,
val name: String = "",
val favorite: Boolean = false
val id: Long,
val name: String,
val favorite: Boolean
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package co.touchlab.kampkit.ui.breedDetails
import co.touchlab.kampkit.domain.breed.Breed

data class BreedDetailsViewState(
val breed: Breed = Breed(),
val breed: Breed? = null,
val error: String? = null,
val isLoading: Boolean = false
) {
Expand Down

0 comments on commit fab2ccf

Please sign in to comment.