diff --git a/presentation/src/main/java/com/knowing/draven/util/EventFlow.kt b/presentation/src/main/java/com/knowing/draven/util/EventFlow.kt new file mode 100644 index 0000000..c6fb1e3 --- /dev/null +++ b/presentation/src/main/java/com/knowing/draven/util/EventFlow.kt @@ -0,0 +1,53 @@ +package com.knowing.draven.util + +import kotlinx.coroutines.InternalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.collect +import java.util.concurrent.atomic.AtomicBoolean + +interface EventFlow : Flow { + + companion object { + const val DEFAULT_REPLAY: Int = 3 + } +} + +interface MutableEventFlow : EventFlow, FlowCollector + +@Suppress("FunctionName") +fun MutableEventFlow( + replay: Int = EventFlow.DEFAULT_REPLAY +): MutableEventFlow = EventFlowImpl(replay) + +fun MutableEventFlow.asEventFlow(): EventFlow = ReadOnlyEventFlow(this) + +private class ReadOnlyEventFlow(flow: EventFlow) : EventFlow by flow + +private class EventFlowImpl( + replay: Int +) : MutableEventFlow { + + private val flow: MutableSharedFlow> = MutableSharedFlow(replay = replay) + + @InternalCoroutinesApi + override suspend fun collect(collector: FlowCollector) = flow + .collect { slot -> + if(!slot.markConsumed()) { + collector.emit(slot.value) + } + } + + override suspend fun emit(value: T) { + flow.emit(EventFlowSlot(value)) + } + + private class EventFlowSlot(val value: T) { + + private val consumed: AtomicBoolean = AtomicBoolean(false) + + fun markConsumed(): Boolean = consumed.getAndSet(true) + } + +} \ No newline at end of file