Add UI improvements & media management features: Add custom T-shaped Tetris icon, implement swipe-to-delete for scores with undo functionality, add long-press media removal with confirmation dialog, fix notification repetition when switching tabs, add visual feedback for interactive elements
BIN
app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 184 KiB |
|
@ -4,6 +4,10 @@ import android.Manifest
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -17,11 +21,15 @@ import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
|
import androidx.core.graphics.drawable.DrawableCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.accidentalproductions.tetristats.databinding.FragmentHistoryBinding
|
import com.accidentalproductions.tetristats.databinding.FragmentHistoryBinding
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
@ -93,6 +101,8 @@ class HistoryFragment : Fragment(), ScoreAdapter.MediaAttachmentListener {
|
||||||
observeScores()
|
observeScores()
|
||||||
observeExportResult()
|
observeExportResult()
|
||||||
observeMediaSaveResult()
|
observeMediaSaveResult()
|
||||||
|
observeDeleteResult()
|
||||||
|
observeMediaRemoveResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
|
@ -100,6 +110,9 @@ class HistoryFragment : Fragment(), ScoreAdapter.MediaAttachmentListener {
|
||||||
binding.recyclerViewHistory.apply {
|
binding.recyclerViewHistory.apply {
|
||||||
adapter = scoreAdapter
|
adapter = scoreAdapter
|
||||||
layoutManager = LinearLayoutManager(context)
|
layoutManager = LinearLayoutManager(context)
|
||||||
|
|
||||||
|
// Add swipe to delete functionality
|
||||||
|
setupSwipeToDelete(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,15 +146,55 @@ class HistoryFragment : Fragment(), ScoreAdapter.MediaAttachmentListener {
|
||||||
when (result) {
|
when (result) {
|
||||||
is MediaSaveResult.Success -> {
|
is MediaSaveResult.Success -> {
|
||||||
Toast.makeText(context, "Media attached successfully", Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, "Media attached successfully", Toast.LENGTH_SHORT).show()
|
||||||
|
viewModel.clearMediaSaveResult()
|
||||||
}
|
}
|
||||||
is MediaSaveResult.Error -> {
|
is MediaSaveResult.Error -> {
|
||||||
Toast.makeText(context, "Failed to attach media: ${result.message}", Toast.LENGTH_LONG).show()
|
Toast.makeText(context, "Failed to attach media: ${result.message}", Toast.LENGTH_LONG).show()
|
||||||
|
viewModel.clearMediaSaveResult()
|
||||||
}
|
}
|
||||||
null -> { /* Ignore initial state */ }
|
null -> { /* Ignore initial state */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun observeDeleteResult() {
|
||||||
|
viewModel.deleteResult.observe(viewLifecycleOwner) { result ->
|
||||||
|
result?.let {
|
||||||
|
when (result) {
|
||||||
|
is DeleteResult.Success -> {
|
||||||
|
showUndoSnackbar(result.message)
|
||||||
|
viewModel.clearDeleteResult()
|
||||||
|
}
|
||||||
|
is DeleteResult.UndoSuccess -> {
|
||||||
|
Toast.makeText(context, result.message, Toast.LENGTH_SHORT).show()
|
||||||
|
viewModel.clearDeleteResult()
|
||||||
|
}
|
||||||
|
is DeleteResult.Error -> {
|
||||||
|
Toast.makeText(context, result.message, Toast.LENGTH_LONG).show()
|
||||||
|
viewModel.clearDeleteResult()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeMediaRemoveResult() {
|
||||||
|
viewModel.mediaRemoveResult.observe(viewLifecycleOwner) { result ->
|
||||||
|
result?.let {
|
||||||
|
when (result) {
|
||||||
|
is MediaRemoveResult.Success -> {
|
||||||
|
Toast.makeText(context, "Media removed", Toast.LENGTH_SHORT).show()
|
||||||
|
viewModel.clearMediaRemoveResult()
|
||||||
|
}
|
||||||
|
is MediaRemoveResult.Error -> {
|
||||||
|
Toast.makeText(context, "Failed to remove media: ${result.message}", Toast.LENGTH_LONG).show()
|
||||||
|
viewModel.clearMediaRemoveResult()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun shareExportedFile(uri: Uri) {
|
private fun shareExportedFile(uri: Uri) {
|
||||||
val shareIntent = Intent(Intent.ACTION_SEND).apply {
|
val shareIntent = Intent(Intent.ACTION_SEND).apply {
|
||||||
type = "text/csv"
|
type = "text/csv"
|
||||||
|
@ -153,6 +206,16 @@ class HistoryFragment : Fragment(), ScoreAdapter.MediaAttachmentListener {
|
||||||
startActivity(chooserIntent)
|
startActivity(chooserIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showUndoSnackbar(message: String) {
|
||||||
|
view?.let { view ->
|
||||||
|
val snackbar = Snackbar.make(view, message, Snackbar.LENGTH_LONG)
|
||||||
|
snackbar.setAction("UNDO") {
|
||||||
|
viewModel.undoDelete()
|
||||||
|
}
|
||||||
|
snackbar.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ScoreAdapter.MediaAttachmentListener implementation
|
// ScoreAdapter.MediaAttachmentListener implementation
|
||||||
override fun onAddMediaClicked(scoreId: Long) {
|
override fun onAddMediaClicked(scoreId: Long) {
|
||||||
currentScoreId = scoreId
|
currentScoreId = scoreId
|
||||||
|
@ -327,4 +390,101 @@ class HistoryFragment : Fragment(), ScoreAdapter.MediaAttachmentListener {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New ScoreAdapter.MediaAttachmentListener methods
|
||||||
|
override fun onRemoveMediaClicked(scoreId: Long) {
|
||||||
|
// Confirm media removal with a dialog
|
||||||
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setTitle("Remove Media")
|
||||||
|
.setMessage("Are you sure you want to remove the attached media?")
|
||||||
|
.setPositiveButton("Remove") { _, _ ->
|
||||||
|
viewModel.removeMedia(scoreId)
|
||||||
|
}
|
||||||
|
.setNegativeButton("Cancel", null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupSwipeToDelete(recyclerView: RecyclerView) {
|
||||||
|
val swipeCallback = object : ItemTouchHelper.SimpleCallback(
|
||||||
|
0, // No drag and drop
|
||||||
|
ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT // Swipe left or right
|
||||||
|
) {
|
||||||
|
private val deleteIcon = ContextCompat.getDrawable(requireContext(), android.R.drawable.ic_menu_delete)
|
||||||
|
private val background = ColorDrawable(Color.parseColor("#FF5252")) // Red background
|
||||||
|
private val backgroundPaint = Paint().apply { color = Color.parseColor("#FF5252") }
|
||||||
|
private val textPaint = Paint().apply {
|
||||||
|
color = Color.WHITE
|
||||||
|
textSize = 40f
|
||||||
|
textAlign = Paint.Align.CENTER
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMove(
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
|
target: RecyclerView.ViewHolder
|
||||||
|
): Boolean {
|
||||||
|
return false // We don't support moving items
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||||
|
val position = viewHolder.adapterPosition
|
||||||
|
val score = scoreAdapter.currentList[position]
|
||||||
|
// Delete the score
|
||||||
|
viewModel.deleteScore(score.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onChildDraw(
|
||||||
|
c: Canvas,
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
|
dX: Float,
|
||||||
|
dY: Float,
|
||||||
|
actionState: Int,
|
||||||
|
isCurrentlyActive: Boolean
|
||||||
|
) {
|
||||||
|
val itemView = viewHolder.itemView
|
||||||
|
val itemHeight = itemView.bottom - itemView.top
|
||||||
|
|
||||||
|
// Draw background
|
||||||
|
if (dX > 0) { // Swiping to the right
|
||||||
|
background.setBounds(itemView.left, itemView.top, itemView.left + dX.toInt(), itemView.bottom)
|
||||||
|
} else { // Swiping to the left
|
||||||
|
background.setBounds(itemView.right + dX.toInt(), itemView.top, itemView.right, itemView.bottom)
|
||||||
|
}
|
||||||
|
background.draw(c)
|
||||||
|
|
||||||
|
// Draw delete icon
|
||||||
|
deleteIcon?.let {
|
||||||
|
val iconMargin = (itemHeight - it.intrinsicHeight) / 2
|
||||||
|
val iconTop = itemView.top + (itemHeight - it.intrinsicHeight) / 2
|
||||||
|
val iconBottom = iconTop + it.intrinsicHeight
|
||||||
|
|
||||||
|
if (dX > 0) { // Swiping to the right
|
||||||
|
val iconLeft = itemView.left + iconMargin
|
||||||
|
val iconRight = iconLeft + it.intrinsicWidth
|
||||||
|
it.setBounds(iconLeft, iconTop, iconRight, iconBottom)
|
||||||
|
} else { // Swiping to the left
|
||||||
|
val iconRight = itemView.right - iconMargin
|
||||||
|
val iconLeft = iconRight - it.intrinsicWidth
|
||||||
|
it.setBounds(iconLeft, iconTop, iconRight, iconBottom)
|
||||||
|
}
|
||||||
|
DrawableCompat.setTint(it, Color.WHITE)
|
||||||
|
it.draw(c)
|
||||||
|
|
||||||
|
// Draw "Delete" text
|
||||||
|
val text = "Delete"
|
||||||
|
if (dX > 0) { // Swiping to the right
|
||||||
|
c.drawText(text, itemView.left + 120f, itemView.top + itemHeight / 2f + 15, textPaint)
|
||||||
|
} else { // Swiping to the left
|
||||||
|
c.drawText(text, itemView.right - 120f, itemView.top + itemHeight / 2f + 15, textPaint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach the swipe handler to the RecyclerView
|
||||||
|
ItemTouchHelper(swipeCallback).attachToRecyclerView(recyclerView)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -43,6 +43,17 @@ class HistoryViewModel(application: Application) : AndroidViewModel(application)
|
||||||
private val _mediaSaveResult = MutableLiveData<MediaSaveResult?>()
|
private val _mediaSaveResult = MutableLiveData<MediaSaveResult?>()
|
||||||
val mediaSaveResult: LiveData<MediaSaveResult?> = _mediaSaveResult
|
val mediaSaveResult: LiveData<MediaSaveResult?> = _mediaSaveResult
|
||||||
|
|
||||||
|
// For delete and undo functionality
|
||||||
|
private val _deleteResult = MutableLiveData<DeleteResult?>()
|
||||||
|
val deleteResult: LiveData<DeleteResult?> = _deleteResult
|
||||||
|
|
||||||
|
// Keep track of recently deleted score for undo
|
||||||
|
private var lastDeletedScore: Score? = null
|
||||||
|
|
||||||
|
// For media removal
|
||||||
|
private val _mediaRemoveResult = MutableLiveData<MediaRemoveResult?>()
|
||||||
|
val mediaRemoveResult: LiveData<MediaRemoveResult?> = _mediaRemoveResult
|
||||||
|
|
||||||
fun exportScoresToCsv() {
|
fun exportScoresToCsv() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
|
@ -195,6 +206,97 @@ class HistoryViewModel(application: Application) : AndroidViewModel(application)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun deleteScore(scoreId: Long) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
val score = getScoreById(scoreId)
|
||||||
|
if (score != null) {
|
||||||
|
// Store for potential undo
|
||||||
|
lastDeletedScore = score
|
||||||
|
|
||||||
|
// Delete from database
|
||||||
|
scoreDao.delete(score)
|
||||||
|
|
||||||
|
_deleteResult.postValue(DeleteResult.Success("Score deleted. Tap UNDO to restore."))
|
||||||
|
} else {
|
||||||
|
_deleteResult.postValue(DeleteResult.Error("Score not found"))
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
_deleteResult.postValue(DeleteResult.Error("Delete failed: ${e.message}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun undoDelete() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
lastDeletedScore?.let { score ->
|
||||||
|
// Reinsert the score
|
||||||
|
scoreDao.insert(score)
|
||||||
|
|
||||||
|
_deleteResult.postValue(DeleteResult.UndoSuccess("Score restored"))
|
||||||
|
|
||||||
|
// Clear the stored score
|
||||||
|
lastDeletedScore = null
|
||||||
|
} ?: run {
|
||||||
|
_deleteResult.postValue(DeleteResult.Error("No score to restore"))
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
_deleteResult.postValue(DeleteResult.Error("Restore failed: ${e.message}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeMedia(scoreId: Long) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
val score = getScoreById(scoreId)
|
||||||
|
if (score != null && score.mediaUri != null) {
|
||||||
|
// Store media URI for potential cleanup
|
||||||
|
val mediaUri = score.mediaUri
|
||||||
|
|
||||||
|
// Update score with null media
|
||||||
|
val updatedScore = score.copy(mediaUri = null)
|
||||||
|
updateScore(updatedScore)
|
||||||
|
|
||||||
|
// Try to delete the physical file if it's in our app storage
|
||||||
|
if (mediaUri.startsWith("content://") &&
|
||||||
|
mediaUri.contains(getApplication<Application>().packageName)) {
|
||||||
|
try {
|
||||||
|
val uriObj = Uri.parse(mediaUri)
|
||||||
|
val context = getApplication<Application>()
|
||||||
|
val contentResolver = context.contentResolver
|
||||||
|
contentResolver.delete(uriObj, null, null)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// Just log, don't fail the whole operation
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_mediaRemoveResult.postValue(MediaRemoveResult.Success)
|
||||||
|
} else {
|
||||||
|
_mediaRemoveResult.postValue(MediaRemoveResult.Error("Score not found or no media attached"))
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
_mediaRemoveResult.postValue(MediaRemoveResult.Error(e.message ?: "Unknown error"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods to clear LiveData after consumption
|
||||||
|
fun clearDeleteResult() {
|
||||||
|
_deleteResult.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearMediaSaveResult() {
|
||||||
|
_mediaSaveResult.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearMediaRemoveResult() {
|
||||||
|
_mediaRemoveResult.value = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class ExportResult {
|
sealed class ExportResult {
|
||||||
|
@ -207,6 +309,17 @@ sealed class MediaSaveResult {
|
||||||
data class Error(val message: String) : MediaSaveResult()
|
data class Error(val message: String) : MediaSaveResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class DeleteResult {
|
||||||
|
data class Success(val message: String) : DeleteResult()
|
||||||
|
data class UndoSuccess(val message: String) : DeleteResult()
|
||||||
|
data class Error(val message: String) : DeleteResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class MediaRemoveResult {
|
||||||
|
object Success : MediaRemoveResult()
|
||||||
|
data class Error(val message: String) : MediaRemoveResult()
|
||||||
|
}
|
||||||
|
|
||||||
class HistoryViewModelFactory(private val application: Application) : ViewModelProvider.Factory {
|
class HistoryViewModelFactory(private val application: Application) : ViewModelProvider.Factory {
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||||
if (modelClass.isAssignableFrom(HistoryViewModel::class.java)) {
|
if (modelClass.isAssignableFrom(HistoryViewModel::class.java)) {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import java.text.NumberFormat
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
|
||||||
class ScoreAdapter(private val mediaListener: MediaAttachmentListener? = null) :
|
class ScoreAdapter(private val mediaListener: MediaAttachmentListener? = null) :
|
||||||
ListAdapter<Score, ScoreAdapter.ScoreViewHolder>(ScoreDiffCallback()) {
|
ListAdapter<Score, ScoreAdapter.ScoreViewHolder>(ScoreDiffCallback()) {
|
||||||
|
@ -24,6 +25,7 @@ class ScoreAdapter(private val mediaListener: MediaAttachmentListener? = null) :
|
||||||
interface MediaAttachmentListener {
|
interface MediaAttachmentListener {
|
||||||
fun onAddMediaClicked(scoreId: Long)
|
fun onAddMediaClicked(scoreId: Long)
|
||||||
fun onMediaClicked(mediaUri: Uri, isVideo: Boolean)
|
fun onMediaClicked(mediaUri: Uri, isVideo: Boolean)
|
||||||
|
fun onRemoveMediaClicked(scoreId: Long)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ScoreViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ScoreViewHolder {
|
||||||
|
@ -79,7 +81,7 @@ class ScoreAdapter(private val mediaListener: MediaAttachmentListener? = null) :
|
||||||
binding.layoutLinesCleared.visibility = View.GONE
|
binding.layoutLinesCleared.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle media display
|
// Handle media display and options
|
||||||
setupMedia(score)
|
setupMedia(score)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +90,7 @@ class ScoreAdapter(private val mediaListener: MediaAttachmentListener? = null) :
|
||||||
// We have media to display
|
// We have media to display
|
||||||
binding.cardViewMedia.visibility = View.VISIBLE
|
binding.cardViewMedia.visibility = View.VISIBLE
|
||||||
binding.buttonAddMedia.visibility = View.GONE
|
binding.buttonAddMedia.visibility = View.GONE
|
||||||
|
binding.buttonRemoveMedia.visibility = View.GONE
|
||||||
|
|
||||||
val uri = score.mediaUri.toUri()
|
val uri = score.mediaUri.toUri()
|
||||||
val isVideo = score.mediaUri.endsWith(".mp4", ignoreCase = true) ||
|
val isVideo = score.mediaUri.endsWith(".mp4", ignoreCase = true) ||
|
||||||
|
@ -111,6 +114,12 @@ class ScoreAdapter(private val mediaListener: MediaAttachmentListener? = null) :
|
||||||
mediaListener?.onMediaClicked(uri, true)
|
mediaListener?.onMediaClicked(uri, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add long press listener for media deletion
|
||||||
|
binding.videoContainer.setOnLongClickListener {
|
||||||
|
showDeleteMediaDialog(score.id)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
retriever.release()
|
retriever.release()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
@ -128,6 +137,13 @@ class ScoreAdapter(private val mediaListener: MediaAttachmentListener? = null) :
|
||||||
binding.imageViewMedia.setOnClickListener {
|
binding.imageViewMedia.setOnClickListener {
|
||||||
mediaListener?.onMediaClicked(uri, false)
|
mediaListener?.onMediaClicked(uri, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add long press listener for media deletion
|
||||||
|
binding.imageViewMedia.setOnLongClickListener {
|
||||||
|
showDeleteMediaDialog(score.id)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
binding.cardViewMedia.visibility = View.GONE
|
binding.cardViewMedia.visibility = View.GONE
|
||||||
|
@ -138,6 +154,7 @@ class ScoreAdapter(private val mediaListener: MediaAttachmentListener? = null) :
|
||||||
// No media, show the add button
|
// No media, show the add button
|
||||||
binding.cardViewMedia.visibility = View.GONE
|
binding.cardViewMedia.visibility = View.GONE
|
||||||
binding.buttonAddMedia.visibility = View.VISIBLE
|
binding.buttonAddMedia.visibility = View.VISIBLE
|
||||||
|
binding.buttonRemoveMedia.visibility = View.GONE
|
||||||
|
|
||||||
// Set click listener to add media
|
// Set click listener to add media
|
||||||
binding.buttonAddMedia.setOnClickListener {
|
binding.buttonAddMedia.setOnClickListener {
|
||||||
|
@ -145,6 +162,19 @@ class ScoreAdapter(private val mediaListener: MediaAttachmentListener? = null) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showDeleteMediaDialog(scoreId: Long) {
|
||||||
|
val context = binding.root.context
|
||||||
|
// Create and show deletion popup
|
||||||
|
MaterialAlertDialogBuilder(context)
|
||||||
|
.setTitle("Remove Media")
|
||||||
|
.setMessage("Would you like to remove this media?")
|
||||||
|
.setPositiveButton("Remove") { _, _ ->
|
||||||
|
mediaListener?.onRemoveMediaClicked(scoreId)
|
||||||
|
}
|
||||||
|
.setNegativeButton("Cancel", null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 460 KiB |
|
@ -1,170 +1,74 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
|
android:width="108dp"
|
||||||
|
android:viewportHeight="108"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="108">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<path
|
<path android:fillColor="#3DDC84"
|
||||||
android:fillColor="#3DDC84"
|
|
||||||
android:pathData="M0,0h108v108h-108z"/>
|
android:pathData="M0,0h108v108h-108z"/>
|
||||||
<path
|
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
||||||
android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M9,0L9,108"
|
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
||||||
android:strokeWidth="0.8"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeColor="#33FFFFFF" />
|
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
||||||
<path
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:fillColor="#00000000"
|
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
||||||
android:pathData="M19,0L19,108"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeWidth="0.8"
|
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
||||||
android:strokeColor="#33FFFFFF" />
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path
|
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
||||||
android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M29,0L29,108"
|
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
||||||
android:strokeWidth="0.8"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeColor="#33FFFFFF" />
|
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
||||||
<path
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:fillColor="#00000000"
|
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
||||||
android:pathData="M39,0L39,108"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeWidth="0.8"
|
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
||||||
android:strokeColor="#33FFFFFF" />
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path
|
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
||||||
android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M49,0L49,108"
|
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
||||||
android:strokeWidth="0.8"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeColor="#33FFFFFF" />
|
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
||||||
<path
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:fillColor="#00000000"
|
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
||||||
android:pathData="M59,0L59,108"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeWidth="0.8"
|
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
||||||
android:strokeColor="#33FFFFFF" />
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path
|
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
||||||
android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M69,0L69,108"
|
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
||||||
android:strokeWidth="0.8"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeColor="#33FFFFFF" />
|
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
||||||
<path
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:fillColor="#00000000"
|
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
||||||
android:pathData="M79,0L79,108"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeWidth="0.8"
|
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
||||||
android:strokeColor="#33FFFFFF" />
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path
|
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
||||||
android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M89,0L89,108"
|
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
||||||
android:strokeWidth="0.8"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeColor="#33FFFFFF" />
|
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
||||||
<path
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:fillColor="#00000000"
|
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
||||||
android:pathData="M99,0L99,108"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeWidth="0.8"
|
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
||||||
android:strokeColor="#33FFFFFF" />
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path
|
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
||||||
android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M0,9L108,9"
|
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
||||||
android:strokeWidth="0.8"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeColor="#33FFFFFF" />
|
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
||||||
<path
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:fillColor="#00000000"
|
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
||||||
android:pathData="M0,19L108,19"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeWidth="0.8"
|
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
||||||
android:strokeColor="#33FFFFFF" />
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
<path
|
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
||||||
android:fillColor="#00000000"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:pathData="M0,29L108,29"
|
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
||||||
android:strokeWidth="0.8"
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,39L108,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,49L108,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,59L108,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,69L108,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,79L108,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,89L108,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,99L108,99"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,29L89,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,39L89,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,49L89,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,59L89,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,69L89,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,79L89,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,19L29,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,19L39,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,19L49,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,19L59,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,19L69,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,19L79,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
@ -1,44 +1,17 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="108">
|
android:viewportHeight="108">
|
||||||
|
|
||||||
<!-- Main T shape -->
|
<!-- Simplified T shape -->
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/tetris_turquoise"
|
android:fillColor="#7DD3DB"
|
||||||
android:pathData="M30,30h48v16h-16v32h-16v-32h-16z"/>
|
android:pathData="M36,36h36v12h-12v24h-12v-24h-12z" />
|
||||||
|
|
||||||
<!-- Border lines -->
|
<!-- Dark outline -->
|
||||||
<path
|
<path
|
||||||
android:strokeColor="@color/tetris_navy"
|
android:fillColor="#263238"
|
||||||
android:strokeWidth="2"
|
android:pathData="M36,36v12h12v24h12v-24h12v-12h-36zM37,37h34v10h-12v24h-10v-24h-12v-10z" />
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M30,30h48v16h-16v32h-16v-32h-16z"/>
|
|
||||||
|
|
||||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="85.84757"
|
|
||||||
android:endY="92.4963"
|
|
||||||
android:startX="42.9492"
|
|
||||||
android:startY="49.59793"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#44000000"
|
|
||||||
android:offset="0.0" />
|
|
||||||
<item
|
|
||||||
android:color="#00000000"
|
|
||||||
android:offset="1.0" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:fillType="nonZero"
|
|
||||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
|
||||||
android:strokeWidth="1"
|
|
||||||
android:strokeColor="#00000000" />
|
|
||||||
</vector>
|
</vector>
|
|
@ -118,13 +118,15 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:contentDescription="Score media" />
|
android:contentDescription="Score media"
|
||||||
|
android:foreground="?attr/selectableItemBackground" />
|
||||||
|
|
||||||
<!-- Video thumbnail with play indicator -->
|
<!-- Video thumbnail with play indicator -->
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/videoContainer"
|
android:id="@+id/videoContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:foreground="?attr/selectableItemBackground"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<VideoView
|
<VideoView
|
||||||
|
@ -148,16 +150,49 @@
|
||||||
android:alpha="0.7"
|
android:alpha="0.7"
|
||||||
android:contentDescription="Play video" />
|
android:contentDescription="Play video" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
<!-- Long press hint -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textHintLongPress"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:text="Long press to remove"
|
||||||
|
android:textSize="10sp"
|
||||||
|
android:textStyle="italic"
|
||||||
|
android:background="#80000000"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:layout_margin="4dp" />
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<!-- Media buttons layout -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<!-- Add media button -->
|
<!-- Add media button -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/buttonAddMedia"
|
android:id="@+id/buttonAddMedia"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Add Photo/Video"
|
android:text="Add Photo/Video"
|
||||||
app:icon="@android:drawable/ic_menu_camera"
|
app:icon="@android:drawable/ic_menu_camera"
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton" />
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton" />
|
||||||
|
|
||||||
|
<!-- Remove media button -->
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/buttonRemoveMedia"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Remove Media"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:icon="@android:drawable/ic_menu_close_clear_cancel"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton" />
|
||||||
|
</LinearLayout>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
|
||||||
</adaptive-icon>
|
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 982 B After Width: | Height: | Size: 2 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 5.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 9.2 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 14 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 21 KiB |
|
@ -19,4 +19,5 @@
|
||||||
<color name="teal_700">#48AAAA</color>
|
<color name="teal_700">#48AAAA</color>
|
||||||
<color name="black">#000000</color>
|
<color name="black">#000000</color>
|
||||||
<color name="white">#FFFFFF</color>
|
<color name="white">#FFFFFF</color>
|
||||||
|
<color name="ic_launcher_background">#F5C3C2</color>
|
||||||
</resources>
|
</resources>
|
|
@ -1,4 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<color name="ic_launcher_background">@color/tetris_pink</color>
|
|
||||||
</resources>
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<!-- Splash screen -->
|
<!-- Splash screen -->
|
||||||
<item name="android:windowSplashScreenBackground">@color/tetris_pink</item>
|
<item name="android:windowSplashScreenBackground">@color/tetris_pink</item>
|
||||||
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
|
<item name="android:windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>
|
||||||
<item name="android:windowSplashScreenIconBackgroundColor">@color/tetris_pink</item>
|
<item name="android:windowSplashScreenIconBackgroundColor">@color/tetris_pink</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|