commit
0b60373f24
@ -0,0 +1,48 @@ |
||||
package net.pokeranalytics.android.ui.activity |
||||
|
||||
import android.content.Intent |
||||
import android.os.Bundle |
||||
import androidx.fragment.app.Fragment |
||||
import net.pokeranalytics.android.R |
||||
import net.pokeranalytics.android.calculus.bankroll.BankrollReport |
||||
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity |
||||
import net.pokeranalytics.android.ui.fragment.BankrollDetailsFragment |
||||
|
||||
class BankrollDetailsActivity : PokerAnalyticsActivity() { |
||||
|
||||
companion object { |
||||
|
||||
private var bankrollReport: BankrollReport? = null |
||||
|
||||
/** |
||||
* Default constructor |
||||
*/ |
||||
fun newInstanceForResult(fragment: Fragment, bankrollReport: BankrollReport, requestCode: Int) { |
||||
this.bankrollReport = bankrollReport |
||||
val intent = Intent(fragment.requireContext(), BankrollDetailsActivity::class.java) |
||||
fragment.startActivityForResult(intent, requestCode) |
||||
} |
||||
} |
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) { |
||||
super.onCreate(savedInstanceState) |
||||
setContentView(R.layout.activity_bankroll_details) |
||||
initUI() |
||||
} |
||||
|
||||
/** |
||||
* Init UI |
||||
*/ |
||||
private fun initUI() { |
||||
|
||||
bankrollReport?.let { |
||||
val fragmentTransaction = supportFragmentManager.beginTransaction() |
||||
val reportDetailsFragment = BankrollDetailsFragment.newInstance(it) |
||||
fragmentTransaction.add(R.id.container, reportDetailsFragment) |
||||
fragmentTransaction.commit() |
||||
|
||||
bankrollReport = null |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,127 @@ |
||||
package net.pokeranalytics.android.ui.activity |
||||
|
||||
import android.animation.Animator |
||||
import android.animation.AnimatorListenerAdapter |
||||
import android.content.Context |
||||
import android.content.Intent |
||||
import android.os.Bundle |
||||
import android.view.View |
||||
import android.view.ViewAnimationUtils |
||||
import kotlinx.android.synthetic.main.activity_new_data.* |
||||
import kotlinx.coroutines.Dispatchers |
||||
import kotlinx.coroutines.GlobalScope |
||||
import kotlinx.coroutines.delay |
||||
import kotlinx.coroutines.launch |
||||
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity |
||||
import net.pokeranalytics.android.ui.extensions.px |
||||
|
||||
|
||||
class NewDataMenuActivity : PokerAnalyticsActivity() { |
||||
|
||||
enum class IntentKey(val keyName: String) { |
||||
CHOICE("CHOICE"), |
||||
} |
||||
|
||||
companion object { |
||||
fun newInstance(context: Context) { |
||||
val intent = Intent(context, NewDataMenuActivity::class.java) |
||||
context.startActivity(intent) |
||||
} |
||||
} |
||||
|
||||
private val fabSize = 48.px |
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) { |
||||
super.onCreate(savedInstanceState) |
||||
setContentView(net.pokeranalytics.android.R.layout.activity_new_data) |
||||
initUI() |
||||
} |
||||
|
||||
override fun onBackPressed() { |
||||
hideMenu() |
||||
} |
||||
|
||||
override fun onPause() { |
||||
super.onPause() |
||||
overridePendingTransition(0, 0) |
||||
} |
||||
|
||||
/** |
||||
* Init UI |
||||
*/ |
||||
private fun initUI() { |
||||
|
||||
overridePendingTransition(0, 0) |
||||
|
||||
container.viewTreeObserver.addOnGlobalLayoutListener { |
||||
showMenu() |
||||
} |
||||
|
||||
newCashGame.setOnClickListener { |
||||
finishWithResult(0) |
||||
} |
||||
|
||||
newTournament.setOnClickListener { |
||||
finishWithResult(1) |
||||
} |
||||
|
||||
newTransaction.setOnClickListener { |
||||
finishWithResult(2) |
||||
} |
||||
|
||||
container.setOnClickListener { |
||||
hideMenu() |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Set the result and hide menu |
||||
*/ |
||||
private fun finishWithResult(choice: Int) { |
||||
val intent = Intent() |
||||
intent.putExtra(IntentKey.CHOICE.keyName, choice) |
||||
setResult(RESULT_OK, intent) |
||||
GlobalScope.launch(Dispatchers.Main) { |
||||
delay(200) |
||||
hideMenu(true) |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Show menu |
||||
*/ |
||||
private fun showMenu() { |
||||
|
||||
val cx = menuContainer.measuredWidth - fabSize / 2 |
||||
val cy = menuContainer.measuredHeight - fabSize / 2 |
||||
val finalRadius = Math.max(menuContainer.width, menuContainer.height) |
||||
val anim = ViewAnimationUtils.createCircularReveal(menuContainer, cx, cy, 0f, finalRadius.toFloat()) |
||||
anim.duration = 300 |
||||
|
||||
menuContainer.visibility = View.VISIBLE |
||||
anim.start() |
||||
} |
||||
|
||||
/** |
||||
* Hide menu |
||||
*/ |
||||
private fun hideMenu(hideQuickly: Boolean = false) { |
||||
|
||||
val cx = menuContainer.measuredWidth - fabSize / 2 |
||||
val cy = menuContainer.measuredHeight - fabSize / 2 |
||||
val initialRadius = menuContainer.width |
||||
val anim = ViewAnimationUtils.createCircularReveal(menuContainer, cx, cy, initialRadius.toFloat(), 0f) |
||||
anim.duration = if (hideQuickly) 150 else 300 |
||||
|
||||
anim.addListener(object : AnimatorListenerAdapter() { |
||||
override fun onAnimationEnd(animation: Animator?) { |
||||
super.onAnimationEnd(animation) |
||||
menuContainer.visibility = View.INVISIBLE |
||||
finish() |
||||
} |
||||
}) |
||||
|
||||
anim.start() |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,166 @@ |
||||
package net.pokeranalytics.android.ui.adapter |
||||
|
||||
import android.view.LayoutInflater |
||||
import android.view.View |
||||
import android.view.ViewGroup |
||||
import androidx.appcompat.widget.AppCompatTextView |
||||
import androidx.recyclerview.widget.RecyclerView |
||||
import io.realm.RealmResults |
||||
import kotlinx.android.synthetic.main.row_transaction.view.* |
||||
import net.pokeranalytics.android.R |
||||
import net.pokeranalytics.android.model.realm.Transaction |
||||
import net.pokeranalytics.android.ui.view.BindableHolder |
||||
import net.pokeranalytics.android.ui.view.RowViewType |
||||
import net.pokeranalytics.android.util.NULL_TEXT |
||||
import net.pokeranalytics.android.util.extensions.getMonthAndYear |
||||
import timber.log.Timber |
||||
import java.util.* |
||||
import kotlin.collections.HashMap |
||||
|
||||
|
||||
/** |
||||
* An adapter capable of displaying a list of RowRepresentables |
||||
* @param dataSource the datasource providing rows |
||||
* @param delegate the delegate, notified of UI actions |
||||
*/ |
||||
class FeedTransactionRowRepresentableAdapter( |
||||
var delegate: RowRepresentableDelegate? = null, |
||||
var realmTransactions: RealmResults<Transaction>, |
||||
var distinctTransactionsHeaders: RealmResults<Transaction> |
||||
) : |
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() { |
||||
|
||||
private var headersPositions = HashMap<Int, Date?>() |
||||
private lateinit var sortedHeaders: SortedMap<Int, Date?> |
||||
|
||||
init { |
||||
refreshData() |
||||
} |
||||
|
||||
/** |
||||
* Display a transaction view |
||||
*/ |
||||
inner class RowTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { |
||||
fun bind(position: Int, row: Transaction?, adapter: FeedTransactionRowRepresentableAdapter) { |
||||
|
||||
itemView.transactionRow.setData(row as Transaction) |
||||
val listener = View.OnClickListener { |
||||
adapter.delegate?.onRowSelected(position, row) |
||||
} |
||||
itemView.transactionRow.setOnClickListener(listener) |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Display a header |
||||
*/ |
||||
inner class HeaderTitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { |
||||
fun bind(title: String) { |
||||
// Title |
||||
itemView.findViewById<AppCompatTextView>(R.id.title)?.let { |
||||
it.text = title |
||||
} |
||||
} |
||||
} |
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { |
||||
return if (viewType == RowViewType.ROW_TRANSACTION.ordinal) { |
||||
val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_transaction, parent, false) |
||||
RowTransactionViewHolder(layout) |
||||
} else { |
||||
val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_header_title, parent, false) |
||||
HeaderTitleViewHolder(layout) |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
override fun getItemViewType(position: Int): Int { |
||||
if (sortedHeaders.containsKey(position)) { |
||||
return RowViewType.HEADER_TITLE.ordinal |
||||
} else { |
||||
return RowViewType.ROW_TRANSACTION.ordinal |
||||
} |
||||
} |
||||
|
||||
override fun getItemCount(): Int { |
||||
return realmTransactions.size + distinctTransactionsHeaders.size |
||||
} |
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { |
||||
if (holder is RowTransactionViewHolder) { |
||||
holder.bind(position, getTransactionForPosition(position), this) |
||||
} else if (holder is HeaderTitleViewHolder) { |
||||
holder.bind(getHeaderForPosition(position)) |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Return the header |
||||
*/ |
||||
private fun getHeaderForPosition(position: Int): String { |
||||
if (sortedHeaders.containsKey(position)) { |
||||
val realmHeaderPosition = sortedHeaders.keys.indexOf(position) |
||||
return distinctTransactionsHeaders[realmHeaderPosition]?.date?.getMonthAndYear() ?: "" |
||||
} |
||||
return NULL_TEXT |
||||
} |
||||
|
||||
/** |
||||
* Get real index |
||||
*/ |
||||
private fun getTransactionForPosition(position: Int): Transaction? { |
||||
|
||||
// Row position |
||||
var headersBefore = 0 |
||||
for (key in sortedHeaders.keys) { |
||||
if (position > key) { |
||||
headersBefore++ |
||||
} else { |
||||
break |
||||
} |
||||
} |
||||
|
||||
return realmTransactions[position - headersBefore] |
||||
} |
||||
|
||||
/** |
||||
* Refresh headers positions |
||||
*/ |
||||
fun refreshData() { |
||||
|
||||
headersPositions.clear() |
||||
|
||||
val start = System.currentTimeMillis() |
||||
|
||||
var previousYear = Int.MAX_VALUE |
||||
var previousMonth = Int.MAX_VALUE |
||||
|
||||
val calendar = Calendar.getInstance() |
||||
|
||||
// Add headers if the date doesn't exist yet |
||||
for ((index, transaction) in realmTransactions.withIndex()) { |
||||
calendar.time = transaction.date |
||||
if (checkHeaderCondition(calendar, previousYear, previousMonth)) { |
||||
headersPositions[index + headersPositions.size] = transaction.date |
||||
previousYear = calendar.get(Calendar.YEAR) |
||||
previousMonth = calendar.get(Calendar.MONTH) |
||||
} |
||||
} |
||||
|
||||
sortedHeaders = headersPositions.toSortedMap() |
||||
|
||||
Timber.d("Create viewTypesPositions in: ${System.currentTimeMillis() - start}ms") |
||||
} |
||||
|
||||
/** |
||||
* Check if we need to add a header |
||||
* Can be change to manage different condition |
||||
*/ |
||||
private fun checkHeaderCondition(currentCalendar: Calendar, previousYear: Int, previousMonth: Int): Boolean { |
||||
return currentCalendar.get(Calendar.YEAR) == previousYear && currentCalendar.get(Calendar.MONTH) < previousMonth || (currentCalendar.get(Calendar.YEAR) < previousYear) |
||||
|
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,166 @@ |
||||
package net.pokeranalytics.android.ui.fragment |
||||
|
||||
import android.app.Activity.RESULT_OK |
||||
import android.content.Intent |
||||
import android.os.Bundle |
||||
import android.view.* |
||||
import androidx.recyclerview.widget.LinearLayoutManager |
||||
import kotlinx.android.synthetic.main.fragment_bankroll.* |
||||
import kotlinx.android.synthetic.main.fragment_stats.recyclerView |
||||
import net.pokeranalytics.android.R |
||||
import net.pokeranalytics.android.calculus.ComputedStat |
||||
import net.pokeranalytics.android.calculus.Stat |
||||
import net.pokeranalytics.android.calculus.bankroll.BankrollReport |
||||
import net.pokeranalytics.android.model.LiveData |
||||
import net.pokeranalytics.android.ui.activity.DataListActivity |
||||
import net.pokeranalytics.android.ui.activity.EditableDataActivity |
||||
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity |
||||
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter |
||||
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate |
||||
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource |
||||
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment |
||||
import net.pokeranalytics.android.ui.view.RowRepresentable |
||||
import net.pokeranalytics.android.ui.view.RowViewType |
||||
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable |
||||
|
||||
class BankrollDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { |
||||
|
||||
companion object { |
||||
|
||||
const val REQUEST_CODE_EDIT = 1000 |
||||
|
||||
/** |
||||
* Create new instance |
||||
*/ |
||||
fun newInstance(bankrollReport: BankrollReport): BankrollDetailsFragment { |
||||
val fragment = BankrollDetailsFragment() |
||||
fragment.bankrollReport = bankrollReport |
||||
return fragment |
||||
} |
||||
} |
||||
|
||||
private lateinit var parentActivity: PokerAnalyticsActivity |
||||
private lateinit var bankrollAdapter: RowRepresentableAdapter |
||||
private lateinit var bankrollReport: BankrollReport |
||||
|
||||
private var bankrollDetailsMenu: Menu? = null |
||||
private var rows: ArrayList<RowRepresentable> = ArrayList() |
||||
|
||||
// Life Cycle |
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { |
||||
return inflater.inflate(R.layout.fragment_bankroll_details, container, false) |
||||
} |
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
||||
super.onViewCreated(view, savedInstanceState) |
||||
initUI() |
||||
initData() |
||||
} |
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { |
||||
super.onActivityResult(requestCode, resultCode, data) |
||||
if (requestCode == REQUEST_CODE_EDIT && resultCode == RESULT_OK) { |
||||
if (data != null && data.getBooleanExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, false)) { |
||||
activity?.setResult(RESULT_OK, data) |
||||
activity?.finish() |
||||
} else { |
||||
updateMenuUI() |
||||
} |
||||
} |
||||
} |
||||
|
||||
override fun adapterRows(): List<RowRepresentable>? { |
||||
return rows |
||||
} |
||||
|
||||
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { |
||||
|
||||
} |
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { |
||||
menu?.clear() |
||||
inflater?.inflate(R.menu.toolbar_comparison_chart, menu) |
||||
this.bankrollDetailsMenu = menu |
||||
updateMenuUI() |
||||
super.onCreateOptionsMenu(menu, inflater) |
||||
} |
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem?): Boolean { |
||||
when (item!!.itemId) { |
||||
R.id.settings -> editBankroll() |
||||
} |
||||
return true |
||||
} |
||||
|
||||
// Business |
||||
|
||||
/** |
||||
* Init data |
||||
*/ |
||||
private fun initData() { |
||||
|
||||
rows.clear() |
||||
|
||||
rows.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.global)) |
||||
|
||||
val totalComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.total) |
||||
val netComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netResult) |
||||
val netBankedComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netBanked) |
||||
|
||||
rows.add(CustomizableRowRepresentable(RowViewType.TITLE_VALUE, resId = R.string.bankroll, computedStat = totalComputedStat)) |
||||
rows.add(CustomizableRowRepresentable(RowViewType.TITLE_VALUE, resId = R.string.net_result, computedStat = netComputedStat)) |
||||
rows.add(CustomizableRowRepresentable(RowViewType.TITLE_VALUE, resId = R.string.net_banked, computedStat = netBankedComputedStat)) |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Init UI |
||||
*/ |
||||
private fun initUI() { |
||||
|
||||
parentActivity = activity as PokerAnalyticsActivity |
||||
|
||||
// Avoid a bug during setting the title |
||||
toolbar.title = "" |
||||
|
||||
parentActivity.setSupportActionBar(toolbar) |
||||
parentActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true) |
||||
setHasOptionsMenu(true) |
||||
updateMenuUI() |
||||
|
||||
bankrollAdapter = RowRepresentableAdapter(this, this) |
||||
|
||||
val viewManager = LinearLayoutManager(requireContext()) |
||||
|
||||
recyclerView.apply { |
||||
setHasFixedSize(true) |
||||
layoutManager = viewManager |
||||
adapter = bankrollAdapter |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Update menu UI |
||||
*/ |
||||
private fun updateMenuUI() { |
||||
if (bankrollReport.setup.virtualBankroll) { |
||||
toolbar.title = getString(R.string.total) |
||||
collapsingToolbar.title = getString(R.string.total) |
||||
bankrollDetailsMenu?.findItem(R.id.settings)?.isVisible = false |
||||
} else { |
||||
toolbar.title = bankrollReport.setup.bankroll?.name |
||||
collapsingToolbar.title = bankrollReport.setup.bankroll?.name |
||||
bankrollDetailsMenu?.findItem(R.id.settings)?.isVisible = true |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Open Bankroll edit activity |
||||
*/ |
||||
private fun editBankroll() { |
||||
EditableDataActivity.newInstanceForResult(this, LiveData.BANKROLL.ordinal, bankrollReport.setup.bankroll?.id, REQUEST_CODE_EDIT) |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,192 @@ |
||||
package net.pokeranalytics.android.ui.fragment |
||||
|
||||
import android.app.Activity.RESULT_OK |
||||
import android.content.Intent |
||||
import android.os.Bundle |
||||
import android.view.LayoutInflater |
||||
import android.view.View |
||||
import android.view.ViewGroup |
||||
import android.widget.Toast |
||||
import androidx.core.app.ActivityOptionsCompat |
||||
import androidx.core.view.isVisible |
||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator |
||||
import io.realm.RealmResults |
||||
import io.realm.Sort |
||||
import io.realm.kotlin.where |
||||
import kotlinx.android.synthetic.main.fragment_feed.* |
||||
import net.pokeranalytics.android.R |
||||
import net.pokeranalytics.android.model.LiveData |
||||
import net.pokeranalytics.android.model.interfaces.Editable |
||||
import net.pokeranalytics.android.model.realm.Session |
||||
import net.pokeranalytics.android.model.realm.Transaction |
||||
import net.pokeranalytics.android.ui.activity.EditableDataActivity |
||||
import net.pokeranalytics.android.ui.activity.NewDataMenuActivity |
||||
import net.pokeranalytics.android.ui.activity.SessionActivity |
||||
import net.pokeranalytics.android.ui.adapter.FeedSessionRowRepresentableAdapter |
||||
import net.pokeranalytics.android.ui.adapter.FeedTransactionRowRepresentableAdapter |
||||
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate |
||||
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment |
||||
import net.pokeranalytics.android.ui.view.RowRepresentable |
||||
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager |
||||
import net.pokeranalytics.android.util.Preferences |
||||
import java.text.SimpleDateFormat |
||||
import java.util.* |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class FeedFragment : PokerAnalyticsFragment(), RowRepresentableDelegate { |
||||
|
||||
companion object { |
||||
|
||||
const val REQUEST_CODE_MENU = 100 |
||||
|
||||
fun newInstance(): FeedFragment { |
||||
val fragment = FeedFragment() |
||||
val bundle = Bundle() |
||||
fragment.arguments = bundle |
||||
return fragment |
||||
} |
||||
} |
||||
|
||||
private lateinit var feedSessionAdapter: FeedSessionRowRepresentableAdapter |
||||
private lateinit var feedTransactionAdapter: FeedTransactionRowRepresentableAdapter |
||||
private lateinit var realmSessions: RealmResults<Session> |
||||
private lateinit var realmTransactions: RealmResults<Transaction> |
||||
private lateinit var betaLimitDate: Date |
||||
|
||||
private var newSessionCreated: Boolean = false |
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { |
||||
return inflater.inflate(R.layout.fragment_feed, container, false) |
||||
} |
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
||||
super.onViewCreated(view, savedInstanceState) |
||||
initUI() |
||||
initData() |
||||
} |
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { |
||||
super.onActivityResult(requestCode, resultCode, data) |
||||
if (requestCode == REQUEST_CODE_MENU && resultCode == RESULT_OK && data != null) { |
||||
when(data.getIntExtra(NewDataMenuActivity.IntentKey.CHOICE.keyName, -1)) { |
||||
0 -> createNewSession(false) |
||||
1 -> createNewSession(true) |
||||
2 -> createNewTransaction() |
||||
} |
||||
} |
||||
} |
||||
|
||||
override fun onDestroyView() { |
||||
super.onDestroyView() |
||||
realmSessions.removeAllChangeListeners() |
||||
} |
||||
|
||||
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { |
||||
when(row) { |
||||
is Session -> SessionActivity.newInstance(requireContext(), sessionId = (row as Editable).id) |
||||
is Transaction -> EditableDataActivity.newInstance(requireContext(), LiveData.TRANSACTION.ordinal, row.id) |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Init UI |
||||
*/ |
||||
private fun initUI() { |
||||
|
||||
disclaimerContainer.isVisible = Preferences.shouldShowDisclaimer(requireContext()) |
||||
|
||||
disclaimerDismiss.setOnClickListener { |
||||
Preferences.setStopShowingDisclaimer(requireContext()) |
||||
|
||||
disclaimerContainer.animate().translationY(disclaimerContainer.height.toFloat()) |
||||
.setInterpolator(FastOutSlowInInterpolator()) |
||||
.withEndAction { disclaimerContainer?.isVisible = false } |
||||
.start() |
||||
} |
||||
|
||||
addButton.setOnClickListener { |
||||
activity?.let { |
||||
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(it) |
||||
val intent = Intent(requireContext(), NewDataMenuActivity::class.java) |
||||
startActivityForResult(intent, REQUEST_CODE_MENU, options.toBundle()) |
||||
} |
||||
} |
||||
|
||||
filterSessions.setOnClickListener { |
||||
recyclerView.adapter = this.feedSessionAdapter |
||||
} |
||||
|
||||
filterTransactions.setOnClickListener { |
||||
recyclerView.adapter = this.feedTransactionAdapter |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Init data |
||||
*/ |
||||
private fun initData() { |
||||
|
||||
val sdf = SimpleDateFormat("dd/M/yyyy hh:mm", Locale.getDefault()) |
||||
betaLimitDate = sdf.parse("17/7/2019 10:00") |
||||
|
||||
this.realmSessions = getRealm().where<Session>().findAll().sort("startDate", Sort.DESCENDING) |
||||
this.realmSessions.addChangeListener { _, _ -> |
||||
this.feedSessionAdapter.refreshData() |
||||
this.feedSessionAdapter.notifyDataSetChanged() |
||||
} |
||||
|
||||
val pendingSessions = getRealm().where<Session>().isNull("year").isNull("month").findAll().sort("startDate", Sort.DESCENDING) |
||||
val distinctDateSessions = getRealm().where<Session>().distinct("year", "month").findAll().sort("startDate", Sort.DESCENDING) |
||||
this.feedSessionAdapter = FeedSessionRowRepresentableAdapter(this, realmSessions, pendingSessions, distinctDateSessions) |
||||
|
||||
this.realmTransactions = getRealm().where<Transaction>().findAll().sort("date", Sort.DESCENDING) |
||||
val distinctDateTransactions = getRealm().where<Transaction>().distinct("year", "month").findAll().sort("date", Sort.DESCENDING) |
||||
this.feedTransactionAdapter = FeedTransactionRowRepresentableAdapter(this, realmTransactions, distinctDateTransactions) |
||||
|
||||
val viewManager = SmoothScrollLinearLayoutManager(requireContext()) |
||||
recyclerView.apply { |
||||
setHasFixedSize(true) |
||||
layoutManager = viewManager |
||||
adapter = feedSessionAdapter |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Create a new cash game |
||||
*/ |
||||
private fun createNewSession(isTournament: Boolean) { |
||||
|
||||
if (Date().after(betaLimitDate)) { |
||||
this.showEndOfBetaMessage() |
||||
return |
||||
} |
||||
|
||||
SessionActivity.newInstance(requireContext(), isTournament) |
||||
newSessionCreated = true |
||||
} |
||||
|
||||
/** |
||||
* Create a new transaction |
||||
*/ |
||||
private fun createNewTransaction() { |
||||
|
||||
if (Date().after(betaLimitDate)) { |
||||
this.showEndOfBetaMessage() |
||||
return |
||||
} |
||||
|
||||
EditableDataActivity.newInstance(requireContext(), LiveData.TRANSACTION.ordinal) |
||||
} |
||||
|
||||
/** |
||||
* Show end of beta message |
||||
*/ |
||||
private fun showEndOfBetaMessage() { |
||||
Toast.makeText(context, "Beta has ended. Please update with the Google Play version", Toast.LENGTH_LONG).show() |
||||
} |
||||
|
||||
} |
||||
@ -1,152 +0,0 @@ |
||||
package net.pokeranalytics.android.ui.fragment |
||||
|
||||
import android.os.Bundle |
||||
import android.view.LayoutInflater |
||||
import android.view.View |
||||
import android.view.ViewGroup |
||||
import android.widget.Toast |
||||
import androidx.core.view.isVisible |
||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator |
||||
import io.realm.RealmResults |
||||
import io.realm.Sort |
||||
import io.realm.kotlin.where |
||||
import kotlinx.android.synthetic.main.fragment_history.* |
||||
import net.pokeranalytics.android.R |
||||
import net.pokeranalytics.android.model.interfaces.Editable |
||||
import net.pokeranalytics.android.model.realm.Session |
||||
import net.pokeranalytics.android.ui.activity.SessionActivity |
||||
import net.pokeranalytics.android.ui.adapter.HistorySessionRowRepresentableAdapter |
||||
import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource |
||||
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate |
||||
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment |
||||
import net.pokeranalytics.android.ui.view.RowRepresentable |
||||
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager |
||||
import net.pokeranalytics.android.util.Preferences |
||||
import java.text.SimpleDateFormat |
||||
import java.util.* |
||||
|
||||
class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource, RowRepresentableDelegate { |
||||
|
||||
companion object { |
||||
fun newInstance(): HistoryFragment { |
||||
val fragment = HistoryFragment() |
||||
val bundle = Bundle() |
||||
fragment.arguments = bundle |
||||
return fragment |
||||
} |
||||
} |
||||
|
||||
private lateinit var historyAdapter: HistorySessionRowRepresentableAdapter |
||||
|
||||
private lateinit var realmSessions: RealmResults<Session> |
||||
private val rows: ArrayList<RowRepresentable> = ArrayList() |
||||
private var newSessionCreated: Boolean = false |
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { |
||||
return inflater.inflate(R.layout.fragment_history, container, false) |
||||
} |
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
||||
super.onViewCreated(view, savedInstanceState) |
||||
initUI() |
||||
initData() |
||||
} |
||||
|
||||
override fun onDestroyView() { |
||||
super.onDestroyView() |
||||
realmSessions.removeAllChangeListeners() |
||||
} |
||||
|
||||
/** |
||||
* Init UI |
||||
*/ |
||||
private fun initUI() { |
||||
|
||||
disclaimerContainer.isVisible = Preferences.shouldShowDisclaimer(requireContext()) |
||||
|
||||
val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") |
||||
val betaLimitDate = sdf.parse("17/7/2019 10:00") |
||||
|
||||
newCashGame.setOnClickListener { |
||||
|
||||
if (Date().after(betaLimitDate)) { |
||||
this.showEndOfBetaMessage() |
||||
return@setOnClickListener |
||||
} |
||||
|
||||
SessionActivity.newInstance(requireContext(), false) |
||||
newSessionCreated = true |
||||
} |
||||
|
||||
newTournament.setOnClickListener { |
||||
|
||||
if (Date().after(betaLimitDate)) { |
||||
this.showEndOfBetaMessage() |
||||
return@setOnClickListener |
||||
} |
||||
|
||||
SessionActivity.newInstance(requireContext(), true) |
||||
newSessionCreated = true |
||||
} |
||||
|
||||
disclaimerDismiss.setOnClickListener { |
||||
Preferences.setStopShowingDisclaimer(requireContext()) |
||||
|
||||
disclaimerContainer.animate().translationY(disclaimerContainer.height.toFloat()) |
||||
.setInterpolator(FastOutSlowInInterpolator()) |
||||
.withEndAction { disclaimerContainer?.isVisible = false } |
||||
.start() |
||||
} |
||||
|
||||
} |
||||
|
||||
private fun showEndOfBetaMessage() { |
||||
Toast.makeText(context, "Beta has ended. Please update with the Google Play version", Toast.LENGTH_LONG).show() |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Init data |
||||
*/ |
||||
private fun initData() { |
||||
|
||||
this.realmSessions = getRealm().where<Session>().findAll().sort("startDate", Sort.DESCENDING) |
||||
this.realmSessions.addChangeListener { _, _ -> |
||||
this.historyAdapter.refreshData() |
||||
this.historyAdapter.notifyDataSetChanged() |
||||
} |
||||
|
||||
val startedSessions = getRealm().where<Session>().isNotNull("year").isNotNull("month").findAll().sort("startDate", Sort.DESCENDING) |
||||
val pendingSessions = getRealm().where<Session>().isNull("year").isNull("month").findAll().sort("startDate", Sort.DESCENDING) |
||||
val distinctDateSessions = getRealm().where<Session>().distinct("year", "month").findAll().sort("startDate", Sort.DESCENDING) |
||||
|
||||
this.historyAdapter = HistorySessionRowRepresentableAdapter(this, startedSessions, pendingSessions, distinctDateSessions) |
||||
|
||||
val viewManager = SmoothScrollLinearLayoutManager(requireContext()) |
||||
recyclerView.apply { |
||||
setHasFixedSize(true) |
||||
layoutManager = viewManager |
||||
adapter = historyAdapter |
||||
} |
||||
} |
||||
|
||||
override fun rowRepresentableForPosition(position: Int): RowRepresentable? { |
||||
return this.rows[position] |
||||
} |
||||
|
||||
override fun numberOfRows(): Int { |
||||
return this.rows.size |
||||
} |
||||
|
||||
override fun viewTypeForPosition(position: Int): Int { |
||||
return rows[position].viewType |
||||
} |
||||
|
||||
override fun indexForRow(row: RowRepresentable): Int { |
||||
return this.rows.indexOf(row) |
||||
} |
||||
|
||||
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { |
||||
SessionActivity.newInstance(requireContext(), sessionId = (row as Editable).id) |
||||
} |
||||
} |
||||
@ -0,0 +1,7 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:id="@+id/container" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent"> |
||||
|
||||
</FrameLayout> |
||||
@ -0,0 +1,132 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
xmlns:tools="http://schemas.android.com/tools" |
||||
android:id="@+id/container" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent"> |
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout |
||||
android:id="@+id/menuContainer" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:layout_gravity="center" |
||||
android:layout_marginEnd="16dp" |
||||
android:layout_marginBottom="72dp" |
||||
android:background="@android:color/transparent" |
||||
android:elevation="4dp" |
||||
android:orientation="vertical" |
||||
android:visibility="invisible" |
||||
app:layout_constraintBottom_toBottomOf="parent" |
||||
app:layout_constraintEnd_toEndOf="parent" |
||||
tools:visibility="visible"> |
||||
|
||||
<View |
||||
android:layout_width="0dp" |
||||
android:layout_height="0dp" |
||||
android:transitionName="newButtonTransition" |
||||
app:layout_constraintBottom_toBottomOf="parent" |
||||
app:layout_constraintEnd_toEndOf="parent" |
||||
android:background="@color/gray_darker" |
||||
app:layout_constraintStart_toStartOf="parent" |
||||
app:layout_constraintTop_toTopOf="parent" /> |
||||
|
||||
<LinearLayout |
||||
android:id="@+id/newCashGame" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="48dp" |
||||
android:layout_marginTop="8dp" |
||||
android:background="?selectableItemBackground" |
||||
android:gravity="center_vertical" |
||||
android:orientation="horizontal" |
||||
android:paddingStart="24dp" |
||||
android:paddingEnd="24dp" |
||||
app:layout_constraintEnd_toEndOf="parent" |
||||
app:layout_constraintStart_toStartOf="parent" |
||||
app:layout_constraintTop_toTopOf="parent"> |
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView |
||||
android:layout_width="32dp" |
||||
android:layout_height="32dp" |
||||
android:tint="@color/green" |
||||
app:layout_constraintStart_toStartOf="parent" |
||||
app:layout_constraintTop_toTopOf="parent" |
||||
app:srcCompat="@drawable/add_cash_game" /> |
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView |
||||
style="@style/PokerAnalyticsTheme.TextView.RowTitle" |
||||
android:layout_width="160dp" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginStart="20dp" |
||||
android:text="@string/new_cash_game" |
||||
app:layout_constraintEnd_toEndOf="parent" /> |
||||
|
||||
</LinearLayout> |
||||
|
||||
<LinearLayout |
||||
android:id="@+id/newTournament" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="48dp" |
||||
android:background="?selectableItemBackground" |
||||
android:gravity="center_vertical" |
||||
android:orientation="horizontal" |
||||
android:paddingStart="24dp" |
||||
android:paddingEnd="24dp" |
||||
app:layout_constraintEnd_toEndOf="parent" |
||||
app:layout_constraintStart_toStartOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/newCashGame"> |
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView |
||||
android:layout_width="32dp" |
||||
android:layout_height="32dp" |
||||
android:tint="@color/green" |
||||
app:layout_constraintStart_toStartOf="parent" |
||||
app:layout_constraintTop_toTopOf="parent" |
||||
app:srcCompat="@drawable/add_tournament" /> |
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView |
||||
style="@style/PokerAnalyticsTheme.TextView.RowTitle" |
||||
android:layout_width="160dp" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginStart="20dp" |
||||
android:text="@string/new_tournament" |
||||
app:layout_constraintEnd_toEndOf="parent" /> |
||||
|
||||
</LinearLayout> |
||||
|
||||
<LinearLayout |
||||
android:id="@+id/newTransaction" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="48dp" |
||||
android:layout_marginBottom="8dp" |
||||
android:background="?selectableItemBackground" |
||||
android:gravity="center_vertical" |
||||
android:orientation="horizontal" |
||||
android:paddingStart="24dp" |
||||
android:paddingEnd="24dp" |
||||
app:layout_constraintBottom_toBottomOf="parent" |
||||
app:layout_constraintEnd_toEndOf="parent" |
||||
app:layout_constraintStart_toStartOf="parent" |
||||
app:layout_constraintTop_toBottomOf="@+id/newTournament"> |
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView |
||||
android:layout_width="32dp" |
||||
android:layout_height="32dp" |
||||
android:tint="@color/green" |
||||
app:layout_constraintStart_toStartOf="parent" |
||||
app:layout_constraintTop_toTopOf="parent" |
||||
app:srcCompat="@drawable/add_transaction" /> |
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView |
||||
style="@style/PokerAnalyticsTheme.TextView.RowTitle" |
||||
android:layout_width="160dp" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginStart="20dp" |
||||
android:text="@string/new_operation" |
||||
app:layout_constraintEnd_toEndOf="parent" /> |
||||
|
||||
</LinearLayout> |
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout> |
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout> |
||||
@ -0,0 +1,56 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent"> |
||||
|
||||
<androidx.core.widget.NestedScrollView |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
android:fillViewport="true" |
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"> |
||||
|
||||
<FrameLayout |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content"> |
||||
|
||||
<androidx.recyclerview.widget.RecyclerView |
||||
android:id="@+id/recyclerView" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
android:clipToPadding="false" /> |
||||
|
||||
</FrameLayout> |
||||
|
||||
</androidx.core.widget.NestedScrollView> |
||||
|
||||
<com.google.android.material.appbar.AppBarLayout |
||||
android:id="@+id/appBar" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="128dp" |
||||
android:theme="@style/PokerAnalyticsTheme.Toolbar.Session"> |
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout |
||||
android:id="@+id/collapsingToolbar" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
app:collapsedTitleTextAppearance="@style/PokerAnalyticsTheme.Toolbar.CollapsedTitleAppearance" |
||||
app:contentScrim="?attr/colorPrimary" |
||||
app:expandedTitleGravity="bottom" |
||||
app:expandedTitleMarginStart="72dp" |
||||
app:expandedTitleTextAppearance="@style/PokerAnalyticsTheme.Toolbar.ExpandedTitleAppearance" |
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> |
||||
|
||||
<androidx.appcompat.widget.Toolbar |
||||
android:id="@+id/toolbar" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="?attr/actionBarSize" |
||||
app:layout_collapseMode="pin" |
||||
app:title="@string/bankroll" |
||||
app:titleTextColor="@color/white" /> |
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout> |
||||
|
||||
</com.google.android.material.appbar.AppBarLayout> |
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout> |
||||
@ -0,0 +1,11 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto"> |
||||
|
||||
<item |
||||
android:id="@+id/settings" |
||||
android:title="@string/services" |
||||
android:icon="@drawable/ic_outline_settings" |
||||
app:showAsAction="always" /> |
||||
|
||||
</menu> |
||||
Loading…
Reference in new issue