diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Player.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Player.kt index 9298641c..7b7b2d95 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Player.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Player.kt @@ -74,6 +74,7 @@ open class Player : RealmObject(), NameManageable, Deletable, StaticRowRepresent when (row) { SimpleRow.NAME -> this.name = value as String? ?: "" PlayerRow.SUMMARY -> this.summary = value as String? ?: "" + PlayerRow.PLAYER_IMAGE -> this.picture = value as String? ?: "" } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt index f9d7bf2a..ef8ff085 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/EditableDataActivity.kt @@ -6,10 +6,12 @@ import android.os.Bundle import androidx.fragment.app.Fragment import net.pokeranalytics.android.R import net.pokeranalytics.android.model.LiveData -import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity +import net.pokeranalytics.android.ui.activity.components.MediaActivity import net.pokeranalytics.android.ui.fragment.data.* +import java.io.File +import java.util.* -class EditableDataActivity : PokerAnalyticsActivity() { +class EditableDataActivity : MediaActivity() { enum class IntentKey(val keyName: String) { DATA_TYPE("DATA_TYPE"), @@ -43,6 +45,8 @@ class EditableDataActivity : PokerAnalyticsActivity() { } + private var currentFragment: EditableDataFragment? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_editable_data) @@ -57,9 +61,7 @@ class EditableDataActivity : PokerAnalyticsActivity() { val dataType = intent.getIntExtra(IntentKey.DATA_TYPE.keyName, 0) val primaryKey = intent.getStringExtra(IntentKey.PRIMARY_KEY.keyName) - val fragmentManager = supportFragmentManager - val fragmentTransaction = fragmentManager.beginTransaction() - val fragment: EditableDataFragment = when (dataType) { + currentFragment = when (dataType) { LiveData.BANKROLL.ordinal -> BankrollDataFragment() LiveData.LOCATION.ordinal -> LocationDataFragment() LiveData.TRANSACTION.ordinal -> TransactionDataFragment() @@ -69,9 +71,24 @@ class EditableDataActivity : PokerAnalyticsActivity() { else -> EditableDataFragment() } - fragmentTransaction.add(R.id.container, fragment) - fragmentTransaction.commit() - fragment.setData(dataType, primaryKey) + currentFragment?.let { fragment -> + val fragmentManager = supportFragmentManager + val fragmentTransaction = fragmentManager.beginTransaction() + fragmentTransaction.add(R.id.container, fragment) + fragmentTransaction.commit() + fragment.setData(dataType, primaryKey) + } + + } + + override fun isLoadingNewPictures() { + super.isLoadingNewPictures() + currentFragment?.isLoadingNewPhotos() + } + + override fun getPictures(files: ArrayList) { + super.getPictures(files) + currentFragment?.getPhotos(files) } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/components/MediaActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/components/MediaActivity.kt index 76745e03..fad8328c 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/components/MediaActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/components/MediaActivity.kt @@ -6,14 +6,17 @@ import android.content.Intent import android.content.pm.PackageManager import android.graphics.Bitmap import android.net.Uri +import android.provider.MediaStore import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat +import androidx.core.content.FileProvider import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import net.pokeranalytics.android.util.ImageUtils import timber.log.Timber import java.io.File +import java.io.IOException import java.util.* @@ -30,10 +33,6 @@ open class MediaActivity : PokerAnalyticsActivity() { // Data - private val outputFileUri: Uri? = null - private val maxSampleWidth = 1024 - private val maxSampleHeight = 1024 - private val resizeImage = true private var tempFile: File? = null private var mCurrentPhotoPath: String? = null private var selectedChoice = -1 @@ -55,12 +54,20 @@ open class MediaActivity : PokerAnalyticsActivity() { val filesList = ArrayList() GlobalScope.launch { - if (data?.clipData != null) { + + if (tempFile != null) { + tempFile?.let { + GlobalScope.launch(Dispatchers.Main) { + filesList.add(it) + getPictures(filesList) + } + } + } else if (data?.clipData != null) { data?.clipData?.let { clipData -> try { GlobalScope.launch(Dispatchers.Main) { - isLoadingNewPhotos() + isLoadingNewPictures() } for (i in 0 until clipData.itemCount) { @@ -73,7 +80,7 @@ open class MediaActivity : PokerAnalyticsActivity() { } GlobalScope.launch(Dispatchers.Main) { - getPhotos(filesList) + getPictures(filesList) } } catch (e: Exception) { @@ -85,7 +92,7 @@ open class MediaActivity : PokerAnalyticsActivity() { try { GlobalScope.launch(Dispatchers.Main) { - isLoadingNewPhotos() + isLoadingNewPictures() } val inputStream = contentResolver.openInputStream(uri) @@ -93,7 +100,7 @@ open class MediaActivity : PokerAnalyticsActivity() { ImageUtils.copyInputStreamToFile(inputStream!!, photoFile) filesList.add(photoFile) GlobalScope.launch(Dispatchers.Main) { - getPhotos(filesList) + getPictures(filesList) } } catch (e: Exception) { @@ -120,8 +127,10 @@ open class MediaActivity : PokerAnalyticsActivity() { } when (selectedChoice) { + SELECTED_CHOICE_TAKE_PICTURE -> { + openImageCaptureIntent(multiplePictures) + } SELECTED_CHOICE_SELECT_PICTURE -> { - Timber.d("openImageGalleryIntent") openImageGalleryIntent(multiplePictures) } } @@ -129,6 +138,47 @@ open class MediaActivity : PokerAnalyticsActivity() { selectedChoice = -1 } + + /** + * Open the Camera Intent + */ + fun openImageCaptureIntent(multiplePictures: Boolean) { + + this.mCurrentPhotoPath = null + this.multiplePictures = multiplePictures + + // Test if we have the permission + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + selectedChoice = 0 + askForCameraPermission() + return + } + + val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) + // Ensure that there's a camera activity to handle the intent + if (takePictureIntent.resolveActivity(packageManager) != null) { + // Create the File where the photo should go + try { + tempFile = ImageUtils.createImageFile(this) + mCurrentPhotoPath = "file:" + tempFile?.absolutePath + } catch (ex: IOException) { + // Error occurred while creating the File + } + + // Continue only if the File was successfully created + if (tempFile != null) { + Timber.d("tempFile: ${tempFile?.absolutePath}") + val photoURI = FileProvider.getUriForFile( + this, + applicationContext.packageName + ".fileprovider", tempFile!! + ) + takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI) + startActivityForResult(takePictureIntent, REQUEST_CODE_TAKE_PICTURE) + } + } + } + + /** * Open the gallery intent */ @@ -193,7 +243,6 @@ open class MediaActivity : PokerAnalyticsActivity() { } } - /** * Called when a bitmap is return * @@ -205,11 +254,12 @@ open class MediaActivity : PokerAnalyticsActivity() { /** * Called when the user is adding new photos */ - open fun isLoadingNewPhotos() {} + open fun isLoadingNewPictures() {} /** * Called when the user has selected photos */ - open fun getPhotos(files: ArrayList) {} + open fun getPictures(files: ArrayList) {} + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/PokerAnalyticsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/PokerAnalyticsFragment.kt index 3bbf1d13..797ffeb1 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/PokerAnalyticsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/PokerAnalyticsFragment.kt @@ -7,11 +7,12 @@ import androidx.fragment.app.Fragment import com.crashlytics.android.Crashlytics import net.pokeranalytics.android.R import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity +import java.io.File open class PokerAnalyticsFragment : Fragment() { private var loaderDialogFragment: LoaderDialogFragment? = null - var parentActivity: PokerAnalyticsActivity? = null + open var parentActivity: PokerAnalyticsActivity? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -94,4 +95,14 @@ open class PokerAnalyticsFragment : Fragment() { parentActivity?.supportActionBar?.setDisplayHomeAsUpEnabled(enabled) } + /** + * Called when the user is adding new photos + */ + open fun isLoadingNewPhotos() {} + + /* + * Called when the user has selected photos + */ + open fun getPhotos(files: ArrayList) {} + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt index bbc9ec70..0416e7b8 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt @@ -16,6 +16,7 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment import net.pokeranalytics.android.ui.view.RowRepresentable +import java.io.File open class EditableDataFragment : DataManagerFragment(), RowRepresentableDelegate { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/PlayerDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/PlayerDataFragment.kt index b35d5534..fe825e84 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/PlayerDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/PlayerDataFragment.kt @@ -1,21 +1,23 @@ package net.pokeranalytics.android.ui.fragment.data +import android.app.AlertDialog import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import net.pokeranalytics.android.R import net.pokeranalytics.android.model.realm.Player +import net.pokeranalytics.android.ui.activity.components.MediaActivity import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource -import net.pokeranalytics.android.ui.extensions.toast import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor +import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.PlayerRow import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow import net.pokeranalytics.android.util.NULL_TEXT -import java.util.* +import java.io.File /** * Player data fragment @@ -27,18 +29,28 @@ class PlayerDataFragment : EditableDataFragment(), StaticRowRepresentableDataSou return this.item as Player } + private var mediaActivity: MediaActivity? = null + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(R.layout.fragment_player, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initUI() } + override fun getPhotos(files: ArrayList) { + super.getPhotos(files) + files.firstOrNull()?.let { picture -> + player.updateValue(picture.absolutePath, PlayerRow.PLAYER_IMAGE) + rowRepresentableAdapter.refreshRow(PlayerRow.PLAYER_IMAGE) + } + + } + override fun getDataSource(): RowRepresentableDataSource { return this } @@ -47,23 +59,22 @@ class PlayerDataFragment : EditableDataFragment(), StaticRowRepresentableDataSou return player.adapterRows() } + override fun viewTypeForPosition(position: Int): Int { + return when (position) { + 0 -> RowViewType.ROW_PLAYER_IMAGE.ordinal + else -> super.viewTypeForPosition(position) + } + } + + override fun rowRepresentableForPosition(position: Int): RowRepresentable? { + return when (position) { + 0 -> player + else -> super.rowRepresentableForPosition(position) + } + } + override fun stringForRow(row: RowRepresentable): String { return when (row) { - PlayerRow.PLAYER_IMAGE -> { - if (player.name.isNotEmpty()) { - val playerData = player.name.split(" ") - if (playerData.size > 1) { - playerData[0].first().toString() + playerData[1].first().toString() - } else if (player.name.length > 1) { - player.name.substring(0, 2) - } else { - player.name.substring(0, player.name.length) - } - } else { - NULL_TEXT - } - } - SimpleRow.NAME -> if (player.name.isNotEmpty()) player.name else NULL_TEXT PlayerRow.SUMMARY -> if (player.summary.isNotEmpty()) player.summary else NULL_TEXT else -> super.stringForRow(row) @@ -79,60 +90,57 @@ class PlayerDataFragment : EditableDataFragment(), StaticRowRepresentableDataSou } override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { - when(row) { + when (row) { PlayerRow.PLAYER_IMAGE -> { - toast("Yo.") + openPictureDialog() } PlayerRow.SUMMARY -> { val data = editDescriptors(row) BottomSheetFragment.create(fragmentManager, row, this, data, isClearable = false, isDeletable = true) } SimpleRow.NAME -> super.onRowSelected(position, row, fromAction) - } - } override fun onRowValueChanged(value: Any?, row: RowRepresentable) { super.onRowValueChanged(value, row) - when(row) { + when (row) { SimpleRow.NAME -> rowRepresentableAdapter.refreshRow(PlayerRow.PLAYER_IMAGE) } } - override fun onRowDeleted(row: RowRepresentable) { - super.onRowDeleted(row) - - } - /** * Init UI */ private fun initUI() { - /* - customField.updateRowRepresentation() - bottomBar.translationY = 72f.px - bottomBar.visibility = View.VISIBLE - */ - - /* - addItem.setOnClickListener { - val customFieldEntry = player.addEntry() - rowRepresentableAdapter.notifyDataSetChanged() - onRowSelected(-1, customFieldEntry) - } - */ + mediaActivity = parentActivity as MediaActivity? + } + + /** + * Open picture dialog + */ + private fun openPictureDialog() { + val builder = AlertDialog.Builder(requireContext()) - /* - updateUI() - rowRepresentableAdapter.notifyDataSetChanged() + val placesArray = ArrayList() + placesArray.add(getString(R.string.take_a_picture)) + placesArray.add(getString(R.string.library)) + placesArray.add(getString(R.string.select_a_color)) - if (!this.deleteButtonShouldAppear) { - rowRepresentableForPosition(0)?.let { - onRowSelected(0, it) + if (player.picture != null) { + placesArray.add(getString(R.string.remove_picture)) + } + + builder.setItems(placesArray.toTypedArray()) { dialog, which -> + when (which) { + 0 -> mediaActivity?.openImageCaptureIntent(false) + 1 -> mediaActivity?.openImageGalleryIntent(false) + 2 -> { + } + 3 -> player.updateValue(null, PlayerRow.PLAYER_IMAGE) } } - */ + builder.show() } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/PlayerImageView.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/PlayerImageView.kt new file mode 100644 index 00000000..5f73df53 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/PlayerImageView.kt @@ -0,0 +1,107 @@ +package net.pokeranalytics.android.ui.view + +import android.content.Context +import android.graphics.drawable.GradientDrawable +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.FrameLayout +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.content.res.ResourcesCompat +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade +import com.bumptech.glide.request.RequestOptions +import kotlinx.android.synthetic.main.view_player_image.view.* +import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.realm.Player +import net.pokeranalytics.android.ui.extensions.px +import net.pokeranalytics.android.util.NULL_TEXT + + +/** + * Display a row session + */ +class PlayerImageView : FrameLayout { + + private lateinit var playerImageView: ConstraintLayout + + private var onImageClickListener: OnClickListener? = null + + /** + * 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() + } + + /** + * Init + */ + private fun init() { + val layoutInflater = LayoutInflater.from(context) + playerImageView = layoutInflater.inflate(R.layout.view_player_image, this, false) as ConstraintLayout + val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) + addView(playerImageView, layoutParams) + } + + /** + * Set the session data to the view + */ + fun setPlayer(player: Player) { + + // Initial + val playerInitial = if (player.name.isNotEmpty()) { + val playerData = player.name.split(" ") + if (playerData.size > 1) { + playerData[0].first().toString() + playerData[1].first().toString() + } else if (player.name.length > 1) { + player.name.substring(0, 2) + } else { + player.name.substring(0, player.name.length) + } + } else { + NULL_TEXT + } + playerImageView.playerInitial.text = playerInitial + + // Picture + if (player.picture != null && player.picture?.isNotEmpty() == true) { + playerImageView.playerStroke.background = null + + Glide.with(this) + .load(player.picture) + .apply(RequestOptions().circleCrop()) + .transition(withCrossFade()) + .into(playerImageView.playerImage) + + } else { + playerImageView.playerStroke.background = ResourcesCompat.getDrawable(resources, R.drawable.circle_stroke_kaki, null) + } + + // Stroke + player.color?.let { + val drawable = playerImageView.playerStroke.background as GradientDrawable? + drawable?.setStroke(4.px, it) + } + + // Click listener + playerImageView.playerImageSelection.setOnClickListener { + onImageClickListener?.onClick(it) + } + } + + /** + * Set image click listener + */ + fun setOnImageClickListener(onImageClickListener: OnClickListener) { + this.onImageClickListener = onImageClickListener + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt index 32292164..f3d5dae1 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt @@ -27,6 +27,7 @@ import net.pokeranalytics.android.calculus.ComputedStat import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.bankroll.BankrollReport import net.pokeranalytics.android.model.realm.CustomField +import net.pokeranalytics.android.model.realm.Player import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter @@ -518,32 +519,17 @@ enum class RowViewType(private var layoutRes: Int) { } /** - * Display a transaction view + * Display a player image view */ inner class RowPlayerImageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) { - - itemView.findViewById(R.id.playerInitial)?.let { textView -> - textView.text = adapter.dataSource.stringForRow(row) - } - - itemView.findViewById(R.id.playerImage)?.let { imageView -> - } - - itemView.findViewById(R.id.playerImageSelection)?.let { imageView -> + itemView.findViewById(R.id.playerImageView)?.let { playerImageView -> val listener = View.OnClickListener { - adapter.delegate?.onRowSelected(position, row) + adapter.delegate?.onRowSelected(position, PlayerRow.PLAYER_IMAGE) } - imageView.setOnClickListener(listener) + playerImageView.setPlayer(row as Player) + playerImageView.setOnImageClickListener(listener) } - - /* - itemView.transactionRow.setData(row as Transaction) - val listener = View.OnClickListener { - adapter.delegate?.onRowSelected(position, row) - } - itemView.transactionRow.setOnClickListener(listener) - */ } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/PlayerRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/PlayerRow.kt index e20fd7c1..8c3c99c6 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/PlayerRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/PlayerRow.kt @@ -13,18 +13,6 @@ enum class PlayerRow : RowRepresentable { PLAYER_IMAGE, SUMMARY; - - companion object { - /** - * Return the report rows - */ - fun getRows(): ArrayList { - val rows = ArrayList() - rows.addAll(values()) - return rows - } - } - override val resId: Int? get() { return when (this) { diff --git a/app/src/main/res/layout/row_player_image.xml b/app/src/main/res/layout/row_player_image.xml index ad2c0a78..2a8a6c20 100644 --- a/app/src/main/res/layout/row_player_image.xml +++ b/app/src/main/res/layout/row_player_image.xml @@ -1,43 +1,17 @@ - - - - - + + + + + + + + + + + diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml index 45ed9d3f..ec836130 100644 --- a/app/src/main/res/xml/provider_paths.xml +++ b/app/src/main/res/xml/provider_paths.xml @@ -3,4 +3,7 @@ + + + \ No newline at end of file