@ -3,9 +3,7 @@ package net.pokeranalytics.android.ui.fragment
import android.app.Activity.RESULT_OK
import android.app.Activity.RESULT_OK
import android.content.Intent
import android.content.Intent
import android.os.Bundle
import android.os.Bundle
import android.view.LayoutInflater
import android.view.*
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import android.widget.Toast
import androidx.core.app.ActivityOptionsCompat
import androidx.core.app.ActivityOptionsCompat
import androidx.core.view.isVisible
import androidx.core.view.isVisible
@ -17,6 +15,7 @@ import io.realm.Sort
import io.realm.kotlin.where
import io.realm.kotlin.where
import kotlinx.android.synthetic.main.fragment_feed.*
import kotlinx.android.synthetic.main.fragment_feed.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.LiveData
import net.pokeranalytics.android.model.interfaces.Editable
import net.pokeranalytics.android.model.interfaces.Editable
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.Filter
@ -30,13 +29,15 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.fragment.components.FilterableFragment
import net.pokeranalytics.android.ui.fragment.components.FilterableFragment
import net.pokeranalytics.android.ui.interfaces.FilterActivityRequestCode
import net.pokeranalytics.android.ui.interfaces.FilterActivityRequestCode
import net.pokeranalytics.android.ui.interfaces.FilterableType
import net.pokeranalytics.android.ui.interfaces.FilterableType
import net.pokeranalytics.android.ui.view.ContextMenuRecyclerView
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager
import net.pokeranalytics.android.util.Preferences
import net.pokeranalytics.android.util.Preferences
import net.pokeranalytics.android.util.billing.AppGuard
import net.pokeranalytics.android.util.extensions.count
import java.text.SimpleDateFormat
import java.text.SimpleDateFormat
import java.util.*
import java.util.*
class FeedFragment : FilterableFragment ( ) , RowRepresentableDelegate {
class FeedFragment : FilterableFragment ( ) , RowRepresentableDelegate {
private enum class Tab {
private enum class Tab {
@ -46,20 +47,20 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
companion object {
companion object {
const val REQUEST _CODE _MENU = 100
const val REQUEST _CODE _TRANSACTION _DETAILS = 101
fun newInstance ( ) : FeedFragment {
fun newInstance ( ) : FeedFragment {
val fragment = FeedFragment ( )
val fragment = FeedFragment ( )
val bundle = Bundle ( )
val bundle = Bundle ( )
fragment . arguments = bundle
fragment . arguments = bundle
return fragment
return fragment
}
}
}
}
private var currentTab = Tab . SESSIONS
private lateinit var feedSessionAdapter : FeedSessionRowRepresentableAdapter
private lateinit var feedSessionAdapter : FeedSessionRowRepresentableAdapter
private lateinit var feedTransactionAdapter : FeedTransactionRowRepresentableAdapter
private lateinit var feedTransactionAdapter : FeedTransactionRowRepresentableAdapter
private lateinit var realmSessions : RealmResults < Session >
private lateinit var realmTransactions : RealmResults < Transaction >
private lateinit var realmTransactions : RealmResults < Transaction >
private lateinit var betaLimitDate : Date
private lateinit var betaLimitDate : Date
@ -70,8 +71,8 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
override val observedEntities : List < Class < out RealmModel > > = listOf ( Session :: class . java , Transaction :: class . java )
override val observedEntities : List < Class < out RealmModel > > = listOf ( Session :: class . java , Transaction :: class . java )
override fun entitiesChanged ( clazz : Class < out RealmModel > ) {
override fun entitiesChanged ( clazz : Class < out RealmModel > , results : RealmResults < out RealmModel > ) {
super . entitiesChanged ( clazz )
super . entitiesChanged ( clazz , results )
when ( clazz . kotlin ) {
when ( clazz . kotlin ) {
Session :: class - > {
Session :: class - > {
@ -91,6 +92,34 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
return inflater . inflate ( R . layout . fragment _feed , container , false )
return inflater . inflate ( R . layout . fragment _feed , container , false )
}
}
override fun onCreateContextMenu ( menu : ContextMenu ? , v : View ? , menuInfo : ContextMenu . ContextMenuInfo ? ) {
super . onCreateContextMenu ( menu , v , menuInfo )
if ( v ?. id == R . id . menuRecyclerView ) {
activity ?. menuInflater ?. inflate ( R . menu . menu _session , menu )
}
}
override fun onContextItemSelected ( item : MenuItem ? ) : Boolean {
when ( item ?. itemId ) {
R . id . duplicate -> {
val info = item . menuInfo as ContextMenuRecyclerView . RecyclerViewContextMenuInfo
val sessionId = this . feedSessionAdapter . sessionIdForPosition ( info . position )
if ( sessionId != null ) {
createNewSession ( true , sessionId = sessionId , duplicate = true )
} else {
throw PAIllegalStateException ( " Session not found for duplicate at position: ${info.position} " )
}
}
else -> {
}
}
return true
}
override fun onViewCreated ( view : View , savedInstanceState : Bundle ? ) {
override fun onViewCreated ( view : View , savedInstanceState : Bundle ? ) {
super . onViewCreated ( view , savedInstanceState )
super . onViewCreated ( view , savedInstanceState )
initUI ( )
initUI ( )
@ -99,13 +128,13 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
override fun onActivityResult ( requestCode : Int , resultCode : Int , data : Intent ? ) {
override fun onActivityResult ( requestCode : Int , resultCode : Int , data : Intent ? ) {
super . onActivityResult ( requestCode , resultCode , data )
super . onActivityResult ( requestCode , resultCode , data )
if ( requestCode == REQUEST _CODE _MENU && resultCode == RESULT _OK && data != null ) {
if ( requestCode == RequestCode . FEED _MENU . value && resultCode == RESULT _OK && data != null ) {
when ( data . getIntExtra ( NewDataMenuActivity . IntentKey . CHOICE . keyName , - 1 ) ) {
when ( data . getIntExtra ( NewDataMenuActivity . IntentKey . CHOICE . keyName , - 1 ) ) {
0 -> createNewSession ( false )
0 -> createNewSession ( false )
1 -> createNewSession ( true )
1 -> createNewSession ( true )
2 -> createNewTransaction ( )
2 -> createNewTransaction ( )
}
}
} else if ( requestCode == REQUEST _CODE _TRANSACTION _DETAILS && resultCode == RESULT _OK && data != null ) {
} else if ( requestCode == RequestCode . FEED _TRANSACTION _DETAILS . value && resultCode == RESULT _OK && data != null ) {
if ( data . getStringExtra ( DataListActivity . IntentKey . ITEM _DELETED . keyName ) != null ) {
if ( data . getStringExtra ( DataListActivity . IntentKey . ITEM _DELETED . keyName ) != null ) {
deleteSelectedTransaction ( )
deleteSelectedTransaction ( )
}
}
@ -123,22 +152,9 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
override fun onDestroyView ( ) {
override fun onDestroyView ( ) {
super . onDestroyView ( )
super . onDestroyView ( )
realmSessions . removeAllChangeListeners ( )
realmTransactions . removeAllChangeListeners ( )
realmTransactions . removeAllChangeListeners ( )
}
}
/ *
override fun setUserVisibleHint ( isVisibleToUser : Boolean ) {
super . setUserVisibleHint ( isVisibleToUser )
if ( isVisibleToUser && view != null ) {
if ( FilterHandler . filterWasUpdated ) {
applyFilter ( )
FilterHandler . filterWasUpdated = false
}
}
}
* /
override fun onRowSelected ( position : Int , row : RowRepresentable , fromAction : Boolean ) {
override fun onRowSelected ( position : Int , row : RowRepresentable , fromAction : Boolean ) {
when ( row ) {
when ( row ) {
is Session -> SessionActivity . newInstance ( requireContext ( ) , sessionId = ( row as Editable ) . id )
is Session -> SessionActivity . newInstance ( requireContext ( ) , sessionId = ( row as Editable ) . id )
@ -149,7 +165,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
this ,
this ,
LiveData . TRANSACTION ,
LiveData . TRANSACTION ,
row . id ,
row . id ,
REQUEST _CODE _TRANSACTION _DETAILS
RequestCode . FEED _TRANSACTION _DETAILS . value
)
)
}
}
}
}
@ -160,37 +176,49 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
* /
* /
private fun initUI ( ) {
private fun initUI ( ) {
disclaimerContainer . isVisible = Preferences . shouldShowDisclaimer ( requireContext ( ) )
this . feedSessionAdapter = FeedSessionRowRepresentableAdapter ( getRealm ( ) , this )
registerForContextMenu ( this . menuRecyclerView )
val messageToShow : Preferences . FeedMessage ? = Preferences . feedMessageToShow ( requireContext ( ) )
if ( messageToShow != null ) {
messageBox . isVisible = true
message . text = getString ( messageToShow . resId )
disclaimerDismiss . setOnClickListener {
messageBox Dismiss . setOnClickListener {
Preferences . setStopShowingDisclaimer ( requireContext ( ) )
Preferences . setStopShowingMessage ( messageToShow , requireContext ( ) )
disclaimerContainer . animate ( ) . translationY ( disclaimerContainer . height . toFloat ( ) )
messageBox . animate ( ) . translationY ( messageBox . height . toFloat ( ) )
. setInterpolator ( FastOutSlowInInterpolator ( ) )
. setInterpolator ( FastOutSlowInInterpolator ( ) )
. withEndAction { disclaimerContainer ?. isVisible = false }
. withEndAction { messageBox ?. isVisible = false }
. start ( )
. start ( )
}
} else {
messageBox . isVisible = false
}
}
// Add button
addButton . setOnClickListener {
addButton . setOnClickListener {
activity ?. let {
activity ?. let {
val options = ActivityOptionsCompat . makeSceneTransitionAnimation ( it )
val options = ActivityOptionsCompat . makeSceneTransitionAnimation ( it )
val intent = Intent ( requireContext ( ) , NewDataMenuActivity :: class . java )
val intent = Intent ( requireContext ( ) , NewDataMenuActivity :: class . java )
startActivityForResult ( intent , REQUEST _CODE _MENU , options . toBundle ( ) )
startActivityForResult ( intent , RequestCode . FEED _MENU . value , options . toBundle ( ) )
}
}
}
}
// Tabs
tabs . addOnTabSelectedListener ( object : TabLayout . OnTabSelectedListener {
tabs . addOnTabSelectedListener ( object : TabLayout . OnTabSelectedListener {
override fun onTabSelected ( tab : TabLayout . Tab ) {
override fun onTabSelected ( tab : TabLayout . Tab ) {
when ( tab . position ) {
when ( tab . position ) {
0 -> {
Tab . SESSIONS . ordinal -> {
currentFilterable = FilterableType . SESSION
currentFilterable = FilterableType . SESSION
recyclerView . adapter = feedSessionAdapter
}
}
1 -> {
Tab . TRANSACTIONS . ordinal -> {
currentFilterable = FilterableType . TRANSACTION
currentFilterable = FilterableType . TRANSACTION
recyclerView . adapter = feedTransactionAdapter
}
}
}
}
tabChanged ( tab . position )
}
}
override fun onTabUnselected ( tab : TabLayout . Tab ) {
override fun onTabUnselected ( tab : TabLayout . Tab ) {
@ -209,10 +237,10 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
val sdf = SimpleDateFormat ( " dd/M/yyyy hh:mm " , Locale . getDefault ( ) )
val sdf = SimpleDateFormat ( " dd/M/yyyy hh:mm " , Locale . getDefault ( ) )
betaLimitDate = sdf . parse ( " 17/7/2019 10:00 " )
betaLimitDate = sdf . parse ( " 17/7/2019 10:00 " )
this . currentFilterable = FilterableType . SESSION
this . currentFilterable = FilterableType . SESSION
val viewManager = SmoothScrollLinearLayoutManager ( requireContext ( ) )
val viewManager = SmoothScrollLinearLayoutManager ( requireContext ( ) )
r ecyclerView. apply {
menuR ecyclerView. apply {
setHasFixedSize ( true )
setHasFixedSize ( true )
layoutManager = viewManager
layoutManager = viewManager
}
}
@ -221,30 +249,15 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
}
}
private fun loadSessions ( filter : Filter ? = null ) {
private fun loadSessions ( filter : Filter ? = null ) {
val sessionFilter : Filter ? = filter ?. let {
if ( it . filterableType == FilterableType . SESSION ) {
it
} else {
null
}
}
// Sessions
when ( filter ?. filterableType ) {
this . realmSessions =
FilterableType . SESSION -> {
sessionFilter ?. results ( ) ?: run { getRealm ( ) . where < Session > ( ) . isNotNull ( " startDate " ) . findAll ( ) }
this . feedSessionAdapter . filter = filter
this . realmSessions = this . realmSessions . sort ( " startDate " , Sort . DESCENDING )
}
else -> {
val pendingSessions = sessionFilter ?. let {
this . feedSessionAdapter . filter = null
getRealm ( ) . where < Session > ( ) . alwaysFalse ( ) . findAll ( )
}
} ?: run {
getRealm ( ) . where < Session > ( ) . isNull ( " year " ) . isNull ( " month " ) . findAll ( ) . sort ( " startDate " , Sort . DESCENDING )
}
var distinctDateSessions = sessionFilter ?. results ( " year " , " month " ) ?: run {
getRealm ( ) . where < Session > ( ) . distinct ( " year " , " month " ) . findAll ( )
}
}
distinctDateSessions = distinctDateSessions . sort ( " startDate " , Sort . DESCENDING )
this . feedSessionAdapter =
FeedSessionRowRepresentableAdapter ( this , realmSessions , pendingSessions , distinctDateSessions )
}
}
private fun loadTransactions ( filter : Filter ? = null ) {
private fun loadTransactions ( filter : Filter ? = null ) {
@ -272,21 +285,27 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
/ * *
/ * *
* Create a new cash game
* Create a new cash game
* /
* /
private fun createNewSession ( isTournament : Boolean ) {
private fun createNewSession ( isTournament : Boolean , sessionId : String ? = null , duplicate : Boolean = false ) {
// val sessionCount = this.feedSessionAdapter.realmResults.size
// if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG
// Toast.makeText(context, "Please subscribe!", Toast.LENGTH_LONG).show()
// BillingActivity.newInstanceForResult(requireContext())
// return
// }
if ( Date ( ) . after ( betaLimitDate ) ) {
val sessionCount = getRealm ( ) . count ( Session :: class . java )
this . showEndOfBetaMessage ( )
if ( ! AppGuard . isProUser && sessionCount >= AppGuard . MAX _SESSIONS _BEFORE _REQUESTING _SUBSCRIPTION ) { // && !BuildConfig.DEBUG
BillingActivity . newInstanceForResult ( this , true )
return
return
}
}
SessionActivity . newInstanceforResult ( this , isTournament , requestCode = RequestCode . NEW _SESSION . value )
// Keep commented code for special versions
// if (Date().after(betaLimitDate)) {
// this.showEndOfBetaMessage()
// return
// }
SessionActivity . newInstanceforResult (
this ,
isTournament ,
sessionId = sessionId ,
duplicate = duplicate ,
requestCode = RequestCode . NEW _SESSION . value
)
newSessionCreated = true
newSessionCreated = true
}
}
@ -295,38 +314,36 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
* /
* /
private fun createNewTransaction ( ) {
private fun createNewTransaction ( ) {
if ( Date ( ) . after ( betaLimitDate ) ) {
// if (Date().after(betaLimitDate)) {
this . showEndOfBetaMessage ( )
// this.showEndOfBetaMessage( )
return
// return
}
// }
EditableDataActivity . newInstanceForResult ( this , LiveData . TRANSACTION , null , RequestCode . NEW _TRANSACTION . value )
EditableDataActivity . newInstanceForResult ( this , LiveData . TRANSACTION , null , RequestCode . NEW _TRANSACTION . value )
// EditableDataActivity.newInstance(requireContext(), LiveData.TRANSACTION.ordinal)
}
}
/ * *
/ * *
* Delete selected transaction
* Delete selected transaction
* /
* /
private fun deleteSelectedTransaction ( ) {
private fun deleteSelectedTransaction ( ) {
val realm = getRealm ( )
getRealm ( ) . executeTransaction {
realm . beginTransaction ( )
selectedTransaction ?. deleteFromRealm ( )
selectedTransaction ?. deleteFromRealm ( )
}
realm . commitTransaction ( )
selectedTransactionPosition = - 1
selectedTransactionPosition = - 1
}
}
/ * *
/ * *
* Show end of beta message
* Show end of beta message
* Keep for possible future uses
* /
* /
private fun showEndOfBetaMessage ( ) {
private fun showEndOfBetaMessage ( ) {
Toast . makeText (
Toast . makeText (
context ,
context ,
" Beta has ended. Thanks a lot for your participation ! Please update with the Google Play version to continue using the app" ,
" App version has ended. Thanks a lot for using it ! Please update with the Google Play version to continue using the app. " ,
Toast . LENGTH _LONG
Toast . LENGTH _LONG
) . show ( )
) . show ( )
}
}
// Filter Handler
// Filter Handler
override fun applyFilter ( ) {
override fun applyFilter ( ) {
@ -337,41 +354,48 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
this . loadTransactions ( filter )
this . loadTransactions ( filter )
filter ?. let {
filter ?. let {
when ( it . filterableType ) {
when ( it . filterableType ) {
FilterableType . SESSION -> {
FilterableType . SESSION -> {
recyclerView . adapter = feedSessionAdapter
this . selectTab ( Tab . SESSIONS )
this . selectTab ( Tab . SESSIONS )
}
}
FilterableType . TRANSACTION -> {
FilterableType . TRANSACTION -> {
this . selectTab ( Tab . TRANSACTIONS )
recyclerView . adapter = feedTransactionAdapter
}
this . selectTab ( Tab . TRANSACTIONS )
else -> {
}
}
else -> {
}
}
}
adapterHasBeenSet = true
adapterHasBeenSet = true
}
}
if ( ! adapterHasBeenSet ) {
if ( ! adapterHasBeenSet ) {
adapterHasBeenSet = true
adapterHasBeenSet = true
recyclerView . adapter = feedSessionAdapter
this . setAdapter ( )
}
}
}
}
override fun removeFilter ( ) {
override fun removeFilter ( ) {
super . removeFilter ( )
super . removeFilter ( )
this . loadSessions ( )
this . loadSessions ( )
this . loadTransactions ( )
this . loadTransactions ( )
if ( currentFilterable == FilterableType . SESSION ) {
this . setAdapter ( )
recyclerView . adapter = feedSessionAdapter
} else {
recyclerView . adapter = feedTransactionAdapter
}
}
}
private fun selectTab ( tab : Tab ) {
private fun selectTab ( tab : Tab ) {
this . currentTab = tab
this . tabs . getTabAt ( tab . ordinal ) ?. select ( )
this . tabs . getTabAt ( tab . ordinal ) ?. select ( )
setAdapter ( )
}
private fun tabChanged ( index : Int ) {
this . currentTab = Tab . values ( ) [ index ]
setAdapter ( )
}
private fun setAdapter ( ) {
when ( this . currentTab ) {
Tab . SESSIONS -> menuRecyclerView . adapter = feedSessionAdapter
Tab . TRANSACTIONS -> menuRecyclerView . adapter = feedTransactionAdapter
}
}
}
}
}