From 89effc942fdc412be3ab283ba7dc4e0c7bf8043d Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 18 Oct 2022 16:13:00 +0200 Subject: [PATCH] Fixes + calendar badge --- .../android/calculus/ReportWhistleBlower.kt | 8 +- .../android/ui/activity/HomeActivity.kt | 79 ++++++++++++++++--- .../android/ui/adapter/HomePagerAdapter.kt | 43 +++++----- .../android/ui/fragment/ReportsFragment.kt | 10 ++- .../android/ui/fragment/SettingsFragment.kt | 9 ++- .../ui/fragment/components/BaseFragment.kt | 10 +++ .../android/ui/modules/feed/FeedFragment.kt | 2 +- .../android/ui/view/rows/SettingsRow.kt | 6 +- .../android/ui/view/rows/StaticReport.kt | 3 +- .../android/util/Preferences.kt | 48 +++++------ .../android/util/SingletonHolder.kt | 26 ++++++ .../main/res/layout/row_title_badge_value.xml | 5 +- app/src/main/res/values/strings.xml | 1 + 13 files changed, 181 insertions(+), 69 deletions(-) create mode 100644 app/src/main/java/net/pokeranalytics/android/util/SingletonHolder.kt diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt b/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt index 6e92d52c..90cc459d 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/ReportWhistleBlower.kt @@ -93,6 +93,10 @@ class ReportWhistleBlower(var context: Context) { } } + fun clearNotifications() { + this.currentNotifications.clear() + } + } class ReportTask(private var whistleBlower: ReportWhistleBlower, var context: Context) { @@ -100,7 +104,7 @@ class ReportTask(private var whistleBlower: ReportWhistleBlower, var context: Co private var cancelled = false private val coroutineContext: CoroutineContext - get() = Dispatchers.Main + get() = Dispatchers.Default fun start() { launchReports() @@ -233,7 +237,7 @@ class ReportTask(private var whistleBlower: ReportWhistleBlower, var context: Co private fun analyseOptimalDuration(realm: Realm, staticReport: StaticReport, key: PerformanceKey, duration: Double) { - var storePerf: Boolean = true + var storePerf = true val performance = realm.where(Performance::class.java) .equalTo("reportId", staticReport.uniqueIdentifier) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt index 79016757..5ca73359 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/HomeActivity.kt @@ -11,11 +11,25 @@ import net.pokeranalytics.android.BuildConfig import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.NewPerformanceListener import net.pokeranalytics.android.databinding.ActivityHomeBinding +import net.pokeranalytics.android.model.filter.Query +import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.realm.Currency +import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.ui.activity.components.BaseActivity import net.pokeranalytics.android.ui.adapter.HomePagerAdapter +import net.pokeranalytics.android.util.Preferences import net.pokeranalytics.android.util.billing.AppGuard - +import net.pokeranalytics.android.util.extensions.findAll +import net.pokeranalytics.android.util.extensions.isSameMonth +import java.util.* + +enum class Tab(var identifier: Int) { + HISTORY(0), + STATS(1), + CALENDAR(2), + REPORTS(3), + SETTINGS(4) +} class HomeActivity : BaseActivity(), NewPerformanceListener { @@ -31,21 +45,26 @@ class HomeActivity : BaseActivity(), NewPerformanceListener { private var homePagerAdapter: HomePagerAdapter? = null private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item -> + + if (binding.viewPager.currentItem == Tab.REPORTS.identifier) { + this.paApplication.reportWhistleBlower?.clearNotifications() + } + when (item.itemId) { R.id.navigation_history -> { - displayFragment(0) + displayFragment(Tab.HISTORY) } R.id.navigation_stats -> { - displayFragment(1) + displayFragment(Tab.STATS) } R.id.navigation_calendar -> { - displayFragment(2) + displayFragment(Tab.CALENDAR) } R.id.navigation_reports -> { - displayFragment(3) + displayFragment(Tab.REPORTS) } R.id.navigation_settings -> { - displayFragment(4) + displayFragment(Tab.SETTINGS) } } binding.navigation.getOrCreateBadge(item.itemId).isVisible = false @@ -56,6 +75,7 @@ class HomeActivity : BaseActivity(), NewPerformanceListener { super.onResume() AppGuard.requestPurchasesUpdate() this.homePagerAdapter?.activityResumed() + lookForCalendarBadge() } private lateinit var binding: ActivityHomeBinding @@ -132,13 +152,52 @@ class HomeActivity : BaseActivity(), NewPerformanceListener { /** * Display a new fragment */ - private fun displayFragment(index: Int) { - binding.viewPager.setCurrentItem(index, false) + private fun displayFragment(tab: Tab) { + binding.viewPager.setCurrentItem(tab.identifier, false) + this.homePagerAdapter?.tabSelected(tab) } override fun newBestPerformanceHandler() { - binding.navigation.getOrCreateBadge(R.id.navigation_reports).isVisible = true - binding.navigation.getOrCreateBadge(R.id.navigation_reports).number = 1 + + if (Preferences.showInAppBadges(this)) { + binding.navigation.getOrCreateBadge(R.id.navigation_reports).isVisible = true + binding.navigation.getOrCreateBadge(R.id.navigation_reports).number = 1 + } + + } + + private fun lookForCalendarBadge() { + + if (!Preferences.showInAppBadges(this)) { + return + } + + val date = Preferences.lastCalendarBadgeDate(this) + + val cal = Calendar.getInstance() + val lastCheck = Calendar.getInstance().apply { timeInMillis = date } + + if (!cal.isSameMonth(lastCheck)) { + lookForSessionsLastMonth() + } + } + + private fun lookForSessionsLastMonth() { + + val cal = Calendar.getInstance() + cal.add(Calendar.MONTH, -1) + + val month = QueryCondition.AnyMonthOfYear(cal.get(Calendar.MONTH)) + val year = QueryCondition.AnyYear(cal.get(Calendar.YEAR)) + val query = Query(month, year) + + val sessions = getRealm().findAll(query) + if (sessions.isNotEmpty()) { + binding.navigation.getOrCreateBadge(R.id.navigation_calendar).isVisible = true + binding.navigation.getOrCreateBadge(R.id.navigation_calendar).number = 1 + Preferences.setLastCalendarBadgeDate(this, Date().time) + } + } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/adapter/HomePagerAdapter.kt b/app/src/main/java/net/pokeranalytics/android/ui/adapter/HomePagerAdapter.kt index 714900c0..7c4efc21 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/adapter/HomePagerAdapter.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/adapter/HomePagerAdapter.kt @@ -2,9 +2,12 @@ package net.pokeranalytics.android.ui.adapter import android.util.SparseArray import android.view.ViewGroup +import androidx.core.util.forEach +import androidx.core.util.size import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentStatePagerAdapter import net.pokeranalytics.android.exceptions.PAIllegalStateException +import net.pokeranalytics.android.ui.activity.Tab import net.pokeranalytics.android.ui.fragment.ReportsFragment import net.pokeranalytics.android.ui.fragment.SettingsFragment import net.pokeranalytics.android.ui.fragment.StatisticsFragment @@ -17,23 +20,23 @@ import java.lang.ref.WeakReference * Home Adapter */ class HomePagerAdapter(fragmentManager: FragmentManager) : - FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { + FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { private var weakReferences = SparseArray>() override fun getItem(position: Int): BaseFragment { return when (position) { - 0 -> FeedFragment.newInstance() - 1 -> StatisticsFragment.newInstance() - 2 -> CalendarFragment.newInstance() - 3 -> ReportsFragment.newInstance() - 4 -> SettingsFragment.newInstance() + Tab.HISTORY.identifier -> FeedFragment.newInstance() + Tab.STATS.identifier -> StatisticsFragment.newInstance() + Tab.CALENDAR.identifier -> CalendarFragment.newInstance() + Tab.REPORTS.identifier -> ReportsFragment.newInstance() + Tab.SETTINGS.identifier -> SettingsFragment.newInstance() else -> throw PAIllegalStateException("Should not happen, position = $position") } } override fun getCount(): Int { - return 5 + return Tab.values().size } override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { @@ -49,29 +52,27 @@ class HomePagerAdapter(fragmentManager: FragmentManager) : override fun getItemPosition(obj: Any): Int { return when (obj) { - is FeedFragment -> 0 - is StatisticsFragment -> 1 - is CalendarFragment -> 2 - is ReportsFragment -> 3 - is SettingsFragment -> 4 + is FeedFragment -> Tab.HISTORY.identifier + is StatisticsFragment -> Tab.STATS.identifier + is CalendarFragment -> Tab.CALENDAR.identifier + is ReportsFragment -> Tab.REPORTS.identifier + is SettingsFragment -> Tab.SETTINGS.identifier else -> throw PAIllegalStateException("Should not happen for object $obj") } } fun activityResumed() { - if (this.weakReferences.size() >= 4) { + this.weakReferences.forEach { _, value -> + value.get()?.activityResumed() + } - val ref = this.weakReferences.get(0) - ref?.get()?.let { - (it as FeedFragment).activityResumed() - } + } - this.weakReferences.get(4)?.get()?.let { - (it as SettingsFragment).activityResumed() - } + fun tabSelected(tab: Tab) { + if (this.weakReferences.size >= 5) { + this.weakReferences.get(tab.identifier).get()?.selectedTab() } - } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt index cffb9dea..38829167 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/ReportsFragment.kt @@ -39,6 +39,7 @@ import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rows.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rows.StaticReport import net.pokeranalytics.android.util.NULL_TEXT +import net.pokeranalytics.android.util.Preferences import timber.log.Timber import java.util.* @@ -128,6 +129,11 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc } + override fun selectedTab() { + this.updateRows() + this.dataListAdapter.notifyDataSetChanged() + } + // Business /** @@ -200,7 +206,9 @@ class ReportsFragment : DeletableItemFragment(), StaticRowRepresentableDataSourc for (performance in performances) { val report = performance.toStaticReport(getRealm()) - val badge = this.paApplication?.reportWhistleBlower?.has(performance.id) ?: false + val badge = Preferences.showInAppBadges(requireContext()) + && (this.paApplication?.reportWhistleBlower?.has(performance.id) ?: false) + val reportRow = PerformanceRow(performance, report, badge) sections.firstOrNull { it.report == report }?.let { section -> diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt index 4ec9ab22..df353214 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt @@ -130,8 +130,8 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep } - fun activityResumed() { - this.settingsAdapterRow.notifyDataSetChanged() // refreshes session durations + override fun activityResumed() { + this.settingsAdapterRow.notifyDataSetChanged() } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { @@ -184,6 +184,7 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep return when (row) { SettingsRow.STOP_NOTIFICATION -> Preferences.showStopNotifications(requireContext()) SettingsRow.SHOULD_SHOW_BLOG_TIPS -> Preferences.shouldShowBlogTips(requireContext()) + SettingsRow.SHOW_INAPP_BADGES -> Preferences.showInAppBadges(requireContext()) else -> false } } @@ -260,6 +261,10 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep val show = value as Boolean Preferences.showBlogTips(show, requireContext()) } + SettingsRow.SHOW_INAPP_BADGES -> { + val show = value as Boolean + Preferences.setShowInAppBadges(requireContext(), show) + } else -> {} } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt index 66dd9b9e..608b1326 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt @@ -70,6 +70,16 @@ abstract class BaseFragment : Fragment() { */ open fun onBackPressed() {} + /** + * Method called when the HomeActivity has resumed, spread to tabs only + */ + open fun activityResumed() {} + + /** + * Method called when a HomeActivity tab has been selected + */ + open fun selectedTab() {} + // /** // * Ask for app permission // */ diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedFragment.kt index 4b79532a..86fc78f1 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedFragment.kt @@ -568,7 +568,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseLis } } - fun activityResumed() { + override fun activityResumed() { this.sessionAdapter.notifyDataSetChanged() // refreshes session durations } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/SettingsRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/SettingsRow.kt index bb3b264d..2ed81e65 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/SettingsRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/SettingsRow.kt @@ -36,6 +36,7 @@ enum class SettingsRow : RowRepresentable { LANGUAGE, CURRENCY, DEALT_HANDS_PER_HOUR, + SHOW_INAPP_BADGES, // Export EXPORT_CSV_SESSIONS, @@ -79,7 +80,7 @@ enum class SettingsRow : RowRepresentable { rows.addAll(arrayListOf(FOLLOW_US, DISCORD, BLOG_TIPS, SHOULD_SHOW_BLOG_TIPS)) rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.preferences)) - rows.addAll(arrayListOf(CURRENCY, DEALT_HANDS_PER_HOUR)) + rows.addAll(arrayListOf(CURRENCY, DEALT_HANDS_PER_HOUR, SHOW_INAPP_BADGES)) rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.export)) rows.addAll(arrayListOf(EXPORT_CSV_SESSIONS, EXPORT_CSV_TRANSACTIONS)) @@ -129,6 +130,7 @@ enum class SettingsRow : RowRepresentable { POKER_RUMBLE -> R.string.poker_rumble DISCORD -> R.string.join_discord DEALT_HANDS_PER_HOUR -> R.string.dealt_hands_per_hour + SHOW_INAPP_BADGES -> R.string.show_inapp_badges else -> null } } @@ -141,7 +143,7 @@ enum class SettingsRow : RowRepresentable { VERSION, SUBSCRIPTION -> RowViewType.TITLE_VALUE.ordinal LANGUAGE, CURRENCY -> RowViewType.TITLE_VALUE_ARROW.ordinal FOLLOW_US -> RowViewType.ROW_FOLLOW_US.ordinal - STOP_NOTIFICATION, SHOULD_SHOW_BLOG_TIPS -> RowViewType.TITLE_SWITCH.ordinal + STOP_NOTIFICATION, SHOULD_SHOW_BLOG_TIPS, SHOW_INAPP_BADGES -> RowViewType.TITLE_SWITCH.ordinal STOP_NOTIFICATION_MESSAGE -> RowViewType.INFO.ordinal else -> RowViewType.TITLE_ARROW.ordinal } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/StaticReport.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/StaticReport.kt index b1d0e5bd..fa08fe80 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/StaticReport.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/StaticReport.kt @@ -56,7 +56,8 @@ sealed class StaticReport(override var uniqueIdentifier: Int) : RowRepresentable } - val basicReports: Set = setOf(General) + val basicReports: Set = setOf(General, Blinds, TournamentBuyin, + DayOfWeek, Location, TournamentType, Game, TableSize, Duration, OptimalDuration) } diff --git a/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt b/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt index f4b7ef65..2a500cd5 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt @@ -45,7 +45,9 @@ class Preferences { LAST_REVIEW_REQUEST_DATE("lastReviewRequestDate"), PATCH_NEGATIVE_LIMITS("negativeLimits"), PATCH_STAKES("patchStakes"), - CLEAN_BLINDS_FILTERS("deleteBlindsFilters") + CLEAN_BLINDS_FILTERS("deleteBlindsFilters"), + SHOW_INAPP_BADGES("showInAppBadges"), + LAST_CALENDAR_BADGE_DATE("lastCalendarBadgeDate") } enum class FeedMessage { @@ -302,7 +304,24 @@ class Preferences { fun getFirstLaunchDate(context: Context): Long { return getLong(Keys.FIRST_LAUNCH, context) } - } + + fun showInAppBadges(context: Context): Boolean { + return getBoolean(Keys.SHOW_INAPP_BADGES, context, true) + } + + fun setShowInAppBadges(context: Context, show: Boolean) { + setBoolean(Keys.SHOW_INAPP_BADGES, show, context) + } + + fun lastCalendarBadgeDate(context: Context): Long { + return getLong(Keys.LAST_CALENDAR_BADGE_DATE, context) + } + + fun setLastCalendarBadgeDate(context: Context, date: Long) { + setLong(Keys.LAST_CALENDAR_BADGE_DATE, date, context) + } + + } } @@ -349,28 +368,3 @@ class UserDefaults private constructor(context: Context) { } } - -open class SingletonHolder(creator: (A) -> T) { - private var creator: ((A) -> T)? = creator - @Volatile - private var instance: T? = null - - fun init(context: A): T { - val i = instance - if (i != null) { - return i - } - - return synchronized(this) { - val i2 = instance - if (i2 != null) { - i2 - } else { - val created = creator!!(context) - instance = created - creator = null - created - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/util/SingletonHolder.kt b/app/src/main/java/net/pokeranalytics/android/util/SingletonHolder.kt new file mode 100644 index 00000000..e3079c1a --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/util/SingletonHolder.kt @@ -0,0 +1,26 @@ +package net.pokeranalytics.android.util + +open class SingletonHolder(creator: (A) -> T) { + private var creator: ((A) -> T)? = creator + @Volatile + private var instance: T? = null + + fun init(context: A): T { + val i = instance + if (i != null) { + return i + } + + return synchronized(this) { + val i2 = instance + if (i2 != null) { + i2 + } else { + val created = creator!!(context) + instance = created + creator = null + created + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/row_title_badge_value.xml b/app/src/main/res/layout/row_title_badge_value.xml index 2afdd7ee..bc42dd92 100644 --- a/app/src/main/res/layout/row_title_badge_value.xml +++ b/app/src/main/res/layout/row_title_badge_value.xml @@ -9,10 +9,11 @@ Transfer Destination Optimal duration + Show in-app badges