diff options
Diffstat (limited to 'app/src/main/kotlin/com')
5 files changed, 47 insertions, 41 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 2d1ec7d6..7f69cc27 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt @@ -473,6 +473,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, override fun onDestroy() { fragmentChannel.close() + headerBadgeChannel.close() controlWebview?.destroy() super.onDestroy() } 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 cc375800..e5eb1907 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt @@ -20,21 +20,23 @@ import android.os.Bundle import androidx.viewpager.widget.ViewPager import com.google.android.material.tabs.TabLayout import com.pitchedapps.frost.facebook.FbItem +import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.views.BadgedIcon -import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.schedulers.Schedulers import io.reactivex.subjects.PublishSubject +import kotlinx.coroutines.Dispatchers 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 -import java.util.concurrent.TimeUnit @UseExperimental(ExperimentalCoroutinesApi::class) class MainActivity : BaseMainActivity() { override val fragmentChannel = BroadcastChannel<Int>(10) + override val headerBadgeChannel = Channel<String>(Channel.RENDEZVOUS) var lastPosition = -1 - val headerBadgeObservable = PublishSubject.create<String>() override fun onNestedCreate(savedInstanceState: Bundle?) { setupTabs() @@ -81,28 +83,37 @@ class MainActivity : BaseMainActivity() { (tab.customView as BadgedIcon).badgeText = null } }) - headerBadgeObservable.throttleFirst(15, TimeUnit.SECONDS) - .subscribeOn(Schedulers.newThread()) - .map { Jsoup.parse(it) } - .filter { it.select("[data-sigil=count]").size >= 0 } //ensure headers exist - .map { - val feed = it.select("[data-sigil*=feed] [data-sigil=count]") - val requests = it.select("[data-sigil*=requests] [data-sigil=count]") - val messages = it.select("[data-sigil*=messages] [data-sigil=count]") - val notifications = it.select("[data-sigil*=notifications] [data-sigil=count]") - return@map arrayOf(feed, requests, messages, notifications).map { e -> e?.getOrNull(0)?.ownText() } - } - .observeOn(AndroidSchedulers.mainThread()) - .subscribe { (feed, requests, messages, notifications) -> - tabsForEachView { _, view -> - when (view.iicon) { - FbItem.FEED.icon -> view.badgeText = feed - FbItem.FRIENDS.icon -> view.badgeText = requests - FbItem.MESSAGES.icon -> view.badgeText = messages - FbItem.NOTIFICATIONS.icon -> view.badgeText = notifications + launch(Dispatchers.IO) { + for (html in headerBadgeChannel) { + try { + val doc = Jsoup.parse(html) + if (doc.select("[data-sigil=count]").isEmpty()) + continue // Header doesn't exist + val (feed, requests, messages, notifications) = listOf( + "feed", + "requests", + "messages", + "notifications" + ) + .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) { + tabsForEachView { _, view -> + when (view.iicon) { + FbItem.FEED.icon -> view.badgeText = feed + FbItem.FRIENDS.icon -> view.badgeText = requests + FbItem.MESSAGES.icon -> view.badgeText = messages + FbItem.NOTIFICATIONS.icon -> view.badgeText = notifications + } + } } + } catch (e: Exception) { + L.e(e) { "Header badge error" } } - }.disposeOnDestroy() + } + } adapter.pages.forEach { tabs.addTab( tabs.newTab() diff --git a/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt b/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt index 9a70436e..483e49c5 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt @@ -20,6 +20,7 @@ import com.mikepenz.iconics.typeface.IIcon import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.fragments.BaseFragment import kotlinx.coroutines.channels.BroadcastChannel +import kotlinx.coroutines.channels.Channel /** * All the contracts for [MainActivity] @@ -28,6 +29,7 @@ interface ActivityContract : FileChooserActivityContract interface MainActivityContract : ActivityContract, MainFabContract { val fragmentChannel: BroadcastChannel<Int> + val headerBadgeChannel : Channel<String> fun setTitle(res: Int) fun setTitle(text: CharSequence) /** diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt index c5880840..72150ddd 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt @@ -16,7 +16,6 @@ */ package com.pitchedapps.frost.fragments -import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -41,6 +40,7 @@ import com.pitchedapps.frost.utils.REQUEST_TEXT_ZOOM import com.pitchedapps.frost.utils.frostEvent import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.channels.ReceiveChannel @@ -54,6 +54,7 @@ import kotlin.coroutines.CoroutineContext * All fragments pertaining to the main view * Must be attached to activities implementing [MainActivityContract] */ +@UseExperimental(ExperimentalCoroutinesApi::class) abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract, DynamicUiContract { companion object { @@ -90,7 +91,6 @@ abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract, Dyna set(value) { if (!isActive || value || this is WebFragment) return arguments!!.putBoolean(ARG_VALID, value) - L.e { "Invalidating position $position" } frostEvent( "Native Fallback", "Item" to baseEnum.name @@ -132,6 +132,10 @@ abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract, Dyna onCreateRunnable?.invoke(this) onCreateRunnable = null firstLoadRequest() + detachMainObservable() + (context as? MainActivityContract)?.let { + activityReceiver = attachMainObservable(it) + } } override fun setUserVisibleHint(isVisibleToUser: Boolean) { @@ -204,22 +208,11 @@ abstract class BaseFragment : Fragment(), CoroutineScope, FragmentContract, Dyna activityReceiver?.cancel() } - override fun onAttach(context: Context) { - super.onAttach(context) - detachMainObservable() - if (context is MainActivityContract) - activityReceiver = attachMainObservable(context) - } - - override fun onDetach() { - detachMainObservable() - super.onDetach() - } - override fun onDestroyView() { L.i { "Fragment on destroy $position ${hashCode()}" } content?.destroy() content = null + detachMainObservable() super.onDestroyView() } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt index 3945a9a0..4611d27d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt @@ -29,7 +29,6 @@ import com.pitchedapps.frost.utils.isIndependent import com.pitchedapps.frost.utils.launchImageActivity import com.pitchedapps.frost.utils.showWebContextMenu import com.pitchedapps.frost.views.FrostWebView -import io.reactivex.subjects.Subject import kotlinx.coroutines.channels.SendChannel /** @@ -39,7 +38,7 @@ class FrostJSI(val web: FrostWebView) { private val context = web.context private val activity = context as? MainActivity - private val header: Subject<String>? = activity?.headerBadgeObservable + private val header: SendChannel<String>? = activity?.headerBadgeChannel private val refresh: SendChannel<Boolean> = web.parent.refreshChannel private val cookies = activity?.cookies() ?: arrayListOf() @@ -133,6 +132,6 @@ class FrostJSI(val web: FrostWebView) { @JavascriptInterface fun handleHeader(html: String?) { html ?: return - header?.onNext(html) + header?.offer(html) } } |