diff options
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/activities')
4 files changed, 80 insertions, 48 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt index 84352cb4..9d16c63a 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt @@ -130,7 +130,6 @@ import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.components.ActivityComponent import dagger.hilt.android.qualifiers.ActivityContext import dagger.hilt.android.scopes.ActivityScoped -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch import javax.inject.Inject import kotlin.math.abs @@ -140,7 +139,6 @@ import kotlin.math.abs * * Most of the logic that is unrelated to handling fragments */ -@UseExperimental(ExperimentalCoroutinesApi::class) @AndroidEntryPoint abstract class BaseMainActivity : BaseActivity(), @@ -498,7 +496,10 @@ abstract class BaseMainActivity : ) positiveButton(R.string.kau_yes) { this@BaseMainActivity.launch { - fbCookie.logout(this@BaseMainActivity, deleteCookie = true) + fbCookie.logout( + this@BaseMainActivity, + deleteCookie = true + ) } } negativeButton(R.string.kau_no) @@ -637,7 +638,7 @@ abstract class BaseMainActivity : private fun refreshAll() { L.d { "Refresh all" } - fragmentChannel.offer(REQUEST_REFRESH) + fragmentEmit(REQUEST_REFRESH) } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -737,19 +738,19 @@ abstract class BaseMainActivity : * These results can be stacked */ if (hasRequest(REQUEST_REFRESH)) { - fragmentChannel.offer(REQUEST_REFRESH) + fragmentEmit(REQUEST_REFRESH) } if (hasRequest(REQUEST_NAV)) { frostNavigationBar(prefs, themeProvider) } if (hasRequest(REQUEST_TEXT_ZOOM)) { - fragmentChannel.offer(REQUEST_TEXT_ZOOM) + fragmentEmit(REQUEST_TEXT_ZOOM) } if (hasRequest(REQUEST_SEARCH)) { invalidateOptionsMenu() } if (hasRequest(REQUEST_FAB)) { - fragmentChannel.offer(lastPosition) + fragmentEmit(lastPosition) } if (hasRequest(REQUEST_NOTIFICATION)) { scheduleNotificationsFromPrefs(prefs) @@ -792,7 +793,6 @@ abstract class BaseMainActivity : override fun onDestroy() { controlWebview?.destroy() super.onDestroy() - fragmentChannel.close() } override fun collapseAppBar() { @@ -864,10 +864,9 @@ abstract class BaseMainActivity : lastPosition = 0 viewpager.setCurrentItem(0, false) viewpager.offscreenPageLimit = pages.size + // todo check if post is necessary viewpager.post { - if (!fragmentChannel.isClosedForSend) { - fragmentChannel.offer(0) - } + fragmentEmit(0) } // trigger hook so title is set } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt index 949f1ddd..a95e931b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt @@ -45,13 +45,20 @@ import com.pitchedapps.frost.utils.frostEvent import com.pitchedapps.frost.utils.frostJsoup import com.pitchedapps.frost.utils.launchNewTask import com.pitchedapps.frost.utils.logFrostEvent -import com.pitchedapps.frost.utils.uniqueOnly +import com.pitchedapps.frost.web.FrostEmitter import com.pitchedapps.frost.web.LoginWebView +import com.pitchedapps.frost.web.asFrostEmitter import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async -import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withContext @@ -76,7 +83,15 @@ class LoginActivity : BaseActivity() { private val profile: ImageView by bindView(R.id.profile) private lateinit var profileLoader: RequestManager - private val refreshChannel = Channel<Boolean>(10) + + private val refreshMutableFlow = MutableSharedFlow<Boolean>( + extraBufferCapacity = 10, + onBufferOverflow = BufferOverflow.DROP_OLDEST + ) + + private val refreshFlow: SharedFlow<Boolean> = refreshMutableFlow.asSharedFlow() + + private val refreshEmit: FrostEmitter<Boolean> = refreshMutableFlow.asFrostEmitter() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -87,11 +102,12 @@ class LoginActivity : BaseActivity() { toolbar(toolbar) } profileLoader = GlideApp.with(profile) - launch { - for (refreshing in refreshChannel.uniqueOnly(this)) { - swipeRefresh.isRefreshing = refreshing - } - } + + refreshFlow + .distinctUntilChanged() + .onEach { swipeRefresh.isRefreshing = it } + .launchIn(this) + launch { val cookie = web.loadLogin { refresh(it != 100) }.await() L.d { "Login found" } @@ -107,7 +123,7 @@ class LoginActivity : BaseActivity() { } private fun refresh(refreshing: Boolean) { - refreshChannel.offer(refreshing) + refreshEmit(refreshing) } private suspend fun loadInfo(cookie: CookieEntity): Unit = withMainContext { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt index 755064cd..16606691 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt @@ -18,23 +18,38 @@ package com.pitchedapps.frost.activities import android.os.Bundle import androidx.viewpager.widget.ViewPager -import ca.allanwang.kau.utils.withMainContext import com.google.android.material.tabs.TabLayout import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.facebook.parsers.BadgeParser -import com.pitchedapps.frost.kotlin.subscribeDuringJob import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.views.BadgedIcon +import com.pitchedapps.frost.web.FrostEmitter +import com.pitchedapps.frost.web.asFrostEmitter import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.channels.BroadcastChannel -import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.onEach -@UseExperimental(ExperimentalCoroutinesApi::class) class MainActivity : BaseMainActivity() { - override val fragmentChannel = BroadcastChannel<Int>(10) - override val headerBadgeChannel = BroadcastChannel<String>(Channel.CONFLATED) + private val fragmentMutableFlow = MutableSharedFlow<Int>( + extraBufferCapacity = 10, + onBufferOverflow = BufferOverflow.DROP_OLDEST + ) + override val fragmentFlow: SharedFlow<Int> = fragmentMutableFlow.asSharedFlow() + override val fragmentEmit: FrostEmitter<Int> = fragmentMutableFlow.asFrostEmitter() + + private val headerMutableFlow = MutableStateFlow("") + override val headerFlow: SharedFlow<String> = headerMutableFlow.asSharedFlow() + override val headerEmit: FrostEmitter<String> = headerMutableFlow.asFrostEmitter() override fun onNestedCreate(savedInstanceState: Bundle?) { with(contentBinding) { @@ -51,9 +66,9 @@ class MainActivity : BaseMainActivity() { return } if (lastPosition != -1) { - fragmentChannel.offer(-(lastPosition + 1)) + fragmentEmit(-(lastPosition + 1)) } - fragmentChannel.offer(position) + fragmentEmit(position) lastPosition = position } @@ -90,12 +105,18 @@ class MainActivity : BaseMainActivity() { (tab.customView as BadgedIcon).badgeText = null } }) - headerBadgeChannel.subscribeDuringJob(this@MainActivity, Dispatchers.IO) { html -> - val data = - BadgeParser.parseFromData(cookie = fbCookie.webCookie, text = html)?.data - ?: return@subscribeDuringJob - L.v { "Badges $data" } - withMainContext { + headerFlow + .filter { it.isNotBlank() } + .mapNotNull { html -> + BadgeParser.parseFromData( + cookie = fbCookie.webCookie, + text = html + )?.data + } + .distinctUntilChanged() + .flowOn(Dispatchers.IO) + .onEach { data -> + L.v { "Badges $data" } tabsForEachView { _, view -> when (view.iicon) { FbItem.FEED.icon -> view.badgeText = data.feed @@ -105,6 +126,7 @@ class MainActivity : BaseMainActivity() { } } } - } + .flowOn(Dispatchers.Main) + .launchIn(this@MainActivity) } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt index ef7579a8..8dbf9d5c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt @@ -27,7 +27,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout import ca.allanwang.kau.swipe.SwipeBackContract import ca.allanwang.kau.swipe.kauSwipeOnCreate import ca.allanwang.kau.swipe.kauSwipeOnDestroy -import ca.allanwang.kau.utils.ContextHelper import ca.allanwang.kau.utils.bindView import ca.allanwang.kau.utils.copyToClipboard import ca.allanwang.kau.utils.darken @@ -56,7 +55,6 @@ import com.pitchedapps.frost.facebook.USER_AGENT import com.pitchedapps.frost.facebook.USER_AGENT_DESKTOP_CONST import com.pitchedapps.frost.facebook.USER_AGENT_MOBILE_CONST import com.pitchedapps.frost.facebook.formattedFbUrl -import com.pitchedapps.frost.kotlin.subscribeDuringJob import com.pitchedapps.frost.utils.ARG_URL import com.pitchedapps.frost.utils.ARG_USER_ID import com.pitchedapps.frost.utils.BiometricUtils @@ -67,7 +65,10 @@ import com.pitchedapps.frost.views.FrostVideoViewer import com.pitchedapps.frost.views.FrostWebView import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.take import kotlinx.coroutines.launch import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import javax.inject.Inject @@ -85,7 +86,6 @@ import javax.inject.Inject * Used by notifications. Unlike the other overlays, this runs as a singleInstance * Going back will bring you back to the previous app */ -@UseExperimental(ExperimentalCoroutinesApi::class) class FrostWebActivity : WebOverlayActivityBase() { override fun onCreate(savedInstanceState: Bundle?) { @@ -97,10 +97,8 @@ class FrostWebActivity : WebOverlayActivityBase() { * We will subscribe to the load cycle once, * and pop a dialog giving the user the option to copy the shared text */ - val refreshReceiver = content.refreshChannel.openSubscription() content.scope.launch(Dispatchers.IO) { - refreshReceiver.receive() - refreshReceiver.cancel() + content.refreshFlow.take(1).collect() withMainContext { materialDialog { title(R.string.invalid_share_url) @@ -151,7 +149,6 @@ class WebOverlayDesktopActivity : WebOverlayActivityBase(USER_AGENT_DESKTOP_CONS */ class WebOverlayActivity : WebOverlayActivityBase() -@UseExperimental(ExperimentalCoroutinesApi::class) @AndroidEntryPoint abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT) : BaseActivity(), @@ -215,9 +212,7 @@ abstract class WebOverlayActivityBase(private val userAgent: String = USER_AGENT content.bind(this) - content.titleChannel.subscribeDuringJob(this, ContextHelper.coroutineContext) { - toolbar.title = it - } + content.titleFlow.onEach { toolbar.title = it }.launchIn(this) with(web) { userAgentString = userAgent |