This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private val ddMMMMyyyyRegex = "([0-9]{1,2})\\s+([A-Za-z]{3,4})\\s+([0-9]{4})".toRegex() | |
private val monthMapping = mapOf( | |
"Jan" to Month.JANUARY, | |
... | |
"Sep" to Month.SEPTEMBER, | |
"Sept" to Month.SEPTEMBER, | |
... | |
"Dec" to Month.DECEMBER | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class PostListViewModelStateObject : ObservableObject { | |
@Published public private(set) var state: PostListState | |
init(viewModel: PostListViewModel) { | |
self.state = viewModel.container.stateFlow.value as! PostListState | |
(viewModel.container.stateFlow.asPublisher() as AnyPublisher<PostListState, Never>) | |
.receive(on: RunLoop.main) | |
.assign(to: &$state) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Combine | |
import shared | |
public extension Kotlinx_coroutines_coreFlow { | |
func asPublisher<T: AnyObject>() -> AnyPublisher<T, Never> { | |
(FlowPublisher(flow: self) as FlowPublisher<T>).eraseToAnyPublisher() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun Flow<*>.subscribe(onEach: (item: Any) -> Unit, onComplete: () -> Unit, onThrow: (error: Throwable) -> Unit): Job = | |
this.onEach { onEach(it as Any) } | |
.catch { onThrow(it) } | |
.onCompletion { onComplete() } | |
.launchIn(CoroutineScope(Job() + Dispatchers.Main)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PostListViewModel( | |
private val postRepository: PostRepository, | |
) : ViewModel(), ContainerHost<PostListState, NavigationEvent> { | |
override val container = viewModelScope.container<PostListState, NavigationEvent>( | |
initialState = PostListState() | |
) { | |
loadOverviews() | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Composable | |
fun Screen() { | |
val lazyListState = rememberLazyListState() | |
Column { | |
AppBar(stringResource(id = R.string.app_name), elevation = lazyListState.elevation) | |
LazyColumn(state = lazyListState) { | |
... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val lazyListState = rememberLazyListState() | |
LazyColumn(state = lazyListState) { | |
... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val LazyListState.elevation: Dp | |
get() = if (firstVisibleItemIndex == 0) { | |
// For the first element, use the minimum of scroll offset and default elevation | |
// i.e. a value between 0 and 4.dp | |
minOf(firstVisibleItemScrollOffset.toFloat().dp, AppBarDefaults.TopAppBarElevation) | |
} else { | |
// If not the first element, always set elevation and show the shadow | |
AppBarDefaults.TopAppBarElevation | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ShadowScrollBehavior(context: Context, attrs: AttributeSet) : AppBarLayout.ScrollingViewBehavior(context, attrs) { | |
@SuppressLint("PrivateResource") | |
private val maxElevation = context.resources.getDimensionPixelSize(R.dimen.design_appbar_elevation).toFloat() | |
override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): | |
Boolean { | |
if (dependency is AppBarLayout) { | |
when (child) { | |
is NestedScrollView -> { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lifecycleScope.launch { | |
// See https://medium.com/androiddevelopers/a-safer-way-to-collect-flows-from-android-uis-23080b1f8bda | |
lifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { | |
launch { viewModel.container.stateFlow.collect(::reduce) | |
launch { viewModel.container.sideEffectFlow.collect(::sideEffect) | |
} | |
} |
NewerOlder