From 1f2460b33405754ba0d9d940b1af98d65b8cbaa4 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sun, 18 Apr 2021 18:02:25 -0700 Subject: Rename basefragment file --- .../pitchedapps/frost/fragments/BaseFragment.kt | 263 +++++++++++++++++++++ .../pitchedapps/frost/fragments/FragmentBase.kt | 263 --------------------- 2 files changed, 263 insertions(+), 263 deletions(-) create mode 100644 app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt delete mode 100644 app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt new file mode 100644 index 00000000..c4f7d6fb --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt @@ -0,0 +1,263 @@ +/* + * Copyright 2018 Allan Wang + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.pitchedapps.frost.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import ca.allanwang.kau.utils.ContextHelper +import ca.allanwang.kau.utils.fadeScaleTransition +import ca.allanwang.kau.utils.setIcon +import ca.allanwang.kau.utils.withArguments +import com.google.android.material.floatingactionbutton.FloatingActionButton +import com.mikepenz.iconics.typeface.IIcon +import com.pitchedapps.frost.contracts.DynamicUiContract +import com.pitchedapps.frost.contracts.FrostContentParent +import com.pitchedapps.frost.contracts.MainActivityContract +import com.pitchedapps.frost.contracts.MainFabContract +import com.pitchedapps.frost.enums.FeedSort +import com.pitchedapps.frost.facebook.FbCookie +import com.pitchedapps.frost.facebook.FbItem +import com.pitchedapps.frost.injectors.ThemeProvider +import com.pitchedapps.frost.prefs.Prefs +import com.pitchedapps.frost.utils.ARG_URL +import com.pitchedapps.frost.utils.L +import com.pitchedapps.frost.utils.REQUEST_REFRESH +import com.pitchedapps.frost.utils.REQUEST_TEXT_ZOOM +import com.pitchedapps.frost.utils.frostEvent +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.Job +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.channels.ReceiveChannel +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import javax.inject.Inject +import kotlin.coroutines.CoroutineContext + +/** + * Created by Allan Wang on 2017-11-07. + * + * All fragments pertaining to the main view + * Must be attached to activities implementing [MainActivityContract] + */ +@UseExperimental(ExperimentalCoroutinesApi::class) +@AndroidEntryPoint +abstract class BaseFragment : + Fragment(), + CoroutineScope, + FragmentContract, + DynamicUiContract { + + companion object { + private const val ARG_POSITION = "arg_position" + private const val ARG_VALID = "arg_valid" + + internal operator fun invoke( + base: () -> BaseFragment, + prefs: Prefs, + useFallback: Boolean, + data: FbItem, + position: Int + ): BaseFragment { + val fragment = if (useFallback) WebFragment() else base() + val d = if (data == FbItem.FEED) FeedSort(prefs.feedSort).item else data + fragment.withArguments( + ARG_URL to d.url, + ARG_POSITION to position + ) + d.put(fragment.arguments!!) + return fragment + } + } + + @Inject + protected lateinit var mainContract: MainActivityContract + + @Inject + protected lateinit var fbCookie: FbCookie + + @Inject + protected lateinit var prefs: Prefs + + @Inject + protected lateinit var themeProvider: ThemeProvider + + open lateinit var job: Job + override val coroutineContext: CoroutineContext + get() = ContextHelper.dispatcher + job + + override val baseUrl: String by lazy { arguments!!.getString(ARG_URL)!! } + override val baseEnum: FbItem by lazy { FbItem[arguments]!! } + override val position: Int by lazy { arguments!!.getInt(ARG_POSITION) } + + override var valid: Boolean + get() = arguments!!.getBoolean(ARG_VALID, true) + set(value) { + if (!isActive || value || this is WebFragment) return + arguments!!.putBoolean(ARG_VALID, value) + frostEvent( + "Native Fallback", + "Item" to baseEnum.name + ) + mainContract.reloadFragment(this) + } + + override var firstLoad: Boolean = true + private var activityReceiver: ReceiveChannel? = null + private var onCreateRunnable: ((FragmentContract) -> Unit)? = null + + override var content: FrostContentParent? = null + + protected abstract val layoutRes: Int + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + job = SupervisorJob() + firstLoad = true + } + + final override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = inflater.inflate(layoutRes, container, false) + val content = view as? FrostContentParent + ?: throw IllegalArgumentException("layoutRes for fragment must return view implementing FrostContentParent") + this.content = content + content.bind(this) + return view + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + onCreateRunnable?.invoke(this) + onCreateRunnable = null + firstLoadRequest() + detachMainObservable() + activityReceiver = attachMainObservable(mainContract) + } + + override fun setUserVisibleHint(isVisibleToUser: Boolean) { + super.setUserVisibleHint(isVisibleToUser) + firstLoadRequest() + } + + override fun firstLoadRequest() { + val core = core ?: return + if (userVisibleHint && isVisible && firstLoad) { + core.reloadBase(true) + firstLoad = false + } + } + + override fun post(action: (fragment: FragmentContract) -> Unit) { + onCreateRunnable = action + } + + override fun setTitle(title: String) { + mainContract.setTitle(title) + } + + override fun attachMainObservable(contract: MainActivityContract): ReceiveChannel { + val receiver = contract.fragmentChannel.openSubscription() + launch { + for (flag in receiver) { + when (flag) { + REQUEST_REFRESH -> { + core?.apply { + clearHistory() + firstLoad = true + firstLoadRequest() + } + } + position -> { + contract.setTitle(baseEnum.titleId) + updateFab(contract) + core?.active = true + } + -(position + 1) -> { + core?.active = false + } + REQUEST_TEXT_ZOOM -> { + reloadTextSize() + } + } + } + } + return receiver + } + + override fun updateFab(contract: MainFabContract) { + contract.hideFab() // default + } + + protected fun FloatingActionButton.update(iicon: IIcon, click: () -> Unit) { + if (isShown) { + fadeScaleTransition { + setIcon(iicon, themeProvider.iconColor) + } + } else { + setIcon(iicon, themeProvider.iconColor) + show() + } + setOnClickListener { click() } + } + + override fun detachMainObservable() { + activityReceiver?.cancel() + } + + override fun onDestroyView() { + super.onDestroyView() + L.i { "Fragment on destroy $position ${hashCode()}" } + content?.destroy() + content = null + detachMainObservable() + } + + override fun onDestroy() { + job.cancel() + super.onDestroy() + } + + override fun reloadTheme() { + reloadThemeSelf() + content?.reloadTextSize() + } + + override fun reloadThemeSelf() { + // intentionally blank + } + + override fun reloadTextSize() { + reloadTextSizeSelf() + content?.reloadTextSize() + } + + override fun reloadTextSizeSelf() { + // intentionally blank + } + + override fun onBackPressed(): Boolean = content?.core?.onBackPressed() ?: false + + override fun onTabClick(): Unit = content?.core?.onTabClicked() ?: Unit +} diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt deleted file mode 100644 index c4f7d6fb..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright 2018 Allan Wang - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.pitchedapps.frost.fragments - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.Fragment -import ca.allanwang.kau.utils.ContextHelper -import ca.allanwang.kau.utils.fadeScaleTransition -import ca.allanwang.kau.utils.setIcon -import ca.allanwang.kau.utils.withArguments -import com.google.android.material.floatingactionbutton.FloatingActionButton -import com.mikepenz.iconics.typeface.IIcon -import com.pitchedapps.frost.contracts.DynamicUiContract -import com.pitchedapps.frost.contracts.FrostContentParent -import com.pitchedapps.frost.contracts.MainActivityContract -import com.pitchedapps.frost.contracts.MainFabContract -import com.pitchedapps.frost.enums.FeedSort -import com.pitchedapps.frost.facebook.FbCookie -import com.pitchedapps.frost.facebook.FbItem -import com.pitchedapps.frost.injectors.ThemeProvider -import com.pitchedapps.frost.prefs.Prefs -import com.pitchedapps.frost.utils.ARG_URL -import com.pitchedapps.frost.utils.L -import com.pitchedapps.frost.utils.REQUEST_REFRESH -import com.pitchedapps.frost.utils.REQUEST_TEXT_ZOOM -import com.pitchedapps.frost.utils.frostEvent -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.channels.ReceiveChannel -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import javax.inject.Inject -import kotlin.coroutines.CoroutineContext - -/** - * Created by Allan Wang on 2017-11-07. - * - * All fragments pertaining to the main view - * Must be attached to activities implementing [MainActivityContract] - */ -@UseExperimental(ExperimentalCoroutinesApi::class) -@AndroidEntryPoint -abstract class BaseFragment : - Fragment(), - CoroutineScope, - FragmentContract, - DynamicUiContract { - - companion object { - private const val ARG_POSITION = "arg_position" - private const val ARG_VALID = "arg_valid" - - internal operator fun invoke( - base: () -> BaseFragment, - prefs: Prefs, - useFallback: Boolean, - data: FbItem, - position: Int - ): BaseFragment { - val fragment = if (useFallback) WebFragment() else base() - val d = if (data == FbItem.FEED) FeedSort(prefs.feedSort).item else data - fragment.withArguments( - ARG_URL to d.url, - ARG_POSITION to position - ) - d.put(fragment.arguments!!) - return fragment - } - } - - @Inject - protected lateinit var mainContract: MainActivityContract - - @Inject - protected lateinit var fbCookie: FbCookie - - @Inject - protected lateinit var prefs: Prefs - - @Inject - protected lateinit var themeProvider: ThemeProvider - - open lateinit var job: Job - override val coroutineContext: CoroutineContext - get() = ContextHelper.dispatcher + job - - override val baseUrl: String by lazy { arguments!!.getString(ARG_URL)!! } - override val baseEnum: FbItem by lazy { FbItem[arguments]!! } - override val position: Int by lazy { arguments!!.getInt(ARG_POSITION) } - - override var valid: Boolean - get() = arguments!!.getBoolean(ARG_VALID, true) - set(value) { - if (!isActive || value || this is WebFragment) return - arguments!!.putBoolean(ARG_VALID, value) - frostEvent( - "Native Fallback", - "Item" to baseEnum.name - ) - mainContract.reloadFragment(this) - } - - override var firstLoad: Boolean = true - private var activityReceiver: ReceiveChannel? = null - private var onCreateRunnable: ((FragmentContract) -> Unit)? = null - - override var content: FrostContentParent? = null - - protected abstract val layoutRes: Int - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - job = SupervisorJob() - firstLoad = true - } - - final override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - val view = inflater.inflate(layoutRes, container, false) - val content = view as? FrostContentParent - ?: throw IllegalArgumentException("layoutRes for fragment must return view implementing FrostContentParent") - this.content = content - content.bind(this) - return view - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - onCreateRunnable?.invoke(this) - onCreateRunnable = null - firstLoadRequest() - detachMainObservable() - activityReceiver = attachMainObservable(mainContract) - } - - override fun setUserVisibleHint(isVisibleToUser: Boolean) { - super.setUserVisibleHint(isVisibleToUser) - firstLoadRequest() - } - - override fun firstLoadRequest() { - val core = core ?: return - if (userVisibleHint && isVisible && firstLoad) { - core.reloadBase(true) - firstLoad = false - } - } - - override fun post(action: (fragment: FragmentContract) -> Unit) { - onCreateRunnable = action - } - - override fun setTitle(title: String) { - mainContract.setTitle(title) - } - - override fun attachMainObservable(contract: MainActivityContract): ReceiveChannel { - val receiver = contract.fragmentChannel.openSubscription() - launch { - for (flag in receiver) { - when (flag) { - REQUEST_REFRESH -> { - core?.apply { - clearHistory() - firstLoad = true - firstLoadRequest() - } - } - position -> { - contract.setTitle(baseEnum.titleId) - updateFab(contract) - core?.active = true - } - -(position + 1) -> { - core?.active = false - } - REQUEST_TEXT_ZOOM -> { - reloadTextSize() - } - } - } - } - return receiver - } - - override fun updateFab(contract: MainFabContract) { - contract.hideFab() // default - } - - protected fun FloatingActionButton.update(iicon: IIcon, click: () -> Unit) { - if (isShown) { - fadeScaleTransition { - setIcon(iicon, themeProvider.iconColor) - } - } else { - setIcon(iicon, themeProvider.iconColor) - show() - } - setOnClickListener { click() } - } - - override fun detachMainObservable() { - activityReceiver?.cancel() - } - - override fun onDestroyView() { - super.onDestroyView() - L.i { "Fragment on destroy $position ${hashCode()}" } - content?.destroy() - content = null - detachMainObservable() - } - - override fun onDestroy() { - job.cancel() - super.onDestroy() - } - - override fun reloadTheme() { - reloadThemeSelf() - content?.reloadTextSize() - } - - override fun reloadThemeSelf() { - // intentionally blank - } - - override fun reloadTextSize() { - reloadTextSizeSelf() - content?.reloadTextSize() - } - - override fun reloadTextSizeSelf() { - // intentionally blank - } - - override fun onBackPressed(): Boolean = content?.core?.onBackPressed() ?: false - - override fun onTabClick(): Unit = content?.core?.onTabClicked() ?: Unit -} -- cgit v1.2.3