aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt402
1 files changed, 402 insertions, 0 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
new file mode 100644
index 00000000..389ff88e
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt
@@ -0,0 +1,402 @@
+package com.pitchedapps.frost.activities
+
+import android.annotation.SuppressLint
+import android.app.AlarmManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.graphics.PointF
+import android.graphics.drawable.ColorDrawable
+import android.net.Uri
+import android.os.Bundle
+import android.support.annotation.StringRes
+import android.support.design.widget.AppBarLayout
+import android.support.design.widget.CoordinatorLayout
+import android.support.design.widget.FloatingActionButton
+import android.support.design.widget.TabLayout
+import android.support.v4.app.ActivityOptionsCompat
+import android.support.v4.app.Fragment
+import android.support.v4.app.FragmentManager
+import android.support.v4.app.FragmentPagerAdapter
+import android.support.v7.widget.Toolbar
+import android.view.Menu
+import android.view.MenuItem
+import android.webkit.ValueCallback
+import android.webkit.WebChromeClient
+import android.widget.FrameLayout
+import ca.allanwang.kau.searchview.SearchItem
+import ca.allanwang.kau.searchview.SearchView
+import ca.allanwang.kau.searchview.SearchViewHolder
+import ca.allanwang.kau.searchview.bindSearchView
+import ca.allanwang.kau.utils.*
+import co.zsmb.materialdrawerkt.builders.Builder
+import co.zsmb.materialdrawerkt.builders.accountHeader
+import co.zsmb.materialdrawerkt.builders.drawer
+import co.zsmb.materialdrawerkt.draweritems.badgeable.primaryItem
+import co.zsmb.materialdrawerkt.draweritems.badgeable.secondaryItem
+import co.zsmb.materialdrawerkt.draweritems.divider
+import co.zsmb.materialdrawerkt.draweritems.profile.profile
+import co.zsmb.materialdrawerkt.draweritems.profile.profileSetting
+import com.crashlytics.android.answers.ContentViewEvent
+import com.mikepenz.google_material_typeface_library.GoogleMaterial
+import com.mikepenz.iconics.IconicsDrawable
+import com.mikepenz.materialdrawer.AccountHeader
+import com.mikepenz.materialdrawer.Drawer
+import com.pitchedapps.frost.BuildConfig
+import com.pitchedapps.frost.R
+import com.pitchedapps.frost.contracts.FileChooserContract
+import com.pitchedapps.frost.contracts.FileChooserDelegate
+import com.pitchedapps.frost.contracts.MainActivityContract
+import com.pitchedapps.frost.contracts.VideoViewHolder
+import com.pitchedapps.frost.dbflow.TAB_COUNT
+import com.pitchedapps.frost.dbflow.loadFbCookie
+import com.pitchedapps.frost.dbflow.loadFbTabs
+import com.pitchedapps.frost.enums.MainActivityLayout
+import com.pitchedapps.frost.enums.Theme
+import com.pitchedapps.frost.facebook.FbCookie
+import com.pitchedapps.frost.facebook.FbItem
+import com.pitchedapps.frost.facebook.PROFILE_PICTURE_URL
+import com.pitchedapps.frost.fragments.BaseFragment
+import com.pitchedapps.frost.parsers.SearchParser
+import com.pitchedapps.frost.utils.*
+import com.pitchedapps.frost.utils.iab.FrostBilling
+import com.pitchedapps.frost.utils.iab.IS_FROST_PRO
+import com.pitchedapps.frost.utils.iab.IabMain
+import com.pitchedapps.frost.views.BadgedIcon
+import com.pitchedapps.frost.views.FrostVideoViewer
+import com.pitchedapps.frost.views.FrostViewPager
+import org.jetbrains.anko.doAsync
+import org.jetbrains.anko.uiThread
+
+/**
+ * Created by Allan Wang on 20/12/17.
+ *
+ * Most of the logic that is unrelated to handling fragments
+ */
+abstract class BaseMainActivity : BaseActivity(), MainActivityContract,
+ FileChooserContract by FileChooserDelegate(),
+ VideoViewHolder, SearchViewHolder,
+ FrostBilling by IabMain() {
+
+ lateinit var adapter: SectionsPagerAdapter
+ override val frameWrapper: FrameLayout by bindView(R.id.frame_wrapper)
+ val toolbar: Toolbar by bindView(R.id.toolbar)
+ val viewPager: FrostViewPager by bindView(R.id.container)
+ val fab: FloatingActionButton by bindView(R.id.fab)
+ val tabs: TabLayout by bindView(R.id.tabs)
+ val appBar: AppBarLayout by bindView(R.id.appbar)
+ val coordinator: CoordinatorLayout by bindView(R.id.main_content)
+ override var videoViewer: FrostVideoViewer? = null
+ lateinit var drawer: Drawer
+ lateinit var drawerHeader: AccountHeader
+
+ override var searchView: SearchView? = null
+ private val searchViewCache = mutableMapOf<String, List<SearchItem>>()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ if (BuildConfig.VERSION_CODE > Prefs.versionCode) {
+ Prefs.versionCode = BuildConfig.VERSION_CODE
+ if (!BuildConfig.DEBUG) {
+ frostChangelog()
+ frostAnswersCustom("Version",
+ "Version code" to BuildConfig.VERSION_CODE,
+ "Version name" to BuildConfig.VERSION_NAME,
+ "Build type" to BuildConfig.BUILD_TYPE,
+ "Frost id" to Prefs.frostId)
+ }
+ }
+ setFrameContentView(Prefs.mainActivityLayout.layoutRes)
+ setSupportActionBar(toolbar)
+ adapter = SectionsPagerAdapter(supportFragmentManager, loadFbTabs())
+ viewPager.adapter = adapter
+ viewPager.offscreenPageLimit = TAB_COUNT
+ setupDrawer(savedInstanceState)
+
+// fab.setOnClickListener { view ->
+// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
+// .setAction("Action", null).show()
+// }
+ setFrostColors(toolbar, themeWindow = false, headers = arrayOf(appBar), backgrounds = arrayOf(viewPager))
+ tabs.setBackgroundColor(Prefs.mainActivityLayout.backgroundColor())
+ onCreateBilling()
+ }
+
+ fun tabsForEachView(action: (position: Int, view: BadgedIcon) -> Unit) {
+ (0 until tabs.tabCount).asSequence().forEach { i ->
+ action(i, tabs.getTabAt(i)!!.customView as BadgedIcon)
+ }
+ }
+
+ private fun setupDrawer(savedInstanceState: Bundle?) {
+ val navBg = Prefs.bgColor.withMinAlpha(200).toLong()
+ val navHeader = Prefs.headerColor.withMinAlpha(200)
+ drawer = drawer {
+ toolbar = this@BaseMainActivity.toolbar
+ savedInstance = savedInstanceState
+ translucentStatusBar = false
+ sliderBackgroundColor = navBg
+ drawerHeader = accountHeader {
+ customViewRes = R.layout.material_drawer_header
+ textColor = Prefs.iconColor.toLong()
+ backgroundDrawable = ColorDrawable(navHeader)
+ selectionSecondLineShown = false
+ cookies().forEach { (id, name) ->
+ profile(name = name ?: "") {
+ iconUrl = PROFILE_PICTURE_URL(id)
+ textColor = Prefs.textColor.toLong()
+ selectedTextColor = Prefs.textColor.toLong()
+ selectedColor = 0x00000001.toLong()
+ identifier = id
+ }
+ }
+ profileSetting(nameRes = R.string.kau_logout) {
+ iicon = GoogleMaterial.Icon.gmd_exit_to_app
+ iconColor = Prefs.textColor.toLong()
+ textColor = Prefs.textColor.toLong()
+ identifier = -2L
+ }
+ profileSetting(nameRes = R.string.kau_add_account) {
+ iconDrawable = IconicsDrawable(this@BaseMainActivity, GoogleMaterial.Icon.gmd_add).actionBar().paddingDp(5).color(Prefs.textColor)
+ textColor = Prefs.textColor.toLong()
+ identifier = -3L
+ }
+ profileSetting(nameRes = R.string.kau_manage_account) {
+ iicon = GoogleMaterial.Icon.gmd_settings
+ iconColor = Prefs.textColor.toLong()
+ textColor = Prefs.textColor.toLong()
+ identifier = -4L
+ }
+ onProfileChanged { _, profile, current ->
+ if (current) launchWebOverlay(FbItem.PROFILE.url)
+ else when (profile.identifier) {
+ -2L -> {
+ val currentCookie = loadFbCookie(Prefs.userId)
+ if (currentCookie == null) {
+ toast(R.string.account_not_found)
+ FbCookie.reset { launchLogin(cookies(), true) }
+ } else {
+ materialDialogThemed {
+ title(R.string.kau_logout)
+ content(String.format(string(R.string.kau_logout_confirm_as_x), currentCookie.name ?: Prefs.userId.toString()))
+ positiveText(R.string.kau_yes)
+ negativeText(R.string.kau_no)
+ onPositive { _, _ -> FbCookie.logout(this@BaseMainActivity) }
+ }
+ }
+ }
+ -3L -> launchNewTask(LoginActivity::class.java, clearStack = false)
+ -4L -> launchNewTask(SelectorActivity::class.java, cookies(), false)
+ else -> {
+ FbCookie.switchUser(profile.identifier, { refreshAll() })
+ tabsForEachView { _, view -> view.badgeText = null }
+ }
+ }
+ false
+ }
+ }
+ drawerHeader.setActiveProfile(Prefs.userId)
+ primaryFrostItem(FbItem.FEED_MOST_RECENT)
+ primaryFrostItem(FbItem.FEED_TOP_STORIES)
+ primaryFrostItem(FbItem.ACTIVITY_LOG)
+ divider()
+ primaryFrostItem(FbItem.PHOTOS)
+ primaryFrostItem(FbItem.GROUPS)
+ primaryFrostItem(FbItem.FRIENDS)
+ primaryFrostItem(FbItem.CHAT)
+ primaryFrostItem(FbItem.PAGES)
+ divider()
+ primaryFrostItem(FbItem.EVENTS)
+ primaryFrostItem(FbItem.BIRTHDAYS)
+ primaryFrostItem(FbItem.ON_THIS_DAY)
+ divider()
+ primaryFrostItem(FbItem.NOTES)
+ primaryFrostItem(FbItem.SAVED)
+ }
+ }
+
+ private fun Builder.primaryFrostItem(item: FbItem) = this.primaryItem(item.titleId) {
+ iicon = item.icon
+ iconColor = Prefs.textColor.toLong()
+ textColor = Prefs.textColor.toLong()
+ selectedIconColor = Prefs.textColor.toLong()
+ selectedTextColor = Prefs.textColor.toLong()
+ selectedColor = 0x00000001.toLong()
+ identifier = item.titleId.toLong()
+ onClick { _ ->
+ frostAnswers {
+ logContentView(ContentViewEvent()
+ .putContentName(item.name)
+ .putContentType("drawer_item"))
+ }
+ launchWebOverlay(item.url)
+ false
+ }
+ }
+
+ private fun Builder.secondaryFrostItem(@StringRes title: Int, onClick: () -> Unit) = this.secondaryItem(title) {
+ textColor = Prefs.textColor.toLong()
+ selectedIconColor = Prefs.textColor.toLong()
+ selectedTextColor = Prefs.textColor.toLong()
+ selectedColor = 0x00000001.toLong()
+ identifier = title.toLong()
+ onClick { _ -> onClick(); false }
+ }
+
+ fun refreshAll() {
+ fragmentSubject.onNext(REQUEST_REFRESH)
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ menuInflater.inflate(R.menu.menu_main, menu)
+ toolbar.tint(Prefs.iconColor)
+ setMenuIcons(menu, Prefs.iconColor,
+ R.id.action_settings to GoogleMaterial.Icon.gmd_settings,
+ R.id.action_search to GoogleMaterial.Icon.gmd_search)
+ searchViewBindIfNull {
+ bindSearchView(menu, R.id.action_search, Prefs.iconColor) {
+ textCallback = { query, _ ->
+ val results = searchViewCache[query]
+ if (results != null)
+ runOnUiThread { searchView?.results = results }
+ else
+ doAsync {
+ val data = SearchParser.query(query) ?: return@doAsync
+ val items = data.map { SearchItem(it.href, it.title, it.description) }.toMutableList()
+ if (items.isNotEmpty())
+ items.add(SearchItem("${FbItem._SEARCH.url}?q=$query", string(R.string.show_all_results), iicon = null))
+ searchViewCache.put(query, items)
+ uiThread { searchView?.results = items }
+ }
+ }
+ textDebounceInterval = 300
+ searchCallback = { query, _ -> launchWebOverlay("${FbItem._SEARCH.url}/?q=$query"); true }
+ closeListener = { _ -> searchViewCache.clear() }
+ foregroundColor = Prefs.textColor
+ backgroundColor = Prefs.bgColor.withMinAlpha(200)
+ onItemClick = { _, key, _, _ -> launchWebOverlay(key) }
+ }
+ }
+ return true
+ }
+
+ @SuppressLint("RestrictedApi")
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ R.id.action_settings -> {
+ val intent = Intent(this, SettingsActivity::class.java)
+ intent.putParcelableArrayListExtra(EXTRA_COOKIES, cookies())
+ val bundle = ActivityOptionsCompat.makeCustomAnimation(this, R.anim.kau_slide_in_right, R.anim.kau_fade_out).toBundle()
+ startActivityForResult(intent, ACTIVITY_SETTINGS, bundle)
+ }
+ else -> return super.onOptionsItemSelected(item)
+ }
+ return true
+ }
+
+ override fun openFileChooser(filePathCallback: ValueCallback<Array<Uri>?>, fileChooserParams: WebChromeClient.FileChooserParams) {
+ openMediaPicker(filePathCallback, fileChooserParams)
+ }
+
+ @SuppressLint("NewApi")
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ if (onActivityResultWeb(requestCode, resultCode, data)) return
+ super.onActivityResult(requestCode, resultCode, data)
+ if (requestCode == ACTIVITY_SETTINGS) {
+ if (resultCode and REQUEST_RESTART_APPLICATION > 0) { //completely restart application
+ L.d("Restart Application Requested")
+ val intent = packageManager.getLaunchIntentForPackage(packageName)
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
+ val pending = PendingIntent.getActivity(this, 666, intent, PendingIntent.FLAG_CANCEL_CURRENT)
+ val alarm = getSystemService(Context.ALARM_SERVICE) as AlarmManager
+ if (buildIsMarshmallowAndUp)
+ alarm.setExactAndAllowWhileIdle(AlarmManager.RTC, System.currentTimeMillis() + 100, pending)
+ else
+ alarm.setExact(AlarmManager.RTC, System.currentTimeMillis() + 100, pending)
+ finish()
+ System.exit(0)
+ return
+ }
+ if (resultCode and REQUEST_RESTART > 0) return restart()
+ /*
+ * These results can be stacked
+ */
+ if (resultCode and REQUEST_REFRESH > 0) fragmentSubject.onNext(REQUEST_REFRESH)
+ if (resultCode and REQUEST_NAV > 0) frostNavigationBar()
+ if (resultCode and REQUEST_TEXT_ZOOM > 0) fragmentSubject.onNext(REQUEST_TEXT_ZOOM)
+ if (resultCode and REQUEST_SEARCH > 0) invalidateOptionsMenu()
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ FbCookie.switchBackUser { }
+ }
+
+ override fun onStart() {
+ //validate some pro features
+ if (!IS_FROST_PRO) {
+ if (Prefs.theme == Theme.CUSTOM.ordinal) Prefs.theme = Theme.DEFAULT.ordinal
+ }
+ super.onStart()
+ }
+
+ override fun onDestroy() {
+ onDestroyBilling()
+ super.onDestroy()
+ }
+
+ override fun backConsumer(): Boolean {
+ if (currentFragment.onBackPressed()) return true
+ if (Prefs.exitConfirmation) {
+ materialDialogThemed {
+ title(R.string.kau_exit)
+ content(R.string.kau_exit_confirmation)
+ positiveText(R.string.kau_yes)
+ negativeText(R.string.kau_no)
+ onPositive { _, _ -> finish() }
+ checkBoxPromptRes(R.string.kau_do_not_show_again, false, { _, b -> Prefs.exitConfirmation = !b })
+ }
+ return true
+ }
+ return false
+ }
+
+ inline val currentFragment
+ get() = supportFragmentManager.findFragmentByTag("android:switcher:${R.id.container}:${viewPager.currentItem}") as BaseFragment
+
+ inner class SectionsPagerAdapter(fm: FragmentManager, val pages: List<FbItem>) : FragmentPagerAdapter(fm) {
+
+ override fun getItem(position: Int): Fragment {
+ val item = pages[position]
+ val fragment = BaseFragment(item.fragmentCreator, item, position)
+ //If first load hasn't occurred, add a listener
+ // todo check
+// if (!firstLoadFinished) {
+// var disposable: Disposable? = null
+// fragment.post {
+// disposable = it.web.refreshObservable.subscribe {
+// if (!it) {
+// //Ensure first load finisher only happens once
+// if (!firstLoadFinished) firstLoadFinished = true
+// disposable?.dispose()
+// disposable = null
+// }
+// }
+// }
+// }
+ return fragment
+ }
+
+ override fun getCount() = pages.size
+
+ override fun getPageTitle(position: Int): CharSequence = getString(pages[position].titleId)
+ }
+
+ override val lowerVideoPadding: PointF
+ get() =
+ if (Prefs.mainActivityLayout == MainActivityLayout.BOTTOM_BAR)
+ PointF(0f, toolbar.height.toFloat())
+ else
+ PointF(0f, 0f)
+} \ No newline at end of file