aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/activities
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2018-12-31 18:57:28 -0500
committerGitHub <noreply@github.com>2018-12-31 18:57:28 -0500
commit149c6be1bfd4bd84381757940fece1be7b9801aa (patch)
tree85fe10e3ee3ea34ad717f0d61975ca0119dd36d5 /app/src/main/kotlin/com/pitchedapps/frost/activities
parent7661bbfc9b8f34bf9d92dc08a9fcd7cc6ec7cbb3 (diff)
downloadfrost-149c6be1bfd4bd84381757940fece1be7b9801aa.tar.gz
frost-149c6be1bfd4bd84381757940fece1be7b9801aa.tar.bz2
frost-149c6be1bfd4bd84381757940fece1be7b9801aa.zip
Enhancement/coroutines (#1273)
* Convert rest of fbcookie to suspended methods * Replace active checks with yield * Apply spotless * Switch cookie domain to exact url * Optimize imports and enable travis tests again * Update proguard rules * Remove unnecessary yield * Remove unused flyweight * Remove unused disposable and method * Use contexthelper instead of dispatcher main * Convert login activity to coroutines * Use kau helper methods for coroutines * Enhancement/offline site (#1288) * Begin conversion of offline site logic * Fix offline tests and add validation tests * Ignore cookie in jsoup if it is blank * Force load and zip to be in io * Use different zip files to fix tests * Log all test output * Do not log stdout * Allow test skip for fb offline
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/activities')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt13
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt29
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt169
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt19
6 files changed, 130 insertions, 112 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
index 08b5ab0c..5965e5cf 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
@@ -22,8 +22,6 @@ import ca.allanwang.kau.internal.KauBaseActivity
import ca.allanwang.kau.searchview.SearchViewHolder
import com.pitchedapps.frost.contracts.VideoViewHolder
import com.pitchedapps.frost.utils.setFrostTheme
-import io.reactivex.disposables.CompositeDisposable
-import io.reactivex.disposables.Disposable
/**
* Created by Allan Wang on 2017-06-12.
@@ -35,8 +33,6 @@ abstract class BaseActivity : KauBaseActivity() {
*/
protected open fun backConsumer(): Boolean = false
- private val compositeDisposable = CompositeDisposable()
-
final override fun onBackPressed() {
if (this is SearchViewHolder && searchViewOnBackPress()) return
if (this is VideoViewHolder && videoOnBackPress()) return
@@ -49,15 +45,6 @@ abstract class BaseActivity : KauBaseActivity() {
if (this !is WebOverlayActivityBase) setFrostTheme()
}
- override fun onDestroy() {
- compositeDisposable.dispose()
- super.onDestroy()
- }
-
- fun Disposable.disposeOnDestroy() {
- compositeDisposable.add(this)
- }
-
//
// private var networkDisposable: Disposable? = null
// private var networkConsumer: ((Connectivity) -> Unit)? = null
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 7f69cc27..13253bcf 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt
@@ -108,6 +108,7 @@ import kotlinx.android.synthetic.main.view_main_fab.*
import kotlinx.android.synthetic.main.view_main_toolbar.*
import kotlinx.android.synthetic.main.view_main_viewpager.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.launch
/**
* Created by Allan Wang on 20/12/17.
@@ -276,7 +277,10 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
val currentCookie = loadFbCookie(Prefs.userId)
if (currentCookie == null) {
toast(R.string.account_not_found)
- FbCookie.reset { launchLogin(cookies(), true) }
+ launch {
+ FbCookie.reset()
+ launchLogin(cookies(), true)
+ }
} else {
materialDialogThemed {
title(R.string.kau_logout)
@@ -288,15 +292,22 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
)
positiveText(R.string.kau_yes)
negativeText(R.string.kau_no)
- onPositive { _, _ -> FbCookie.logout(this@BaseMainActivity) }
+ onPositive { _, _ ->
+ launch {
+ FbCookie.logout(this@BaseMainActivity)
+ }
+ }
}
}
}
-3L -> launchNewTask<LoginActivity>(clearStack = false)
-4L -> launchNewTask<SelectorActivity>(cookies(), false)
else -> {
- FbCookie.switchUser(profile.identifier, this@BaseMainActivity::refreshAll)
- tabsForEachView { _, view -> view.badgeText = null }
+ launch {
+ FbCookie.switchUser(profile.identifier)
+ tabsForEachView { _, view -> view.badgeText = null }
+ refreshAll()
+ }
}
}
false
@@ -456,12 +467,14 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
override fun onResume() {
super.onResume()
- FbCookie.switchBackUser {}
+ val shouldReload = System.currentTimeMillis() - lastAccessTime > MAIN_TIMEOUT_DURATION
+ lastAccessTime = System.currentTimeMillis() // precaution to avoid loops
controlWebview?.resumeTimers()
- if (System.currentTimeMillis() - lastAccessTime > MAIN_TIMEOUT_DURATION) {
- refreshAll()
+ launch {
+ FbCookie.switchBackUser()
+ if (shouldReload)
+ refreshAll()
}
- lastAccessTime = System.currentTimeMillis() // precaution to avoid loops
}
override fun onPause() {
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 8b5fe38d..9540636a 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt
@@ -18,7 +18,6 @@ package com.pitchedapps.frost.activities
import android.graphics.drawable.Drawable
import android.os.Bundle
-import android.os.Handler
import android.widget.ImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.appcompat.widget.Toolbar
@@ -26,6 +25,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import ca.allanwang.kau.utils.bindView
import ca.allanwang.kau.utils.fadeIn
import ca.allanwang.kau.utils.fadeOut
+import ca.allanwang.kau.utils.withMainContext
import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
@@ -34,7 +34,7 @@ import com.bumptech.glide.request.target.Target
import com.pitchedapps.frost.R
import com.pitchedapps.frost.dbflow.CookieModel
import com.pitchedapps.frost.dbflow.fetchUsername
-import com.pitchedapps.frost.dbflow.loadFbCookiesAsync
+import com.pitchedapps.frost.dbflow.loadFbCookiesSuspend
import com.pitchedapps.frost.facebook.FbCookie
import com.pitchedapps.frost.facebook.profilePictureUrl
import com.pitchedapps.frost.glide.FrostGlide
@@ -46,11 +46,16 @@ import com.pitchedapps.frost.utils.frostEvent
import com.pitchedapps.frost.utils.launchNewTask
import com.pitchedapps.frost.utils.logFrostEvent
import com.pitchedapps.frost.utils.setFrostColors
+import com.pitchedapps.frost.utils.uniqueOnly
import com.pitchedapps.frost.web.LoginWebView
-import io.reactivex.Single
-import io.reactivex.android.schedulers.AndroidSchedulers
-import io.reactivex.functions.BiFunction
-import io.reactivex.subjects.SingleSubject
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlinx.coroutines.withContext
+import kotlin.coroutines.resume
/**
* Created by Allan Wang on 2017-06-01.
@@ -63,18 +68,8 @@ class LoginActivity : BaseActivity() {
private val textview: AppCompatTextView by bindView(R.id.textview)
private val profile: ImageView by bindView(R.id.profile)
- private val profileSubject = SingleSubject.create<Boolean>()
- private val usernameSubject = SingleSubject.create<String>()
private lateinit var profileLoader: RequestManager
-
- // Helper to set and enable swipeRefresh
- private var refresh: Boolean
- get() = swipeRefresh.isRefreshing
- set(value) {
- if (value) swipeRefresh.isEnabled = true
- swipeRefresh.isRefreshing = value
- if (!value) swipeRefresh.isEnabled = false
- }
+ private val refreshChannel = Channel<Boolean>(10)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -84,80 +79,96 @@ class LoginActivity : BaseActivity() {
setFrostColors {
toolbar(toolbar)
}
- web.loadLogin({ refresh = it != 100 }) { cookie ->
+ profileLoader = GlideApp.with(profile)
+ launch {
+ for (refreshing in refreshChannel.uniqueOnly(this)) {
+ if (refreshing) swipeRefresh.isEnabled = true
+ swipeRefresh.isRefreshing = refreshing
+ if (!refreshing) swipeRefresh.isEnabled = false
+ }
+ }
+ launch {
+ val cookie = web.loadLogin { refresh(it != 100) }
L.d { "Login found" }
FbCookie.save(cookie.id)
web.fadeOut(onFinish = {
profile.fadeIn()
- loadInfo(cookie)
+ launch { loadInfo(cookie) }
})
}
- profileLoader = GlideApp.with(profile)
}
- private fun loadInfo(cookie: CookieModel) {
- refresh = true
- Single.zip<Boolean, String, Pair<Boolean, String>>(
- profileSubject,
- usernameSubject,
- BiFunction(::Pair)
- )
- .observeOn(AndroidSchedulers.mainThread()).subscribe { (foundImage, name) ->
- refresh = false
- if (!foundImage) {
- L.e { "Could not get profile photo; Invalid userId?" }
- L._i { cookie }
- }
- textview.text = String.format(getString(R.string.welcome), name)
- textview.fadeIn()
- frostEvent("Login", "success" to true)
- /*
- * The user may have logged into an account that is already in the database
- * We will let the db handle duplicates and load it now after the new account has been saved
- */
- loadFbCookiesAsync {
- val cookies = ArrayList(it)
- Handler().postDelayed({
- if (Showcase.intro)
- launchNewTask<IntroActivity>(cookies, true)
- else
- launchNewTask<MainActivity>(cookies, true)
- }, 1000)
- }
- }.disposeOnDestroy()
- loadProfile(cookie.id)
- loadUsername(cookie)
+ private fun refresh(refreshing: Boolean) {
+ refreshChannel.offer(refreshing)
}
- private fun loadProfile(id: Long) {
- profileLoader.load(profilePictureUrl(id))
- .transform(FrostGlide.roundCorner).listener(object : RequestListener<Drawable> {
- override fun onResourceReady(
- resource: Drawable?,
- model: Any?,
- target: Target<Drawable>?,
- dataSource: DataSource?,
- isFirstResource: Boolean
- ): Boolean {
- profileSubject.onSuccess(true)
- return false
- }
-
- override fun onLoadFailed(
- e: GlideException?,
- model: Any?,
- target: Target<Drawable>?,
- isFirstResource: Boolean
- ): Boolean {
- e.logFrostEvent("Profile loading exception")
- profileSubject.onSuccess(false)
- return false
- }
- }).into(profile)
+ private suspend fun loadInfo(cookie: CookieModel): Unit = withMainContext {
+ refresh(true)
+
+ val imageDeferred = async { loadProfile(cookie.id) }
+ val nameDeferred = async { loadUsername(cookie) }
+
+ val foundImage = imageDeferred.await()
+ val name = nameDeferred.await()
+
+ refresh(false)
+
+ if (!foundImage) {
+ L.e { "Could not get profile photo; Invalid userId?" }
+ L._i { cookie }
+ }
+
+ textview.text = String.format(getString(R.string.welcome), name)
+ textview.fadeIn()
+ frostEvent("Login", "success" to true)
+
+ /*
+ * The user may have logged into an account that is already in the database
+ * We will let the db handle duplicates and load it now after the new account has been saved
+ */
+ val cookies = ArrayList(loadFbCookiesSuspend())
+ delay(1000)
+ if (Showcase.intro)
+ launchNewTask<IntroActivity>(cookies, true)
+ else
+ launchNewTask<MainActivity>(cookies, true)
+ }
+
+ private suspend fun loadProfile(id: Long): Boolean = withMainContext {
+ suspendCancellableCoroutine<Boolean> { cont ->
+ profileLoader.load(profilePictureUrl(id))
+ .transform(FrostGlide.roundCorner).listener(object : RequestListener<Drawable> {
+ override fun onResourceReady(
+ resource: Drawable?,
+ model: Any?,
+ target: Target<Drawable>?,
+ dataSource: DataSource?,
+ isFirstResource: Boolean
+ ): Boolean {
+ cont.resume(true)
+ return false
+ }
+
+ override fun onLoadFailed(
+ e: GlideException?,
+ model: Any?,
+ target: Target<Drawable>?,
+ isFirstResource: Boolean
+ ): Boolean {
+ e.logFrostEvent("Profile loading exception")
+ cont.resume(false)
+ return false
+ }
+ }).into(profile)
+ }
}
- private fun loadUsername(cookie: CookieModel) {
- cookie.fetchUsername(usernameSubject::onSuccess).disposeOnDestroy()
+ private suspend fun loadUsername(cookie: CookieModel): String = withContext(Dispatchers.IO) {
+ suspendCancellableCoroutine<String> { cont ->
+ cookie.fetchUsername {
+ cont.resume(it)
+ }
+ }
}
override fun backConsumer(): Boolean {
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 90f38e9e..9a0c6270 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt
@@ -18,6 +18,7 @@ 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.utils.L
@@ -27,7 +28,6 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
import org.jsoup.Jsoup
@UseExperimental(ExperimentalCoroutinesApi::class)
@@ -97,8 +97,8 @@ class MainActivity : BaseMainActivity() {
.map { "[data-sigil*=$it] [data-sigil=count]" }
.map { doc.select(it) }
.map { e -> e?.getOrNull(0)?.ownText() }
- L._d { "Badges $feed $requests $messages $notifications" }
- withContext(Dispatchers.Main) {
+ L.v { "Badges $feed $requests $messages $notifications" }
+ withMainContext {
tabsForEachView { _, view ->
when (view.iicon) {
FbItem.FEED.icon -> view.badgeText = feed
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt
index 2907bac6..c3224237 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt
@@ -32,6 +32,7 @@ import com.pitchedapps.frost.utils.cookies
import com.pitchedapps.frost.utils.launchNewTask
import com.pitchedapps.frost.utils.setFrostColors
import com.pitchedapps.frost.views.AccountItem
+import kotlinx.coroutines.launch
/**
* Created by Allan Wang on 2017-06-04.
@@ -55,7 +56,10 @@ class SelectorActivity : BaseActivity() {
override fun onClick(v: View, position: Int, fastAdapter: FastAdapter<AccountItem>, item: AccountItem) {
if (item.cookie == null) this@SelectorActivity.launchNewTask<LoginActivity>()
- else FbCookie.switchUser(item.cookie) { launchNewTask<MainActivity>(cookies()) }
+ else launch {
+ FbCookie.switchUser(item.cookie)
+ launchNewTask<MainActivity>(cookies())
+ }
}
})
setFrostColors {
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 19a1109f..a8c25050 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt
@@ -43,6 +43,7 @@ import ca.allanwang.kau.utils.tint
import ca.allanwang.kau.utils.toDrawable
import ca.allanwang.kau.utils.toast
import ca.allanwang.kau.utils.withAlpha
+import ca.allanwang.kau.utils.withMainContext
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.mikepenz.community_material_typeface_library.CommunityMaterial
import com.mikepenz.google_material_typeface_library.GoogleMaterial
@@ -74,7 +75,6 @@ import com.pitchedapps.frost.views.FrostWebView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
import okhttp3.HttpUrl
/**
@@ -106,7 +106,7 @@ class FrostWebActivity : WebOverlayActivityBase(false) {
content.scope.launch(Dispatchers.IO) {
refreshReceiver.receive()
refreshReceiver.cancel()
- withContext(Dispatchers.Main) {
+ withMainContext {
materialDialogThemed {
title(R.string.invalid_share_url)
content(R.string.invalid_share_url_desc)
@@ -216,12 +216,15 @@ open class WebOverlayActivityBase(private val forceBasicAgent: Boolean) : BaseAc
if (forceBasicAgent) //todo check; the webview already adds it dynamically
userAgentString = USER_AGENT_BASIC
Prefs.prevId = Prefs.userId
- if (userId != Prefs.userId) FbCookie.switchUser(userId) { reloadBase(true) }
- else reloadBase(true)
- if (Showcase.firstWebOverlay) {
- coordinator.frostSnackbar(R.string.web_overlay_swipe_hint) {
- duration = BaseTransientBottomBar.LENGTH_INDEFINITE
- setAction(R.string.kau_got_it) { _ -> this.dismiss() }
+ launch {
+ if (userId != Prefs.userId)
+ FbCookie.switchUser(userId)
+ reloadBase(true)
+ if (Showcase.firstWebOverlay) {
+ coordinator.frostSnackbar(R.string.web_overlay_swipe_hint) {
+ duration = BaseTransientBottomBar.LENGTH_INDEFINITE
+ setAction(R.string.kau_got_it) { dismiss() }
+ }
}
}
}