Adding new HH button linked to video test

hh
Laurent 6 years ago
parent 4fe79df786
commit 296b7942b0
  1. 4
      app/src/main/java/net/pokeranalytics/android/ui/activity/NewDataMenuActivity.kt
  2. 36
      app/src/main/java/net/pokeranalytics/android/ui/extensions/UIExtensions.kt
  3. 106
      app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt
  4. 35
      app/src/main/java/net/pokeranalytics/android/ui/view/handhistory/Circle.kt
  5. 53
      app/src/main/java/net/pokeranalytics/android/ui/view/handhistory/VideoView.kt
  6. 28
      app/src/main/java/net/pokeranalytics/android/util/video/MMediaMuxer.kt
  7. 34
      app/src/main/res/layout/activity_new_data.xml
  8. 12
      app/src/main/res/layout/view_video.xml

@ -79,6 +79,10 @@ class NewDataMenuActivity : BaseActivity() {
finishWithResult(2)
}
newHandHistory.setOnClickListener {
finishWithResult(3)
}
container.setOnClickListener {
hideMenu()
}

@ -11,6 +11,7 @@ import android.graphics.Color
import android.net.Uri
import android.util.TypedValue
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
@ -19,6 +20,7 @@ import androidx.appcompat.widget.SearchView
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import net.pokeranalytics.android.BuildConfig
@ -178,20 +180,28 @@ fun SearchView.removeMargins() {
}
fun View.toByteArray() : ByteArray {
val bitmap = this.convertToBitmap()
val stream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream)
return stream.toByteArray()
return this.convertToBitmap().toByteArray()
}
fun View.convertToBitmap(): Bitmap {
val measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
measure(measureSpec, measureSpec)
layout(0, 0, measuredWidth, measuredHeight)
val r = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)
r.eraseColor(Color.TRANSPARENT)
val canvas = Canvas(r)
draw(canvas)
return r
val b = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(b)
val background = this.background
this.background?.let {
background.draw(canvas)
} ?: run {
canvas.drawColor(Color.WHITE)
}
this.draw(canvas)
return b
}
fun ImageView.toByteArray() : ByteArray {
return this.drawable.toBitmap().toByteArray()
}
private fun Bitmap.toByteArray() : ByteArray {
val baos = ByteArrayOutputStream()
this.compress(Bitmap.CompressFormat.PNG, 100, baos)
return baos.toByteArray()
}

