Improved user profile image picking

This commit is contained in:
Hemanth S 2020-05-21 04:23:09 +05:30
parent 607d1722da
commit 2c4b00edb9
7 changed files with 412 additions and 360 deletions

View file

@ -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'
} }

View file

@ -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)
} }
} }

View file

@ -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 {

View file

@ -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));
}
}
}

View file

@ -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));
}
}
}

View file

@ -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);

View file

@ -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"