Improved user profile image picking
This commit is contained in:
parent
607d1722da
commit
2c4b00edb9
7 changed files with 412 additions and 360 deletions
|
@ -183,4 +183,5 @@ dependencies {
|
||||||
implementation 'com.google.android.play:core:1.7.2'
|
implementation 'com.google.android.play:core:1.7.2'
|
||||||
implementation 'me.jorgecastillo:androidcolorx:0.2.0'
|
implementation 'me.jorgecastillo:androidcolorx:0.2.0'
|
||||||
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'
|
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'
|
||||||
|
implementation 'com.github.dhaval2404:imagepicker:1.7.1'
|
||||||
}
|
}
|
|
@ -1,38 +1,38 @@
|
||||||
package code.name.monkey.retromusic.activities
|
package code.name.monkey.retromusic.activities
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
|
||||||
import android.content.ContextWrapper
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.MediaStore.Images.Media
|
|
||||||
import android.provider.MediaStore.Images.Media.getBitmap
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
|
||||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||||
import code.name.monkey.appthemehelper.util.MaterialUtil
|
import code.name.monkey.appthemehelper.util.MaterialUtil
|
||||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
import code.name.monkey.retromusic.App
|
|
||||||
import code.name.monkey.retromusic.Constants.USER_BANNER
|
import code.name.monkey.retromusic.Constants.USER_BANNER
|
||||||
import code.name.monkey.retromusic.Constants.USER_PROFILE
|
import code.name.monkey.retromusic.Constants.USER_PROFILE
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
import code.name.monkey.retromusic.activities.base.AbsBaseActivity
|
||||||
|
import code.name.monkey.retromusic.extensions.accentColor
|
||||||
import code.name.monkey.retromusic.extensions.applyToolbar
|
import code.name.monkey.retromusic.extensions.applyToolbar
|
||||||
import code.name.monkey.retromusic.util.Compressor
|
import code.name.monkey.retromusic.glide.ProfileBannerGlideRequest
|
||||||
import code.name.monkey.retromusic.util.ImageUtil.getResizedBitmap
|
import code.name.monkey.retromusic.glide.UserProfileGlideRequest
|
||||||
|
import code.name.monkey.retromusic.util.ImageUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.bumptech.glide.Glide
|
||||||
import com.afollestad.materialdialogs.list.listItems
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
|
import com.bumptech.glide.request.RequestListener
|
||||||
|
import com.bumptech.glide.request.target.Target
|
||||||
|
import com.github.dhaval2404.imagepicker.ImagePicker
|
||||||
import kotlinx.android.synthetic.main.activity_user_info.*
|
import kotlinx.android.synthetic.main.activity_user_info.*
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.io.BufferedOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
@ -46,53 +46,19 @@ class UserInfoActivity : AbsBaseActivity() {
|
||||||
setNavigationbarColorAuto()
|
setNavigationbarColorAuto()
|
||||||
setTaskDescriptionColorAuto()
|
setTaskDescriptionColorAuto()
|
||||||
setLightNavigationBar(true)
|
setLightNavigationBar(true)
|
||||||
|
|
||||||
applyToolbar(toolbar)
|
applyToolbar(toolbar)
|
||||||
|
|
||||||
MaterialUtil.setTint(nameContainer, false)
|
MaterialUtil.setTint(nameContainer, false)
|
||||||
name.setText(PreferenceUtil.getInstance(this).userName)
|
name.setText(PreferenceUtil.getInstance(this).userName)
|
||||||
|
|
||||||
if (PreferenceUtil.getInstance(this).profileImage.isNotEmpty()) {
|
|
||||||
loadImageFromStorage(PreferenceUtil.getInstance(this).profileImage)
|
|
||||||
}
|
|
||||||
if (PreferenceUtil.getInstance(this).bannerImage.isNotEmpty()) {
|
|
||||||
loadBannerFromStorage(PreferenceUtil.getInstance(this).bannerImage)
|
|
||||||
}
|
|
||||||
userImage.setOnClickListener {
|
userImage.setOnClickListener {
|
||||||
MaterialDialog(this).show {
|
pickNewPhoto()
|
||||||
cornerRadius(PreferenceUtil.getInstance(this@UserInfoActivity).dialogCorner)
|
|
||||||
title(text = getString(R.string.set_photo))
|
|
||||||
listItems(
|
|
||||||
items = listOf(
|
|
||||||
getString(R.string.new_profile_photo),
|
|
||||||
getString(R.string.remove_profile_photo)
|
|
||||||
)
|
|
||||||
) { _, position, _ ->
|
|
||||||
when (position) {
|
|
||||||
0 -> pickNewPhoto()
|
|
||||||
1 -> PreferenceUtil.getInstance(this@UserInfoActivity).saveProfileImage("")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bannerSelect.setOnClickListener {
|
bannerSelect.setOnClickListener {
|
||||||
MaterialDialog(this).show {
|
selectBannerImage()
|
||||||
cornerRadius(PreferenceUtil.getInstance(this@UserInfoActivity).dialogCorner)
|
|
||||||
title(R.string.select_banner_photo)
|
|
||||||
listItems(
|
|
||||||
items = listOf(
|
|
||||||
getString(R.string.new_banner_photo),
|
|
||||||
getString(R.string.remove_banner_photo)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{ _, position, _ ->
|
|
||||||
when (position) {
|
|
||||||
0 -> selectBannerImage()
|
|
||||||
1 -> PreferenceUtil.getInstance(this@UserInfoActivity)
|
|
||||||
.setBannerImagePath("")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next.setOnClickListener {
|
next.setOnClickListener {
|
||||||
val nameString = name.text.toString().trim { it <= ' ' }
|
val nameString = name.text.toString().trim { it <= ' ' }
|
||||||
if (TextUtils.isEmpty(nameString)) {
|
if (TextUtils.isEmpty(nameString)) {
|
||||||
|
@ -103,17 +69,26 @@ class UserInfoActivity : AbsBaseActivity() {
|
||||||
setResult(Activity.RESULT_OK)
|
setResult(Activity.RESULT_OK)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
next.backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(this))
|
|
||||||
ColorStateList.valueOf(
|
val textColor =
|
||||||
MaterialValueHelper.getPrimaryTextColor(
|
MaterialValueHelper.getPrimaryTextColor(this, ColorUtil.isColorLight(accentColor()))
|
||||||
this,
|
next.backgroundTintList = ColorStateList.valueOf(accentColor())
|
||||||
ColorUtil.isColorLight(ThemeStore.accentColor(this))
|
next.iconTint = ColorStateList.valueOf(textColor)
|
||||||
)
|
next.setTextColor(textColor)
|
||||||
)
|
loadProfile()
|
||||||
.apply {
|
|
||||||
next.setTextColor(this)
|
|
||||||
next.iconTint = this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadProfile() {
|
||||||
|
bannerImage?.let {
|
||||||
|
ProfileBannerGlideRequest.Builder.from(
|
||||||
|
Glide.with(this),
|
||||||
|
ProfileBannerGlideRequest.getBannerModel()
|
||||||
|
).build().into(it)
|
||||||
|
}
|
||||||
|
UserProfileGlideRequest.Builder.from(
|
||||||
|
Glide.with(this),
|
||||||
|
UserProfileGlideRequest.getUserModel()
|
||||||
|
).build().into(userImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
@ -124,141 +99,138 @@ class UserInfoActivity : AbsBaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun selectBannerImage() {
|
private fun selectBannerImage() {
|
||||||
val pickImageIntent = Intent(Intent.ACTION_PICK, Media.EXTERNAL_CONTENT_URI)
|
ImagePicker.with(this)
|
||||||
pickImageIntent.type = "image/*"
|
.compress(1024)
|
||||||
//pickImageIntent.putExtra("crop", "true")
|
.crop(16f, 9f)
|
||||||
pickImageIntent.putExtra("outputX", 1290)
|
.start(PICK_BANNER_REQUEST)
|
||||||
pickImageIntent.putExtra("outputY", 720)
|
|
||||||
pickImageIntent.putExtra("aspectX", 16)
|
|
||||||
pickImageIntent.putExtra("aspectY", 9)
|
|
||||||
pickImageIntent.putExtra("scale", true)
|
|
||||||
//intent.setAction(Intent.ACTION_GET_CONTENT);
|
|
||||||
startActivityForResult(
|
|
||||||
Intent.createChooser(pickImageIntent, "Select Picture"),
|
|
||||||
PICK_BANNER_REQUEST
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pickNewPhoto() {
|
private fun pickNewPhoto() {
|
||||||
val pickImageIntent = Intent(Intent.ACTION_PICK, Media.EXTERNAL_CONTENT_URI)
|
ImagePicker.with(this)
|
||||||
pickImageIntent.type = "image/*"
|
.galleryOnly()
|
||||||
pickImageIntent.putExtra("crop", "true")
|
.cropSquare()
|
||||||
pickImageIntent.putExtra("outputX", 512)
|
.compress(1024)
|
||||||
pickImageIntent.putExtra("outputY", 512)
|
.start(PICK_IMAGE_REQUEST)
|
||||||
pickImageIntent.putExtra("aspectX", 1)
|
|
||||||
pickImageIntent.putExtra("aspectY", 1)
|
|
||||||
pickImageIntent.putExtra("scale", true)
|
|
||||||
startActivityForResult(
|
|
||||||
Intent.createChooser(pickImageIntent, "Select Picture"),
|
|
||||||
PICK_IMAGE_REQUEST
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
if (resultCode == Activity.RESULT_OK && requestCode == PICK_IMAGE_REQUEST) {
|
||||||
when (requestCode) {
|
val fileUri = data?.data
|
||||||
PICK_IMAGE_REQUEST -> {
|
fileUri?.let { setAndSaveUserImage(it) }
|
||||||
try {
|
} else if (resultCode == Activity.RESULT_OK && requestCode == PICK_BANNER_REQUEST) {
|
||||||
data.data?.let {
|
val fileUri = data?.data
|
||||||
val bitmap = getResizedBitmap(
|
fileUri?.let { setAndSaveBannerImage(it) }
|
||||||
getBitmap(contentResolver, it),
|
} else if (resultCode == ImagePicker.RESULT_ERROR) {
|
||||||
PROFILE_ICON_SIZE
|
Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
|
||||||
)
|
} else {
|
||||||
val profileImagePath = saveToInternalStorage(bitmap, USER_PROFILE)
|
Toast.makeText(this, "Task Cancelled", Toast.LENGTH_SHORT).show()
|
||||||
PreferenceUtil.getInstance(this).saveProfileImage(profileImagePath)
|
|
||||||
loadImageFromStorage(profileImagePath)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setAndSaveBannerImage(fileUri: Uri) {
|
||||||
|
Glide.with(this)
|
||||||
|
.load(fileUri)
|
||||||
|
.asBitmap()
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
.listener(object : RequestListener<Any, Bitmap> {
|
||||||
|
override fun onException(
|
||||||
|
e: java.lang.Exception?,
|
||||||
|
model: Any?,
|
||||||
|
target: Target<Bitmap>?,
|
||||||
|
isFirstResource: Boolean
|
||||||
|
): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResourceReady(
|
||||||
|
resource: Bitmap?,
|
||||||
|
model: Any?,
|
||||||
|
target: Target<Bitmap>?,
|
||||||
|
isFromMemoryCache: Boolean,
|
||||||
|
isFirstResource: Boolean
|
||||||
|
): Boolean {
|
||||||
|
resource?.let { saveBannerImage(it) }
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.into(bannerImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveBannerImage(bitmap: Bitmap) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch() {
|
||||||
|
val appDir = applicationContext.filesDir
|
||||||
|
val file = File(appDir, USER_BANNER)
|
||||||
|
var successful = false
|
||||||
|
try {
|
||||||
|
val os = BufferedOutputStream(FileOutputStream(file))
|
||||||
|
successful = ImageUtil.resizeBitmap(bitmap, 2048)
|
||||||
|
.compress(Bitmap.CompressFormat.WEBP, 100, os)
|
||||||
|
os.close()
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
if (successful) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
Toast.makeText(this@UserInfoActivity, "Done", Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
PICK_BANNER_REQUEST -> {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setAndSaveUserImage(fileUri: Uri) {
|
||||||
|
Glide.with(this)
|
||||||
|
.load(fileUri)
|
||||||
|
.asBitmap()
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
.listener(object : RequestListener<Any, Bitmap> {
|
||||||
|
override fun onException(
|
||||||
|
e: java.lang.Exception?,
|
||||||
|
model: Any?,
|
||||||
|
target: Target<Bitmap>?,
|
||||||
|
isFirstResource: Boolean
|
||||||
|
): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResourceReady(
|
||||||
|
resource: Bitmap?,
|
||||||
|
model: Any?,
|
||||||
|
target: Target<Bitmap>?,
|
||||||
|
isFromMemoryCache: Boolean,
|
||||||
|
isFirstResource: Boolean
|
||||||
|
): Boolean {
|
||||||
|
resource?.let { saveImage(it) }
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.into(userImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveImage(bitmap: Bitmap) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch() {
|
||||||
|
val appDir = applicationContext.filesDir
|
||||||
|
val file = File(appDir, USER_PROFILE)
|
||||||
|
var successful = false
|
||||||
try {
|
try {
|
||||||
data.data?.let {
|
val os = BufferedOutputStream(FileOutputStream(file))
|
||||||
val bitmap = getBitmap(contentResolver, it)
|
successful = ImageUtil.resizeBitmap(bitmap, 2048)
|
||||||
val profileImagePath = saveToInternalStorage(bitmap, USER_BANNER)
|
.compress(Bitmap.CompressFormat.WEBP, 100, os)
|
||||||
PreferenceUtil.getInstance(this).setBannerImagePath(profileImagePath)
|
os.close()
|
||||||
loadBannerFromStorage(profileImagePath)
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
if (successful) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
Toast.makeText(this@UserInfoActivity, "Done", Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getImagePath(aUri: Uri, aSelection: String?): String? {
|
|
||||||
var path: String? = null
|
|
||||||
val cursor = App.getContext().contentResolver.query(aUri, null, aSelection, null, null)
|
|
||||||
if (cursor != null) {
|
|
||||||
if (cursor.moveToFirst()) {
|
|
||||||
path = cursor.getString(cursor.getColumnIndex(Media.DATA))
|
|
||||||
}
|
|
||||||
cursor.close()
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadBannerFromStorage(profileImagePath: String) {
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
val bitmap = Compressor(this@UserInfoActivity).setQuality(100)
|
|
||||||
.setCompressFormat(Bitmap.CompressFormat.WEBP)
|
|
||||||
.compressToBitmap(File(profileImagePath, USER_BANNER))
|
|
||||||
withContext(Dispatchers.Main) { bannerImage.setImageBitmap(bitmap) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadImageFromStorage(path: String) {
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
val bitmap = Compressor(this@UserInfoActivity)
|
|
||||||
.setMaxHeight(300)
|
|
||||||
.setMaxWidth(300)
|
|
||||||
.setQuality(75)
|
|
||||||
.setCompressFormat(Bitmap.CompressFormat.WEBP)
|
|
||||||
.compressToBitmap(File(path, USER_PROFILE))
|
|
||||||
withContext(Dispatchers.Main) { userImage.setImageBitmap(bitmap) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun saveToInternalStorage(bitmapImage: Bitmap, userBanner: String): String {
|
|
||||||
val cw = ContextWrapper(this)
|
|
||||||
val directory = cw.getDir("imageDir", Context.MODE_PRIVATE)
|
|
||||||
val myPath = File(directory, userBanner)
|
|
||||||
var fos: FileOutputStream? = null
|
|
||||||
try {
|
|
||||||
fos = FileOutputStream(myPath)
|
|
||||||
// Use the compress method on the BitMap object to write image to the OutputStream
|
|
||||||
bitmapImage.compress(Bitmap.CompressFormat.WEBP, 100, fos)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
fos?.close()
|
|
||||||
} catch (e: IOException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return directory.absolutePath
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val PICK_IMAGE_REQUEST = 9002
|
private const val PICK_IMAGE_REQUEST = 9002
|
||||||
private const val PICK_BANNER_REQUEST = 9004
|
private const val PICK_BANNER_REQUEST = 9004
|
||||||
private const val PROFILE_ICON_SIZE = 400
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Activity.pickImage(requestCode: Int) {
|
|
||||||
Intent(Intent.ACTION_GET_CONTENT).apply {
|
|
||||||
addCategory(Intent.CATEGORY_OPENABLE)
|
|
||||||
type = "image/*"
|
|
||||||
startActivityForResult(this, requestCode)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,13 +22,11 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import code.name.monkey.appthemehelper.ThemeStore
|
|
||||||
import code.name.monkey.appthemehelper.util.TintHelper
|
|
||||||
import code.name.monkey.retromusic.Constants
|
|
||||||
import code.name.monkey.retromusic.Constants.USER_BANNER
|
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.adapter.HomeAdapter
|
import code.name.monkey.retromusic.adapter.HomeAdapter
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
||||||
|
import code.name.monkey.retromusic.glide.ProfileBannerGlideRequest
|
||||||
|
import code.name.monkey.retromusic.glide.UserProfileGlideRequest
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
|
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
|
||||||
import code.name.monkey.retromusic.loaders.SongLoader
|
import code.name.monkey.retromusic.loaders.SongLoader
|
||||||
|
@ -38,12 +36,9 @@ import code.name.monkey.retromusic.model.smartplaylist.MyTopTracksPlaylist
|
||||||
import code.name.monkey.retromusic.util.NavigationUtil
|
import code.name.monkey.retromusic.util.NavigationUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
|
||||||
import kotlinx.android.synthetic.main.abs_playlists.*
|
import kotlinx.android.synthetic.main.abs_playlists.*
|
||||||
import kotlinx.android.synthetic.main.fragment_banner_home.*
|
import kotlinx.android.synthetic.main.fragment_banner_home.*
|
||||||
import kotlinx.android.synthetic.main.home_content.*
|
import kotlinx.android.synthetic.main.home_content.*
|
||||||
import java.io.File
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallbacks {
|
class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallbacks {
|
||||||
|
|
||||||
|
@ -63,31 +58,10 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadImageFromStorage() {
|
private fun loadImageFromStorage() {
|
||||||
Glide.with(requireContext())
|
UserProfileGlideRequest.Builder.from(
|
||||||
.load(
|
Glide.with(requireActivity()),
|
||||||
File(
|
UserProfileGlideRequest.getUserModel()
|
||||||
PreferenceUtil.getInstance(requireContext()).profileImage,
|
).build().into(userImage)
|
||||||
Constants.USER_PROFILE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.asBitmap()
|
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
|
||||||
.skipMemoryCache(true)
|
|
||||||
.placeholder(
|
|
||||||
TintHelper.createTintedDrawable(
|
|
||||||
requireContext(),
|
|
||||||
R.drawable.ic_account_white_24dp,
|
|
||||||
ThemeStore.accentColor(requireContext())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.error(
|
|
||||||
TintHelper.createTintedDrawable(
|
|
||||||
requireContext(),
|
|
||||||
R.drawable.ic_account_white_24dp,
|
|
||||||
ThemeStore.accentColor(requireContext())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.into(userImage)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val displayMetrics: DisplayMetrics
|
private val displayMetrics: DisplayMetrics
|
||||||
|
@ -151,58 +125,24 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
|
||||||
homeModel.sections.observe(viewLifecycleOwner, androidx.lifecycle.Observer { sections ->
|
homeModel.sections.observe(viewLifecycleOwner, androidx.lifecycle.Observer { sections ->
|
||||||
homeAdapter.swapData(sections)
|
homeAdapter.swapData(sections)
|
||||||
})
|
})
|
||||||
|
loadProfile()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleBackPress(): Boolean {
|
override fun handleBackPress(): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
private fun loadProfile() {
|
||||||
super.onResume()
|
|
||||||
getTimeOfTheDay()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getTimeOfTheDay() {
|
|
||||||
val calendar = Calendar.getInstance()
|
|
||||||
val timeOfDay = calendar.get(Calendar.HOUR_OF_DAY)
|
|
||||||
var images = arrayOf<String>()
|
|
||||||
when (timeOfDay) {
|
|
||||||
in 0..5 -> images = resources.getStringArray(R.array.night)
|
|
||||||
in 6..11 -> images = resources.getStringArray(R.array.morning)
|
|
||||||
in 12..15 -> images = resources.getStringArray(R.array.after_noon)
|
|
||||||
in 16..19 -> images = resources.getStringArray(R.array.evening)
|
|
||||||
in 20..23 -> images = resources.getStringArray(R.array.night)
|
|
||||||
}
|
|
||||||
val day = images[Random().nextInt(images.size)]
|
|
||||||
loadTimeImage(day)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadTimeImage(day: String) {
|
|
||||||
bannerImage?.let {
|
bannerImage?.let {
|
||||||
val request = Glide.with(requireContext())
|
ProfileBannerGlideRequest.Builder.from(
|
||||||
if (PreferenceUtil.getInstance(requireContext()).bannerImage.isEmpty()) {
|
Glide.with(requireContext()),
|
||||||
request.load(day)
|
ProfileBannerGlideRequest.getBannerModel()
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
).build().into(it)
|
||||||
.skipMemoryCache(true)
|
|
||||||
.placeholder(R.drawable.material_design_default)
|
|
||||||
.error(R.drawable.material_design_default)
|
|
||||||
.into(it)
|
|
||||||
} else {
|
|
||||||
request.load(
|
|
||||||
File(
|
|
||||||
PreferenceUtil.getInstance(requireContext()).bannerImage,
|
|
||||||
USER_BANNER
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.asBitmap()
|
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
|
||||||
.skipMemoryCache(true)
|
|
||||||
.placeholder(R.drawable.material_design_default)
|
|
||||||
.error(R.drawable.material_design_default)
|
|
||||||
.into(it)
|
|
||||||
}
|
}
|
||||||
}
|
UserProfileGlideRequest.Builder.from(
|
||||||
loadImageFromStorage()
|
Glide.with(requireActivity()),
|
||||||
|
UserProfileGlideRequest.getUserModel()
|
||||||
|
).build().into(userImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
package code.name.monkey.retromusic.glide;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.bumptech.glide.BitmapRequestBuilder;
|
||||||
|
import com.bumptech.glide.BitmapTypeRequest;
|
||||||
|
import com.bumptech.glide.RequestManager;
|
||||||
|
import com.bumptech.glide.load.Key;
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
import com.bumptech.glide.signature.MediaStoreSignature;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import code.name.monkey.retromusic.App;
|
||||||
|
import code.name.monkey.retromusic.R;
|
||||||
|
|
||||||
|
import static code.name.monkey.retromusic.Constants.USER_BANNER;
|
||||||
|
|
||||||
|
public class ProfileBannerGlideRequest {
|
||||||
|
private static final DiskCacheStrategy DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.NONE;
|
||||||
|
private static final int DEFAULT_ERROR_IMAGE = R.drawable.material_design_default;
|
||||||
|
private static final int DEFAULT_ANIMATION = android.R.anim.fade_in;
|
||||||
|
|
||||||
|
public static File getBannerModel() {
|
||||||
|
File dir = App.Companion.getContext().getFilesDir();
|
||||||
|
return new File(dir, USER_BANNER);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BitmapTypeRequest<File> createBaseRequest(RequestManager requestManager, File profile) {
|
||||||
|
return requestManager.load(profile).asBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Key createSignature(File file) {
|
||||||
|
return new MediaStoreSignature("", file.lastModified(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private RequestManager requestManager;
|
||||||
|
private File profile;
|
||||||
|
|
||||||
|
private Builder(RequestManager requestManager, File profile) {
|
||||||
|
this.requestManager = requestManager;
|
||||||
|
this.profile = profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder from(@NonNull RequestManager requestManager, File profile) {
|
||||||
|
return new Builder(requestManager, profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public BitmapRequestBuilder<File, Bitmap> build() {
|
||||||
|
//noinspection unchecked
|
||||||
|
return createBaseRequest(requestManager, profile)
|
||||||
|
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||||
|
.placeholder(DEFAULT_ERROR_IMAGE)
|
||||||
|
.animate(DEFAULT_ANIMATION)
|
||||||
|
.signature(createSignature(profile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BitmapBuilder {
|
||||||
|
private final Builder builder;
|
||||||
|
|
||||||
|
BitmapBuilder(Builder builder) {
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitmapRequestBuilder<?, Bitmap> build() {
|
||||||
|
//noinspection unchecked
|
||||||
|
return createBaseRequest(builder.requestManager, builder.profile)
|
||||||
|
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||||
|
.error(DEFAULT_ERROR_IMAGE)
|
||||||
|
.animate(DEFAULT_ANIMATION)
|
||||||
|
.signature(createSignature(builder.profile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package code.name.monkey.retromusic.glide;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.bumptech.glide.BitmapRequestBuilder;
|
||||||
|
import com.bumptech.glide.BitmapTypeRequest;
|
||||||
|
import com.bumptech.glide.RequestManager;
|
||||||
|
import com.bumptech.glide.load.Key;
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
import com.bumptech.glide.signature.MediaStoreSignature;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import code.name.monkey.retromusic.App;
|
||||||
|
import code.name.monkey.retromusic.R;
|
||||||
|
|
||||||
|
import static code.name.monkey.retromusic.Constants.USER_PROFILE;
|
||||||
|
|
||||||
|
public class UserProfileGlideRequest {
|
||||||
|
private static final DiskCacheStrategy DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.NONE;
|
||||||
|
private static final int DEFAULT_ERROR_IMAGE = R.drawable.ic_account_white_24dp;
|
||||||
|
private static final int DEFAULT_ANIMATION = android.R.anim.fade_in;
|
||||||
|
|
||||||
|
public static File getUserModel() {
|
||||||
|
File dir = App.Companion.getContext().getFilesDir();
|
||||||
|
return new File(dir, USER_PROFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BitmapTypeRequest<File> createBaseRequest(RequestManager requestManager, File profile) {
|
||||||
|
return requestManager.load(profile).asBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Key createSignature(File file) {
|
||||||
|
return new MediaStoreSignature("", file.lastModified(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private RequestManager requestManager;
|
||||||
|
private File profile;
|
||||||
|
|
||||||
|
private Builder(RequestManager requestManager, File profile) {
|
||||||
|
this.requestManager = requestManager;
|
||||||
|
this.profile = profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder from(@NonNull RequestManager requestManager, File profile) {
|
||||||
|
return new Builder(requestManager, profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public BitmapRequestBuilder<File, Bitmap> build() {
|
||||||
|
//noinspection unchecked
|
||||||
|
return createBaseRequest(requestManager, profile)
|
||||||
|
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||||
|
.placeholder(DEFAULT_ERROR_IMAGE)
|
||||||
|
.animate(DEFAULT_ANIMATION)
|
||||||
|
.signature(createSignature(profile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BitmapBuilder {
|
||||||
|
private final Builder builder;
|
||||||
|
|
||||||
|
BitmapBuilder(Builder builder) {
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitmapRequestBuilder<?, Bitmap> build() {
|
||||||
|
//noinspection unchecked
|
||||||
|
return createBaseRequest(builder.requestManager, builder.profile)
|
||||||
|
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||||
|
.error(DEFAULT_ERROR_IMAGE)
|
||||||
|
.animate(DEFAULT_ANIMATION)
|
||||||
|
.signature(createSignature(builder.profile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -67,11 +67,8 @@ import static code.name.monkey.retromusic.helper.SortOrder.SongSortOrder;
|
||||||
public final class PreferenceUtil {
|
public final class PreferenceUtil {
|
||||||
|
|
||||||
public static final String LIBRARY_CATEGORIES = "library_categories";
|
public static final String LIBRARY_CATEGORIES = "library_categories";
|
||||||
|
|
||||||
public static final String EXTRA_SONG_INFO = "extra_song_info";
|
public static final String EXTRA_SONG_INFO = "extra_song_info";
|
||||||
|
|
||||||
public static final String DESATURATED_COLOR = "desaturated_color";
|
public static final String DESATURATED_COLOR = "desaturated_color";
|
||||||
|
|
||||||
public static final String BLACK_THEME = "black_theme";
|
public static final String BLACK_THEME = "black_theme";
|
||||||
public static final String KEEP_SCREEN_ON = "keep_screen_on";
|
public static final String KEEP_SCREEN_ON = "keep_screen_on";
|
||||||
public static final String TOGGLE_HOME_BANNER = "toggle_home_banner";
|
public static final String TOGGLE_HOME_BANNER = "toggle_home_banner";
|
||||||
|
@ -549,9 +546,6 @@ public final class PreferenceUtil {
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getProfileImage() {
|
|
||||||
return mPreferences.getString(PROFILE_IMAGE_PATH, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public final String getSAFSDCardUri() {
|
public final String getSAFSDCardUri() {
|
||||||
return mPreferences.getString(SAF_SDCARD_URI, "");
|
return mPreferences.getString(SAF_SDCARD_URI, "");
|
||||||
|
@ -700,11 +694,6 @@ public final class PreferenceUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void saveProfileImage(String profileImagePath) {
|
|
||||||
mPreferences.edit().putString(PROFILE_IMAGE_PATH, profileImagePath).apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setAlbumGridSize(final int gridSize) {
|
public void setAlbumGridSize(final int gridSize) {
|
||||||
final SharedPreferences.Editor editor = mPreferences.edit();
|
final SharedPreferences.Editor editor = mPreferences.edit();
|
||||||
editor.putInt(ALBUM_GRID_SIZE, gridSize);
|
editor.putInt(ALBUM_GRID_SIZE, gridSize);
|
||||||
|
|
|
@ -23,26 +23,19 @@
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical"
|
||||||
|
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:id="@+id/imageContainer"
|
android:id="@+id/imageContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_margin="16dp"
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
app:cardCornerRadius="12dp"
|
app:cardCornerRadius="12dp"
|
||||||
app:cardUseCompatPadding="true"
|
app:cardElevation="8dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
@ -72,7 +65,6 @@
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
app:srcCompat="@drawable/ic_add_photo_white_24dp" />
|
app:srcCompat="@drawable/ic_add_photo_white_24dp" />
|
||||||
|
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
@ -85,6 +77,7 @@
|
||||||
android:elevation="8dp"
|
android:elevation="8dp"
|
||||||
android:transitionName="@string/transition_user_image"
|
android:transitionName="@string/transition_user_image"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/imageContainer"
|
app:layout_constraintBottom_toBottomOf="@id/imageContainer"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/imageContainer"
|
||||||
app:layout_constraintStart_toStartOf="@+id/imageContainer"
|
app:layout_constraintStart_toStartOf="@+id/imageContainer"
|
||||||
app:layout_constraintTop_toBottomOf="@id/imageContainer">
|
app:layout_constraintTop_toBottomOf="@id/imageContainer">
|
||||||
|
|
||||||
|
@ -116,7 +109,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
app:hintAnimationEnabled="true"
|
app:hintAnimationEnabled="true"
|
||||||
app:hintEnabled="true"
|
app:hintEnabled="true"
|
||||||
|
@ -124,7 +117,6 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/userImageContainer">
|
app:layout_constraintTop_toBottomOf="@id/userImageContainer">
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -138,7 +130,7 @@
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
android:id="@+id/next"
|
android:id="@+id/next"
|
||||||
|
|
Loading…
Reference in a new issue