@ -26,14 +26,18 @@ import net.pokeranalytics.android.ui.activity.components.RequestCode
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.extensions.toByteArray
import net.pokeranalytics.android.ui.fragment.components.FilterableFragment
import net.pokeranalytics.android.ui.interfaces.FilterActivityRequestCode
import net.pokeranalytics.android.ui.interfaces.FilterableType
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager
import net.pokeranalytics.android.ui.view.handhistory.VideoView
import net.pokeranalytics.android.util.Preferences
import net.pokeranalytics.android.util.billing.AppGuard
import net.pokeranalytics.android.util.extensions.count
import net.pokeranalytics.android.util.video.MMediaMuxer
import timber.log.Timber
import java.text.SimpleDateFormat
import java.util.*
@ -70,9 +74,13 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
private var selectedTransaction: Transaction? = null
private var selectedTransactionPosition: Int = -1
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>, results: RealmResults<out RealmModel>) {
override fun entitiesChanged(
clazz: Class<out RealmModel>,
results: RealmResults<out RealmModel>
) {
super.entitiesChanged(clazz, results)
when (clazz.kotlin) {
@ -88,12 +96,20 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_feed, container, false)
}
override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
override fun onCreateContextMenu(
menu: ContextMenu?,
v: View?,
menuInfo: ContextMenu.ContextMenuInfo?
) {
super.onCreateContextMenu(menu, v, menuInfo)
if (v?.id == R.id.menuRecyclerView) {
@ -168,6 +184,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
0 -> createNewSession(false)
1 -> createNewSession(true)
2 -> createNewTransaction()
3 -> createNewHandHistory()
}
} else if (requestCode == RequestCode.FEED_TRANSACTION_DETAILS.value && resultCode == RESULT_OK && data != null) {
if (data.getStringExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName) != null) {
@ -175,7 +192,10 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
}
} else if (requestCode == FilterActivityRequestCode.CREATE_FILTER.ordinal && resultCode == RESULT_OK) {
data?.let {
this.saveFilter(this.requireContext(), it.getStringExtra(FiltersActivity.IntentKey.FILTER_ID.keyName))
this.saveFilter(
this.requireContext(),
it.getStringExtra(FiltersActivity.IntentKey.FILTER_ID.keyName)
)
}
} else if (requestCode == RequestCode.NEW_TRANSACTION.value && resultCode == RESULT_OK) {
this.selectTab(Tab.TRANSACTIONS)
@ -192,7 +212,10 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) {
when (row) {
is Session -> SessionActivity.newInstance(requireContext(), sessionId = (row as Editable).id)
is Session -> SessionActivity.newInstance(
requireContext(),
sessionId = (row as Editable).id
)
is Transaction -> {
selectedTransaction = row
selectedTransactionPosition = position
@ -215,7 +238,8 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
registerForContextMenu(this.menuRecyclerView)
val messageToShow: Preferences.FeedMessage? = Preferences.feedMessageToShow(requireContext())
val messageToShow: Preferences.FeedMessage? =
Preferences.feedMessageToShow(requireContext())
if (messageToShow != null) {
messageBox.isVisible = true
@ -322,7 +346,8 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
}
// Transactions
this.realmTransactions = transactionFilter?.results() ?: run { getRealm().where<Transaction>().findAll() }
this.realmTransactions =
transactionFilter?.results() ?: run { getRealm().where<Transaction>().findAll() }
this.realmTransactions = this.realmTransactions.sort("date", Sort.DESCENDING)
var distinctDateTransactions = transactionFilter?.results("year", "month") ?: run {
@ -330,14 +355,22 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
}
distinctDateTransactions = distinctDateTransactions.sort("date", Sort.DESCENDING)
this.feedTransactionAdapter =
FeedTransactionRowRepresentableAdapter(this, realmTransactions, distinctDateTransactions)
FeedTransactionRowRepresentableAdapter(
this,
realmTransactions,
distinctDateTransactions
)
}
/**
* Create a new cash game
*/
private fun createNewSession(isTournament: Boolean, sessionId: String? = null, duplicate: Boolean = false) {
private fun createNewSession(
isTournament: Boolean,
sessionId: String? = null,
duplicate: Boolean = false
) {
val sessionCount = getRealm().count(Session::class.java)
if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG
@ -374,7 +407,56 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
}
}
EditableDataActivity.newInstanceForResult(this, LiveData.TRANSACTION, null, RequestCode.NEW_TRANSACTION.value)
EditableDataActivity.newInstanceForResult(
this,
LiveData.TRANSACTION,
null,
RequestCode.NEW_TRANSACTION.value
)
}
/***
* Create a new hand history
*/
private fun createNewHandHistory() {
Timber.d("**** Start video test")
val testView = View(requireContext())
testView.setBackgroundColor(requireContext().getColor(R.color.blue))
testView.layoutParams = ViewGroup.LayoutParams(480, 480)
val videoView = VideoView(requireContext())
videoView.let {
val muxer = MMediaMuxer()
Timber.d("width = ${it.width}, height = ${it.height}")
val width = (it.width / 2) * 2
val height= (it.height / 2) * 2
muxer.Init(requireActivity(), width, height, "hhVideo", "YES!")
Timber.d("**** Adds frames")
for (i in 0..50) {
try {
val byteArray = it.toByteArray()
muxer.AddFrame(byteArray)
} catch (e: Exception) {
Timber.e("error = ${e.message}")
}
}
Timber.d("**** Create video")
muxer.CreateVideo()
val path = muxer.GetPath()
Timber.d("**** Video path = $path")
}
}
/**
@ -399,7 +481,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate {
).show()
}
// Filter Handler
// Filter Handler
override fun applyFilter() {
super.applyFilter()

@ -0,0 +1,35 @@
package net.pokeranalytics.android.ui.view.handhistory
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View
import net.pokeranalytics.android.R
class Circle(context: Context, attrs: AttributeSet) : View(context, attrs) {
companion object {
private val START_ANGLE_POINT = 270
private val STROKE_WIDTH = 40
}
private val paint: Paint = Paint()
private lateinit var rect: RectF
var angle: Float = 180.0f
init {
paint.isAntiAlias = true
paint.style = Paint.Style.STROKE
paint.strokeWidth = STROKE_WIDTH.toFloat()
paint.color = getContext().getColor(R.color.chart_selected_bar)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawArc(rect, START_ANGLE_POINT.toFloat(), angle, false, paint)
}
}

@ -0,0 +1,53 @@
package net.pokeranalytics.android.ui.view.handhistory
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import net.pokeranalytics.android.R
import timber.log.Timber
class VideoView : FrameLayout {
/**
* Constructors
*/
constructor(context: Context) : super(context) {
init()
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
init()
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init()
}
open fun getResourceLayout(): Int {
return R.layout.view_video
}
private lateinit var frameLayout: FrameLayout
/**
* Init
*/
private fun init() {
this.setBackgroundColor(context.getColor(R.color.blue))
val layoutInflater = LayoutInflater.from(context)
frameLayout = layoutInflater.inflate(getResourceLayout(), this, false) as FrameLayout
// val layoutParams = LayoutParams(480, 480)
val width = frameLayout.layoutParams.width
val height = frameLayout.layoutParams.height
Timber.d("W = $width, H = $height")
this.layoutParams = frameLayout.layoutParams
addView(frameLayout, frameLayout.layoutParams)
}
}

@ -9,6 +9,7 @@ import android.media.MediaCodecInfo.CodecCapabilities
import android.os.Environment
import android.os.Handler
import android.util.Log
import timber.log.Timber
import java.io.File
import java.io.IOException
import java.text.DateFormat
@ -203,7 +204,7 @@ class MMediaMuxer {
DateFormat.getDateTimeInstance().format(Date())
outputPath = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES),
"pixel$currentDateTimeString.mp4"
"pixel.mp4"
).toString()
mediaMuxer = MediaMuxer(outputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
} catch (ioe: IOException) {
@ -278,7 +279,7 @@ class MMediaMuxer {
mediaMuxer!!.stop()
mediaMuxer!!.release()
mediaMuxer = null
Logd("RELEASE MUXER")
Logd("RELEASE MUXER, path = ${outputPath}")
}
}
@ -310,21 +311,22 @@ class MMediaMuxer {
var index = 0
for (j in 0 until height) {
for (i in 0 until width) {
a = argb[index] and -0x1000000 shr 24 // a is not used obviously
R = argb[index] and 0xff0000 shr 16
G = argb[index] and 0xff00 shr 8
B = argb[index] and 0xff shr 0
Y = (66 * R + 129 * G + 25 * B + 128 shr 8) + 16
U = (-38 * R - 74 * G + 112 * B + 128 shr 8) + 128
V = (112 * R - 94 * G - 18 * B + 128 shr 8) + 128
yuv420sp[yIndex++] =
(if (Y < 0) 0 else if (Y > 255) 255 else Y).toByte()
yuv420sp[yIndex++] = (if (Y < 0) 0 else if (Y > 255) 255 else Y).toByte()
if (j % 2 == 0 && index % 2 == 0) {
yuv420sp[uvIndex++] =
(if (U < 0) 0 else if (U > 255) 255 else U).toByte()
yuv420sp[uvIndex++] =
(if (V < 0) 0 else if (V > 255) 255 else V).toByte()
yuv420sp[uvIndex++] = (if (U < 0) 0 else if (U > 255) 255 else U).toByte()
yuv420sp[uvIndex++] = (if (V < 0) 0 else if (V > 255) 255 else V).toByte()
}
index++
}
}
@ -411,13 +413,15 @@ class MMediaMuxer {
}
private fun Logd(Mess: String) {
if (DEBUG) {
Log.d(TAG, Mess)
}
Timber.d("$Mess")
// if (DEBUG) {
// Log.d(TAG, Mess)
// }
}
private fun Loge(Mess: String?) {
Log.e(TAG, Mess)
Timber.e("$Mess")
// Log.e(TAG, Mess)
}
}
}

@ -104,7 +104,6 @@
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingEnd="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newTournament">
@ -127,6 +126,39 @@
</LinearLayout>
<LinearLayout
android:id="@+id/newHandHistory"
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="16dp"
android:paddingEnd="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/newTransaction">
<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_hand" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/PokerAnalyticsTheme.TextView.RowTitle"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/new_hand"
app:layout_constraintEnd_toEndOf="parent" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<net.pokeranalytics.android.ui.view.handhistory.Circle
android:id="@+id/circle"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Loading…
Cancel
Save