added shortcuts and widgets

main
h4h13 2018-12-08 09:03:02 +05:30
parent d47aeccd87
commit 03aeb88964
54 changed files with 2646 additions and 935 deletions

View File

@ -3,6 +3,8 @@ package code.name.monkey.retromusic
import android.content.Context
import androidx.multidex.MultiDexApplication
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
import com.anjlab.android.iab.v3.BillingProcessor
import com.anjlab.android.iab.v3.TransactionDetails
import com.bumptech.glide.Glide
@ -25,6 +27,10 @@ class App : MultiDexApplication() {
.commit()
}
if (VersionUtils.hasNougatMR())
DynamicShortcutManager(this).initDynamicShortcuts()
// automatically restores purchases
billingProcessor = BillingProcessor(this, BuildConfig.GOOGLE_PLAY_LICENSE_KEY,
object : BillingProcessor.IBillingHandler {

View File

@ -10,7 +10,7 @@ import code.name.monkey.retromusic.util.schedulers.SchedulerProvider
object Injection {
fun provideRepository(): Repository {
return RepositoryImpl.getInstance()
return RepositoryImpl.instance
}
fun provideSchedulerProvider(): BaseSchedulerProvider {

View File

@ -0,0 +1,70 @@
package code.name.monkey.retromusic.appshortcuts;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.util.TypedValue;
import androidx.annotation.RequiresApi;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.RetroUtil;
/**
* @author Adrian Campos
*/
@RequiresApi(Build.VERSION_CODES.N_MR1)
public final class AppShortcutIconGenerator {
public static Icon generateThemedIcon(Context context, int iconId) {
if (PreferenceUtil.getInstance().coloredAppShortcuts()) {
return generateUserThemedIcon(context, iconId);
} else {
return generateDefaultThemedIcon(context, iconId);
}
}
private static Icon generateDefaultThemedIcon(Context context, int iconId) {
// Return an Icon of iconId with default colors
return generateThemedIcon(context, iconId,
context.getColor(R.color.app_shortcut_default_foreground),
context.getColor(R.color.app_shortcut_default_background)
);
}
private static Icon generateUserThemedIcon(Context context, int iconId) {
// Get background color from context's theme
final TypedValue typedColorBackground = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.colorBackground, typedColorBackground, true);
// Return an Icon of iconId with those colors
return generateThemedIcon(context, iconId,
ThemeStore.accentColor(context),
typedColorBackground.data
);
}
private static Icon generateThemedIcon(Context context, int iconId, int foregroundColor, int backgroundColor) {
// Get and tint foreground and background drawables
Drawable vectorDrawable = RetroUtil.getTintedVectorDrawable(context, iconId, foregroundColor);
Drawable backgroundDrawable = RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_app_shortcut_background, backgroundColor);
// Squash the two drawables together
LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{backgroundDrawable, vectorDrawable});
// Return as an Icon
return Icon.createWithBitmap(drawableToBitmap(layerDrawable));
}
private static Bitmap drawableToBitmap(Drawable drawable) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}

View File

@ -0,0 +1,77 @@
package code.name.monkey.retromusic.appshortcuts;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist;
import code.name.monkey.retromusic.model.smartplaylist.MyTopTracksPlaylist;
import code.name.monkey.retromusic.model.smartplaylist.ShuffleAllPlaylist;
import code.name.monkey.retromusic.appshortcuts.shortcuttype.LastAddedShortcutType;
import code.name.monkey.retromusic.appshortcuts.shortcuttype.ShuffleAllShortcutType;
import code.name.monkey.retromusic.appshortcuts.shortcuttype.TopTracksShortcutType;
import code.name.monkey.retromusic.service.MusicService;
import static code.name.monkey.retromusic.Constants.*;
/**
* @author Adrian Campos
*/
public class AppShortcutLauncherActivity extends Activity {
public static final String KEY_SHORTCUT_TYPE = "code.name.monkey.retromusic.appshortcuts.ShortcutType";
public static final int SHORTCUT_TYPE_SHUFFLE_ALL = 0;
public static final int SHORTCUT_TYPE_TOP_TRACKS = 1;
public static final int SHORTCUT_TYPE_LAST_ADDED = 2;
public static final int SHORTCUT_TYPE_NONE = 3;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int shortcutType = SHORTCUT_TYPE_NONE;
// Set shortcutType from the intent extras
Bundle extras = getIntent().getExtras();
if (extras != null) {
//noinspection WrongConstant
shortcutType = extras.getInt(KEY_SHORTCUT_TYPE, SHORTCUT_TYPE_NONE);
}
switch (shortcutType) {
case SHORTCUT_TYPE_SHUFFLE_ALL:
startServiceWithPlaylist(MusicService.SHUFFLE_MODE_SHUFFLE,
new ShuffleAllPlaylist(getApplicationContext()));
DynamicShortcutManager.reportShortcutUsed(this, ShuffleAllShortcutType.getId());
break;
case SHORTCUT_TYPE_TOP_TRACKS:
startServiceWithPlaylist(MusicService.SHUFFLE_MODE_NONE,
new MyTopTracksPlaylist(getApplicationContext()));
DynamicShortcutManager.reportShortcutUsed(this, TopTracksShortcutType.getId());
break;
case SHORTCUT_TYPE_LAST_ADDED:
startServiceWithPlaylist(MusicService.SHUFFLE_MODE_NONE,
new LastAddedPlaylist(getApplicationContext()));
DynamicShortcutManager.reportShortcutUsed(this, LastAddedShortcutType.getId());
break;
}
finish();
}
private void startServiceWithPlaylist(int shuffleMode, Playlist playlist) {
Intent intent = new Intent(this, MusicService.class);
intent.setAction(ACTION_PLAY_PLAYLIST);
Bundle bundle = new Bundle();
bundle.putParcelable(INTENT_EXTRA_PLAYLIST, playlist);
bundle.putInt(INTENT_EXTRA_SHUFFLE_MODE, shuffleMode);
intent.putExtras(bundle);
startService(intent);
}
}

View File

@ -0,0 +1,63 @@
package code.name.monkey.retromusic.appshortcuts;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Icon;
import android.os.Build;
import java.util.Arrays;
import java.util.List;
import code.name.monkey.retromusic.appshortcuts.shortcuttype.LastAddedShortcutType;
import code.name.monkey.retromusic.appshortcuts.shortcuttype.ShuffleAllShortcutType;
import code.name.monkey.retromusic.appshortcuts.shortcuttype.TopTracksShortcutType;
/**
* @author Adrian Campos
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
public class DynamicShortcutManager {
private Context context;
private ShortcutManager shortcutManager;
public DynamicShortcutManager(Context context) {
this.context = context;
shortcutManager = this.context.getSystemService(ShortcutManager.class);
}
public static ShortcutInfo createShortcut(Context context, String id, String shortLabel, String longLabel, Icon icon, Intent intent) {
return new ShortcutInfo.Builder(context, id)
.setShortLabel(shortLabel)
.setLongLabel(longLabel)
.setIcon(icon)
.setIntent(intent)
.build();
}
public static void reportShortcutUsed(Context context, String shortcutId) {
context.getSystemService(ShortcutManager.class).reportShortcutUsed(shortcutId);
}
public void initDynamicShortcuts() {
if (shortcutManager.getDynamicShortcuts().size() == 0) {
shortcutManager.setDynamicShortcuts(getDefaultShortcuts());
}
}
public void updateDynamicShortcuts() {
shortcutManager.updateShortcuts(getDefaultShortcuts());
}
public List<ShortcutInfo> getDefaultShortcuts() {
return (Arrays.asList(
new ShuffleAllShortcutType(context).getShortcutInfo(),
new TopTracksShortcutType(context).getShortcutInfo(),
new LastAddedShortcutType(context).getShortcutInfo()
));
}
}

View File

@ -0,0 +1,50 @@
package code.name.monkey.retromusic.appshortcuts.shortcuttype;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.os.Build;
import android.os.Bundle;
import code.name.monkey.retromusic.appshortcuts.AppShortcutLauncherActivity;
/**
* @author Adrian Campos
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
public abstract class BaseShortcutType {
static final String ID_PREFIX = "code.name.monkey.retromusic.appshortcuts.id.";
Context context;
public BaseShortcutType(Context context) {
this.context = context;
}
static public String getId() {
return ID_PREFIX + "invalid";
}
abstract ShortcutInfo getShortcutInfo();
/**
* Creates an Intent that will launch MainActivtiy and immediately play {@param songs} in either shuffle or normal mode
*
* @param shortcutType Describes the type of shortcut to create (ShuffleAll, TopTracks, custom playlist, etc.)
* @return
*/
Intent getPlaySongsIntent(int shortcutType) {
Intent intent = new Intent(context, AppShortcutLauncherActivity.class);
intent.setAction(Intent.ACTION_VIEW);
Bundle b = new Bundle();
b.putInt(AppShortcutLauncherActivity.KEY_SHORTCUT_TYPE, shortcutType);
intent.putExtras(b);
return intent;
}
}

View File

@ -0,0 +1,34 @@
package code.name.monkey.retromusic.appshortcuts.shortcuttype;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.os.Build;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.appshortcuts.AppShortcutIconGenerator;
import code.name.monkey.retromusic.appshortcuts.AppShortcutLauncherActivity;
/**
* @author Adrian Campos
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
public final class LastAddedShortcutType extends BaseShortcutType {
public LastAddedShortcutType(Context context) {
super(context);
}
public static String getId() {
return ID_PREFIX + "last_added";
}
public ShortcutInfo getShortcutInfo() {
return new ShortcutInfo.Builder(context, getId())
.setShortLabel(context.getString(R.string.app_shortcut_last_added_short))
.setLongLabel(context.getString(R.string.app_shortcut_last_added_long))
.setIcon(AppShortcutIconGenerator.generateThemedIcon(context, R.drawable.ic_app_shortcut_last_added))
.setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_LAST_ADDED))
.build();
}
}

View File

@ -0,0 +1,35 @@
package code.name.monkey.retromusic.appshortcuts.shortcuttype;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.os.Build;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.appshortcuts.AppShortcutIconGenerator;
import code.name.monkey.retromusic.appshortcuts.AppShortcutLauncherActivity;
/**
* @author Adrian Campos
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
public final class ShuffleAllShortcutType extends BaseShortcutType {
public ShuffleAllShortcutType(Context context) {
super(context);
}
public static String getId() {
return ID_PREFIX + "shuffle_all";
}
public ShortcutInfo getShortcutInfo() {
return new ShortcutInfo.Builder(context, getId())
.setShortLabel(context.getString(R.string.app_shortcut_shuffle_all_short))
.setLongLabel(context.getString(R.string.app_shortcut_shuffle_all_long))
.setIcon(AppShortcutIconGenerator.generateThemedIcon(context, R.drawable.ic_app_shortcut_shuffle_all))
.setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_SHUFFLE_ALL))
.build();
}
}

View File

@ -0,0 +1,35 @@
package code.name.monkey.retromusic.appshortcuts.shortcuttype;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.os.Build;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.appshortcuts.AppShortcutIconGenerator;
import code.name.monkey.retromusic.appshortcuts.AppShortcutLauncherActivity;
/**
* @author Adrian Campos
*/
@TargetApi(Build.VERSION_CODES.N_MR1)
public final class TopTracksShortcutType extends BaseShortcutType {
public TopTracksShortcutType(Context context) {
super(context);
}
public static String getId() {
return ID_PREFIX + "top_tracks";
}
public ShortcutInfo getShortcutInfo() {
return new ShortcutInfo.Builder(context, getId())
.setShortLabel(context.getString(R.string.app_shortcut_top_tracks_short))
.setLongLabel(context.getString(R.string.app_shortcut_top_tracks_long))
.setIcon(AppShortcutIconGenerator.generateThemedIcon(context, R.drawable.ic_app_shortcut_top_tracks))
.setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_TOP_TRACKS))
.build();
}
}

View File

@ -0,0 +1,167 @@
package code.name.monkey.retromusic.appwidgets
import android.app.PendingIntent
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.text.TextUtils
import android.view.View
import android.widget.RemoteViews
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.Constants
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.appwidgets.base.BaseAppWidget
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.ui.activities.MainActivity
import code.name.monkey.retromusic.util.RetroUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.request.animation.GlideAnimation
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.target.Target
class AppWidgetBig : BaseAppWidget() {
private var target: Target<Bitmap>? = null // for cancellation
/**
* Initialize given widgets to default state, where we launch Music on default click and hide
* actions if service not running.
*/
override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) {
val appWidgetView = RemoteViews(context.packageName,
R.layout.app_widget_big)
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
appWidgetView.setImageViewResource(R.id.image, R.drawable.default_album_art)
appWidgetView.setImageViewBitmap(R.id.button_next, BaseAppWidget.createBitmap(
RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_next_white_24dp,
MaterialValueHelper.getPrimaryTextColor(context, false))!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_prev, BaseAppWidget.Companion.createBitmap(
RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_previous_white_24dp,
MaterialValueHelper.getPrimaryTextColor(context, false))!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause, BaseAppWidget.Companion.createBitmap(
RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_play_arrow_white_24dp,
MaterialValueHelper.getPrimaryTextColor(context, false))!!, 1f))
linkButtons(context, appWidgetView)
pushUpdate(context, appWidgetIds, appWidgetView)
}
/**
* Update all active widget instances by pushing changes
*/
override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) {
val appWidgetView = RemoteViews(service.packageName,
R.layout.app_widget_big)
val isPlaying = service.isPlaying
val song = service.currentSong
// Set the titles and artwork
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) {
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
} else {
appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE)
appWidgetView.setTextViewText(R.id.title, song.title)
appWidgetView.setTextViewText(R.id.text, getSongArtistAndAlbum(song))
}
// Set correct drawable for pause state
val playPauseRes = if (isPlaying) R.drawable.ic_pause_white_24dp else R.drawable.ic_play_arrow_white_24dp
appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause, BaseAppWidget.createBitmap(
RetroUtil.getTintedVectorDrawable(service, playPauseRes,
MaterialValueHelper.getPrimaryTextColor(service, false))!!, 1f))
// Set prev/next button drawables
appWidgetView.setImageViewBitmap(R.id.button_next, BaseAppWidget.Companion.createBitmap(
RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_next_white_24dp,
MaterialValueHelper.getPrimaryTextColor(service, false))!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_prev, BaseAppWidget.Companion.createBitmap(
RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_previous_white_24dp,
MaterialValueHelper.getPrimaryTextColor(service, false))!!, 1f))
// Link actions buttons to intents
linkButtons(service, appWidgetView)
// Load the album cover async and push the update on completion
val p = RetroUtil.getScreenSize(service)
val widgetImageSize = Math.min(p.x, p.y)
val appContext = service.applicationContext
service.runOnUiThread {
if (target != null) {
Glide.clear(target!!)
}
target = SongGlideRequest.Builder.from(Glide.with(appContext), song)
.checkIgnoreMediaStore(appContext)
.asBitmap().build()
.into(object : SimpleTarget<Bitmap>(widgetImageSize, widgetImageSize) {
override fun onResourceReady(resource: Bitmap,
glideAnimation: GlideAnimation<in Bitmap>) {
update(resource)
}
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
super.onLoadFailed(e, errorDrawable)
update(null)
}
private fun update(bitmap: Bitmap?) {
if (bitmap == null) {
appWidgetView.setImageViewResource(R.id.image, R.drawable.default_album_art)
} else {
appWidgetView.setImageViewBitmap(R.id.image, bitmap)
}
pushUpdate(appContext, appWidgetIds, appWidgetView)
}
})
}
}
/**
* Link up various button actions using [PendingIntent].
*/
private fun linkButtons(context: Context, views: RemoteViews) {
val action = Intent(context, MainActivity::class.java).putExtra("expand", true)
var pendingIntent: PendingIntent
val serviceName = ComponentName(context, MusicService::class.java)
// Home
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
pendingIntent = PendingIntent.getActivity(context, 0, action, 0)
views.setOnClickPendingIntent(R.id.clickable_area, pendingIntent)
// Previous track
pendingIntent = buildPendingIntent(context, Constants.ACTION_REWIND, serviceName)
views.setOnClickPendingIntent(R.id.button_prev, pendingIntent)
// Play and pause
pendingIntent = buildPendingIntent(context, Constants.ACTION_TOGGLE_PAUSE, serviceName)
views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent)
// Next track
pendingIntent = buildPendingIntent(context, Constants.ACTION_SKIP, serviceName)
views.setOnClickPendingIntent(R.id.button_next, pendingIntent)
}
companion object {
const val NAME: String = "app_widget_big"
private var mInstance: AppWidgetBig? = null
val instance: AppWidgetBig
@Synchronized get() {
if (mInstance == null) {
mInstance = AppWidgetBig()
}
return mInstance!!
}
}
}

View File

@ -0,0 +1,182 @@
package code.name.monkey.retromusic.appwidgets
import android.app.PendingIntent
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.text.TextUtils
import android.view.View
import android.widget.RemoteViews
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.Constants
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.appwidgets.base.BaseAppWidget
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.ui.activities.MainActivity
import code.name.monkey.retromusic.util.RetroUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.request.animation.GlideAnimation
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.target.Target
class AppWidgetCard : BaseAppWidget() {
private var target: Target<BitmapPaletteWrapper>? = null // for cancellation
/**
* Initialize given widgets to default state, where we launch Music on default click and hide
* actions if service not running.
*/
override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) {
val appWidgetView = RemoteViews(context.packageName,
R.layout.app_widget_card)
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
appWidgetView.setImageViewResource(R.id.image, R.drawable.default_album_art)
appWidgetView.setImageViewBitmap(R.id.button_next, BaseAppWidget.Companion.createBitmap(
RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_next_white_24dp,
MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_prev, BaseAppWidget.Companion.createBitmap(
RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_previous_white_24dp,
MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause, BaseAppWidget.Companion.createBitmap(
RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_play_arrow_white_24dp,
MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
linkButtons(context, appWidgetView)
pushUpdate(context, appWidgetIds, appWidgetView)
}
/**
* Update all active widget instances by pushing changes
*/
override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) {
val appWidgetView = RemoteViews(service.packageName,
R.layout.app_widget_card)
val isPlaying = service.isPlaying
val song = service.currentSong
// Set the titles and artwork
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) {
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
} else {
appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE)
appWidgetView.setTextViewText(R.id.title, song.title)
appWidgetView.setTextViewText(R.id.text, getSongArtistAndAlbum(song))
}
// Set correct drawable for pause state
val playPauseRes = if (isPlaying) R.drawable.ic_pause_white_24dp else R.drawable.ic_play_arrow_white_24dp
appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause, BaseAppWidget.Companion.createBitmap(
RetroUtil.getTintedVectorDrawable(service, playPauseRes,
MaterialValueHelper.getSecondaryTextColor(service, true))!!, 1f))
// Set prev/next button drawables
appWidgetView.setImageViewBitmap(R.id.button_next, BaseAppWidget.Companion.createBitmap(
RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_next_white_24dp,
MaterialValueHelper.getSecondaryTextColor(service, true))!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_prev, BaseAppWidget.Companion.createBitmap(
RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_previous_white_24dp,
MaterialValueHelper.getSecondaryTextColor(service, true))!!, 1f))
// Link actions buttons to intents
linkButtons(service, appWidgetView)
if (imageSize == 0) {
imageSize = service.resources.getDimensionPixelSize(R.dimen.app_widget_card_image_size)
}
if (cardRadius == 0f) {
cardRadius = service.resources.getDimension(R.dimen.app_widget_card_radius)
}
// Load the album cover async and push the update on completion
service.runOnUiThread {
if (target != null) {
Glide.clear(target!!)
}
target = SongGlideRequest.Builder.from(Glide.with(service), song)
.checkIgnoreMediaStore(service)
.generatePalette(service).build()
.centerCrop()
.into(object : SimpleTarget<BitmapPaletteWrapper>(imageSize, imageSize) {
override fun onResourceReady(resource: BitmapPaletteWrapper,
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>) {
val palette = resource.palette
update(resource.bitmap, palette.getVibrantColor(palette
.getMutedColor(MaterialValueHelper.getSecondaryTextColor(service, true))))
}
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
super.onLoadFailed(e, errorDrawable)
update(null, MaterialValueHelper.getSecondaryTextColor(service, true))
}
private fun update(bitmap: Bitmap?, color: Int) {
// Set correct drawable for pause state
val playPauseRest = if (isPlaying) R.drawable.ic_pause_white_24dp
else
R.drawable.ic_play_arrow_white_24dp
appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause, BaseAppWidget.createBitmap(RetroUtil.getTintedVectorDrawable(service, playPauseRest, color)!!, 1f))
// Set prev/next button drawables
appWidgetView.setImageViewBitmap(R.id.button_next, BaseAppWidget.createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_next_white_24dp, color)!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_prev, BaseAppWidget.createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_previous_white_24dp, color)!!, 1f))
val image = getAlbumArtDrawable(service.resources, bitmap)
val roundedBitmap = BaseAppWidget.Companion.createRoundedBitmap(image, imageSize, imageSize, cardRadius, 0f, cardRadius, 0f)
appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap)
pushUpdate(service, appWidgetIds, appWidgetView)
}
})
}
}
/**
* Link up various button actions using [PendingIntent].
*/
private fun linkButtons(context: Context, views: RemoteViews) {
val action: Intent = Intent(context, MainActivity::class.java).putExtra("expand", true)
var pendingIntent: PendingIntent
val serviceName = ComponentName(context, MusicService::class.java)
// Home
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
pendingIntent = PendingIntent.getActivity(context, 0, action, 0)
views.setOnClickPendingIntent(R.id.image, pendingIntent)
views.setOnClickPendingIntent(R.id.media_titles, pendingIntent)
// Previous track
pendingIntent = buildPendingIntent(context, Constants.ACTION_REWIND, serviceName)
views.setOnClickPendingIntent(R.id.button_prev, pendingIntent)
// Play and pause
pendingIntent = buildPendingIntent(context, Constants.ACTION_TOGGLE_PAUSE, serviceName)
views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent)
// Next track
pendingIntent = buildPendingIntent(context, Constants.ACTION_SKIP, serviceName)
views.setOnClickPendingIntent(R.id.button_next, pendingIntent)
}
companion object {
const val NAME = "app_widget_card"
private var mInstance: AppWidgetCard? = null
private var imageSize = 0
private var cardRadius = 0f
val instance: AppWidgetCard
@Synchronized get() {
if (mInstance == null) {
mInstance = AppWidgetCard()
}
return mInstance!!
}
}
}

View File

@ -0,0 +1,166 @@
package code.name.monkey.retromusic.appwidgets
import android.app.PendingIntent
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.text.TextUtils
import android.view.View
import android.widget.RemoteViews
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.Constants
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.appwidgets.base.BaseAppWidget
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.ui.activities.MainActivity
import code.name.monkey.retromusic.util.RetroUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.request.animation.GlideAnimation
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.target.Target
class AppWidgetClassic : BaseAppWidget() {
private var target: Target<BitmapPaletteWrapper>? = null // for cancellation
/**
* Initialize given widgets to default state, where we launch Music on default click and hide
* actions if service not running.
*/
override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) {
val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_classic)
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
appWidgetView.setImageViewResource(R.id.image, R.drawable.default_album_art)
appWidgetView.setImageViewBitmap(R.id.button_next, BaseAppWidget.Companion.createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_next_white_24dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_prev, BaseAppWidget.Companion.createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_previous_white_24dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause, BaseAppWidget.Companion.createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_play_arrow_white_24dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
linkButtons(context, appWidgetView)
pushUpdate(context, appWidgetIds, appWidgetView)
}
/**
* Update all active widget instances by pushing changes
*/
override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) {
val appWidgetView = RemoteViews(service.packageName,
R.layout.app_widget_classic)
val isPlaying = service.isPlaying
val song = service.currentSong
// Set the titles and artwork
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) {
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
} else {
appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE)
appWidgetView.setTextViewText(R.id.title, song.title)
appWidgetView.setTextViewText(R.id.text, getSongArtistAndAlbum(song))
}
// Link actions buttons to intents
linkButtons(service, appWidgetView)
if (imageSize == 0) {
imageSize = service.resources
.getDimensionPixelSize(R.dimen.app_widget_classic_image_size)
}
if (cardRadius == 0f) {
cardRadius = service.resources.getDimension(R.dimen.app_widget_card_radius)
}
// Load the album cover async and push the update on completion
val appContext = service.applicationContext
service.runOnUiThread {
if (target != null) {
Glide.clear(target!!)
}
target = SongGlideRequest.Builder.from(Glide.with(appContext), song)
.checkIgnoreMediaStore(appContext)
.generatePalette(service).build()
.centerCrop()
.into(object : SimpleTarget<BitmapPaletteWrapper>(imageSize, imageSize) {
override fun onResourceReady(resource: BitmapPaletteWrapper,
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>) {
val palette = resource.palette
update(resource.bitmap, palette.getVibrantColor(palette.getMutedColor(MaterialValueHelper.getSecondaryTextColor(appContext, true))))
}
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
super.onLoadFailed(e, errorDrawable)
update(null, MaterialValueHelper.getSecondaryTextColor(appContext, true))
}
private fun update(bitmap: Bitmap?, color: Int) {
// Set correct drawable for pause state
val playPauseRes = if (isPlaying)
R.drawable.ic_pause_white_24dp
else
R.drawable.ic_play_arrow_white_24dp
appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause,
BaseAppWidget.createBitmap(RetroUtil.getTintedVectorDrawable(service, playPauseRes, color)!!, 1f))
// Set prev/next button drawables
appWidgetView.setImageViewBitmap(R.id.button_next, BaseAppWidget.createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_next_white_24dp, color)!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_prev, BaseAppWidget.createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_previous_white_24dp, color)!!, 1f))
val image = getAlbumArtDrawable(service.resources, bitmap)
val roundedBitmap = BaseAppWidget.createRoundedBitmap(image, imageSize, imageSize,
cardRadius, 0f, cardRadius, 0f)
appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap)
pushUpdate(appContext, appWidgetIds, appWidgetView)
}
})
}
}
/**
* Link up various button actions using [PendingIntent].
*/
private fun linkButtons(context: Context, views: RemoteViews) {
val action = Intent(context, MainActivity::class.java).putExtra("expand", true)
var pendingIntent: PendingIntent
val serviceName = ComponentName(context, MusicService::class.java)
// Home
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
pendingIntent = PendingIntent.getActivity(context, 0, action, 0)
views.setOnClickPendingIntent(R.id.image, pendingIntent)
views.setOnClickPendingIntent(R.id.media_titles, pendingIntent)
// Previous track
pendingIntent = buildPendingIntent(context, Constants.ACTION_REWIND, serviceName)
views.setOnClickPendingIntent(R.id.button_prev, pendingIntent)
// Play and pause
pendingIntent = buildPendingIntent(context, Constants.ACTION_TOGGLE_PAUSE, serviceName)
views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent)
// Next track
pendingIntent = buildPendingIntent(context, Constants.ACTION_SKIP, serviceName)
views.setOnClickPendingIntent(R.id.button_next, pendingIntent)
}
companion object {
const val NAME = "app_widget_classic"
private var mInstance: AppWidgetClassic? = null
private var imageSize = 0
private var cardRadius = 0f
val instance: AppWidgetClassic
@Synchronized get() {
if (mInstance == null) {
mInstance = AppWidgetClassic()
}
return mInstance!!
}
}
}

View File

@ -0,0 +1,170 @@
package code.name.monkey.retromusic.appwidgets
import android.app.PendingIntent
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.text.TextUtils
import android.view.View
import android.widget.RemoteViews
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.Constants
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.appwidgets.base.BaseAppWidget
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.ui.activities.MainActivity
import code.name.monkey.retromusic.util.RetroUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.request.animation.GlideAnimation
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.target.Target
class AppWidgetSmall : BaseAppWidget() {
private var target: Target<BitmapPaletteWrapper>? = null // for cancellation
/**
* Initialize given widgets to default state, where we launch Music on default click and hide
* actions if service not running.
*/
override fun defaultAppWidget(context: Context, appWidgetIds: IntArray) {
val appWidgetView = RemoteViews(context.packageName, R.layout.app_widget_small)
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
appWidgetView.setImageViewResource(R.id.image, R.drawable.default_album_art)
appWidgetView.setImageViewBitmap(R.id.button_next, BaseAppWidget.Companion.createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_next_white_24dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_prev, BaseAppWidget.Companion.createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_skip_previous_white_24dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause, BaseAppWidget.Companion.createBitmap(RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_play_arrow_white_24dp, MaterialValueHelper.getSecondaryTextColor(context, true))!!, 1f))
linkButtons(context, appWidgetView)
pushUpdate(context, appWidgetIds, appWidgetView)
}
/**
* Update all active widget instances by pushing changes
*/
override fun performUpdate(service: MusicService, appWidgetIds: IntArray?) {
val appWidgetView = RemoteViews(service.packageName,
R.layout.app_widget_small)
val isPlaying = service.isPlaying
val song = service.currentSong
// Set the titles and artwork
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) {
appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE)
} else {
if (TextUtils.isEmpty(song.title) || TextUtils.isEmpty(song.artistName)) {
appWidgetView.setTextViewText(R.id.text_separator, "")
} else {
appWidgetView.setTextViewText(R.id.text_separator, "")
}
appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE)
appWidgetView.setTextViewText(R.id.title, song.title)
appWidgetView.setTextViewText(R.id.text, song.artistName)
}
// Link actions buttons to intents
linkButtons(service, appWidgetView)
if (imageSize == 0) {
imageSize = service.resources.getDimensionPixelSize(R.dimen.app_widget_small_image_size)
}
if (cardRadius == 0f) {
cardRadius = service.resources.getDimension(R.dimen.app_widget_card_radius)
}
// Load the album cover async and push the update on completion
val appContext = service.applicationContext
service.runOnUiThread {
if (target != null) {
Glide.clear(target!!)
}
target = SongGlideRequest.Builder.from(Glide.with(appContext), song)
.checkIgnoreMediaStore(appContext)
.generatePalette(service).build()
.centerCrop()
.into(object : SimpleTarget<BitmapPaletteWrapper>(imageSize, imageSize) {
override fun onResourceReady(resource: BitmapPaletteWrapper,
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>) {
val palette = resource.palette
update(resource.bitmap, palette.getVibrantColor(palette
.getMutedColor(MaterialValueHelper.getSecondaryTextColor(appContext, true))))
}
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
super.onLoadFailed(e, errorDrawable)
update(null, MaterialValueHelper.getSecondaryTextColor(appContext, true))
}
private fun update(bitmap: Bitmap?, color: Int) {
// Set correct drawable for pause state
val playPauseRes = if (isPlaying)
R.drawable.ic_pause_white_24dp
else
R.drawable.ic_play_arrow_white_24dp
appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause, BaseAppWidget.Companion.createBitmap(RetroUtil.getTintedVectorDrawable(service, playPauseRes, color)!!, 1f))
// Set prev/next button drawables
appWidgetView.setImageViewBitmap(R.id.button_next, BaseAppWidget.Companion.createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_next_white_24dp, color)!!, 1f))
appWidgetView.setImageViewBitmap(R.id.button_prev, BaseAppWidget.Companion.createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_previous_white_24dp, color)!!, 1f))
val image = getAlbumArtDrawable(service.resources, bitmap)
val roundedBitmap = BaseAppWidget.createRoundedBitmap(image, imageSize, imageSize, cardRadius, 0f, 0f, 0f)
appWidgetView.setImageViewBitmap(R.id.image, roundedBitmap)
pushUpdate(appContext, appWidgetIds, appWidgetView)
}
})
}
}
/**
* Link up various button actions using [PendingIntent].
*/
private fun linkButtons(context: Context, views: RemoteViews) {
val action = Intent(context, MainActivity::class.java).putExtra("expand", true)
var pendingIntent: PendingIntent
val serviceName = ComponentName(context, MusicService::class.java)
// Home
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
pendingIntent = PendingIntent.getActivity(context, 0, action, 0)
views.setOnClickPendingIntent(R.id.image, pendingIntent)
views.setOnClickPendingIntent(R.id.media_titles, pendingIntent)
// Previous track
pendingIntent = buildPendingIntent(context, Constants.ACTION_REWIND, serviceName)
views.setOnClickPendingIntent(R.id.button_prev, pendingIntent)
// Play and pause
pendingIntent = buildPendingIntent(context, Constants.ACTION_TOGGLE_PAUSE, serviceName)
views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent)
// Next track
pendingIntent = buildPendingIntent(context, Constants.ACTION_SKIP, serviceName)
views.setOnClickPendingIntent(R.id.button_next, pendingIntent)
}
companion object {
const val NAME:String = "app_widget_small"
private var mInstance: AppWidgetSmall? = null
private var imageSize = 0
private var cardRadius = 0f
val instance: AppWidgetSmall
@Synchronized get() {
if (mInstance == null) {
mInstance = AppWidgetSmall()
}
return mInstance!!
}
}
}

View File

@ -0,0 +1,31 @@
package code.name.monkey.retromusic.appwidgets
import android.appwidget.AppWidgetManager
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Build
import code.name.monkey.retromusic.service.MusicService
/**
* @author Eugene Cheung (arkon)
*/
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val widgetManager = AppWidgetManager.getInstance(context)
// Start music service if there are any existing widgets
if (widgetManager.getAppWidgetIds(ComponentName(context, AppWidgetBig::class.java)).isNotEmpty() ||
widgetManager.getAppWidgetIds(ComponentName(context, AppWidgetClassic::class.java)).isNotEmpty() ||
widgetManager.getAppWidgetIds(ComponentName(context, AppWidgetSmall::class.java)).isNotEmpty() ||
widgetManager.getAppWidgetIds(ComponentName(context, AppWidgetCard::class.java)).isNotEmpty()) {
val serviceIntent = Intent(context, MusicService::class.java)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { // not allowed on Oreo
context.startService(serviceIntent)
}
}
}
}

View File

@ -0,0 +1,163 @@
package code.name.monkey.retromusic.appwidgets.base
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.graphics.*
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.os.Build
import android.text.TextUtils
import android.widget.RemoteViews
import androidx.core.content.ContextCompat
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.Constants
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.service.MusicService
abstract class BaseAppWidget : AppWidgetProvider() {
/**
* {@inheritDoc}
*/
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray) {
defaultAppWidget(context, appWidgetIds)
val updateIntent = Intent(Constants.APP_WIDGET_UPDATE)
updateIntent.putExtra(Constants.EXTRA_APP_WIDGET_NAME, NAME)
updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)
updateIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
context.sendBroadcast(updateIntent)
}
/**
* Handle a change notification coming over from [MusicService]
*/
fun notifyChange(service: MusicService, what: String) {
if (hasInstances(service)) {
if (Constants.META_CHANGED == what || Constants.PLAY_STATE_CHANGED == what) {
performUpdate(service, null)
}
}
}
protected fun pushUpdate(context: Context, appWidgetIds: IntArray?,
views: RemoteViews) {
val appWidgetManager = AppWidgetManager.getInstance(context)
if (appWidgetIds != null) {
appWidgetManager.updateAppWidget(appWidgetIds, views)
} else {
appWidgetManager.updateAppWidget(ComponentName(context, javaClass), views)
}
}
/**
* Check against [AppWidgetManager] if there are any instances of this widget.
*/
protected fun hasInstances(context: Context): Boolean {
val appWidgetManager = AppWidgetManager.getInstance(context)
val mAppWidgetIds = appWidgetManager.getAppWidgetIds(ComponentName(context,
javaClass))
return mAppWidgetIds.size > 0
}
protected fun buildPendingIntent(context: Context, action: String,
serviceName: ComponentName): PendingIntent {
val intent = Intent(action)
intent.component = serviceName
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PendingIntent.getForegroundService(context, 0, intent, 0)
} else {
PendingIntent.getService(context, 0, intent, 0)
}
}
protected abstract fun defaultAppWidget(context: Context, appWidgetIds: IntArray)
abstract fun performUpdate(service: MusicService, appWidgetIds: IntArray?)
protected fun getAlbumArtDrawable(resources: Resources, bitmap: Bitmap?): Drawable {
return if (bitmap == null) {
ContextCompat.getDrawable(App.context, R.drawable.default_album_art)!!
} else {
BitmapDrawable(resources, bitmap)
}
}
protected fun getSongArtistAndAlbum(song: Song): String {
val builder = StringBuilder()
builder.append(song.artistName)
if (!TextUtils.isEmpty(song.artistName) && !TextUtils.isEmpty(song.albumName)) {
builder.append("")
}
builder.append(song.albumName)
return builder.toString()
}
companion object {
const val NAME: String = "app_widget"
fun createRoundedBitmap(drawable: Drawable?, width: Int, height: Int, tl: Float,
tr: Float, bl: Float, br: Float): Bitmap? {
if (drawable == null) {
return null
}
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val c = Canvas(bitmap)
drawable.setBounds(0, 0, width, height)
drawable.draw(c)
val rounded = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(rounded)
val paint = Paint()
paint.shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
paint.isAntiAlias = true
canvas.drawPath(composeRoundedRectPath(RectF(0f, 0f, width.toFloat(), height.toFloat()), tl, tr, bl, br), paint)
return rounded
}
fun createBitmap(drawable: Drawable, sizeMultiplier: Float): Bitmap {
val bitmap = Bitmap.createBitmap((drawable.intrinsicWidth * sizeMultiplier).toInt(),
(drawable.intrinsicHeight * sizeMultiplier).toInt(), Bitmap.Config.ARGB_8888)
val c = Canvas(bitmap)
drawable.setBounds(0, 0, c.width, c.height)
drawable.draw(c)
return bitmap
}
protected fun composeRoundedRectPath(rect: RectF, tl: Float, tr: Float, bl: Float, br: Float): Path {
var tlf = tl
var trf = tr
var blf = bl
var brf = br
val path = Path()
tlf = if (tl < 0) 0F else tl
trf = if (tr < 0) 0f else tr
blf = if (bl < 0) 0f else bl
brf = if (br < 0) 0f else br
path.moveTo(rect.left + tl, rect.top)
path.lineTo(rect.right - tr, rect.top)
path.quadTo(rect.right, rect.top, rect.right, rect.top + tr)
path.lineTo(rect.right, rect.bottom - br)
path.quadTo(rect.right, rect.bottom, rect.right - br, rect.bottom)
path.lineTo(rect.left + bl, rect.bottom)
path.quadTo(rect.left, rect.bottom, rect.left, rect.bottom - bl)
path.lineTo(rect.left, rect.top + tl)
path.quadTo(rect.left, rect.top, rect.left + tl, rect.top)
path.close()
return path
}
}
}

View File

@ -24,7 +24,7 @@ class DeletePlaylistDialog : RoundedBottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val playlists = arguments!!.getParcelableArrayList<Playlist>("playlists")
val playlists = arguments!!.getParcelableArrayList<Playlist>("playlist")
val content: CharSequence
content = if (playlists!!.size > 1) {

View File

@ -29,16 +29,16 @@ class SortOrder {
companion object {
/* Artist sort order A-Z */
val ARTIST_A_Z = MediaStore.Audio.Artists.DEFAULT_SORT_ORDER
const val ARTIST_A_Z = MediaStore.Audio.Artists.DEFAULT_SORT_ORDER
/* Artist sort order Z-A */
val ARTIST_Z_A = "$ARTIST_A_Z DESC"
const val ARTIST_Z_A = "$ARTIST_A_Z DESC"
/* Artist sort order number of songs */
val ARTIST_NUMBER_OF_SONGS = MediaStore.Audio.Artists.NUMBER_OF_TRACKS + " DESC"
const val ARTIST_NUMBER_OF_SONGS = MediaStore.Audio.Artists.NUMBER_OF_TRACKS + " DESC"
/* Artist sort order number of albums */
val ARTIST_NUMBER_OF_ALBUMS = MediaStore.Audio.Artists.NUMBER_OF_ALBUMS + " DESC"
const val ARTIST_NUMBER_OF_ALBUMS = MediaStore.Audio.Artists.NUMBER_OF_ALBUMS + " DESC"
}
}
@ -49,20 +49,20 @@ class SortOrder {
companion object {
/* Album sort order A-Z */
val ALBUM_A_Z = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER
const val ALBUM_A_Z = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER
/* Album sort order Z-A */
val ALBUM_Z_A = "$ALBUM_A_Z DESC"
const val ALBUM_Z_A = "$ALBUM_A_Z DESC"
/* Album sort order songs */
val ALBUM_NUMBER_OF_SONGS = MediaStore.Audio.Albums.NUMBER_OF_SONGS + " DESC"
const val ALBUM_NUMBER_OF_SONGS = MediaStore.Audio.Albums.NUMBER_OF_SONGS + " DESC"
/* Album sort order artist */
val ALBUM_ARTIST = (MediaStore.Audio.Artists.DEFAULT_SORT_ORDER
const val ALBUM_ARTIST = (MediaStore.Audio.Artists.DEFAULT_SORT_ORDER
+ ", " + MediaStore.Audio.Albums.DEFAULT_SORT_ORDER)
/* Album sort order year */
val ALBUM_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
const val ALBUM_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
}
}
@ -73,25 +73,25 @@ class SortOrder {
companion object {
/* Song sort order A-Z */
val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
const val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
/* Song sort order Z-A */
val SONG_Z_A = "$SONG_A_Z DESC"
const val SONG_Z_A = "$SONG_A_Z DESC"
/* Song sort order artist */
val SONG_ARTIST = MediaStore.Audio.Artists.DEFAULT_SORT_ORDER
const val SONG_ARTIST = MediaStore.Audio.Artists.DEFAULT_SORT_ORDER
/* Song sort order album */
val SONG_ALBUM = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER
const val SONG_ALBUM = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER
/* Song sort order year */
val SONG_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
const val SONG_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
/* Song sort order duration */
val SONG_DURATION = MediaStore.Audio.Media.DURATION + " DESC"
const val SONG_DURATION = MediaStore.Audio.Media.DURATION + " DESC"
/* Song sort order date */
val SONG_DATE = MediaStore.Audio.Media.DATE_ADDED + " DESC"
const val SONG_DATE = MediaStore.Audio.Media.DATE_ADDED + " DESC"
}
}
@ -102,17 +102,17 @@ class SortOrder {
companion object {
/* Album song sort order A-Z */
val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
const val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
/* Album song sort order Z-A */
val SONG_Z_A = "$SONG_A_Z DESC"
const val SONG_Z_A = "$SONG_A_Z DESC"
/* Album song sort order track list */
val SONG_TRACK_LIST = (MediaStore.Audio.Media.TRACK + ", "
const val SONG_TRACK_LIST = (MediaStore.Audio.Media.TRACK + ", "
+ MediaStore.Audio.Media.DEFAULT_SORT_ORDER)
/* Album song sort order duration */
val SONG_DURATION = SongSortOrder.SONG_DURATION
const val SONG_DURATION = SongSortOrder.SONG_DURATION
}
}
@ -123,22 +123,22 @@ class SortOrder {
companion object {
/* Artist song sort order A-Z */
val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
const val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
/* Artist song sort order Z-A */
val SONG_Z_A = "$SONG_A_Z DESC"
const val SONG_Z_A = "$SONG_A_Z DESC"
/* Artist song sort order album */
val SONG_ALBUM = MediaStore.Audio.Media.ALBUM
const val SONG_ALBUM = MediaStore.Audio.Media.ALBUM
/* Artist song sort order year */
val SONG_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
const val SONG_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
/* Artist song sort order duration */
val SONG_DURATION = MediaStore.Audio.Media.DURATION + " DESC"
const val SONG_DURATION = MediaStore.Audio.Media.DURATION + " DESC"
/* Artist song sort order date */
val SONG_DATE = MediaStore.Audio.Media.DATE_ADDED + " DESC"
const val SONG_DATE = MediaStore.Audio.Media.DATE_ADDED + " DESC"
}
}
@ -149,16 +149,16 @@ class SortOrder {
companion object {
/* Artist album sort order A-Z */
val ALBUM_A_Z = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER
const val ALBUM_A_Z = MediaStore.Audio.Albums.DEFAULT_SORT_ORDER
/* Artist album sort order Z-A */
val ALBUM_Z_A = "$ALBUM_A_Z DESC"
const val ALBUM_Z_A = "$ALBUM_A_Z DESC"
/* Artist album sort order year */
val ALBUM_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
const val ALBUM_YEAR = MediaStore.Audio.Media.YEAR + " DESC"
/* Artist album sort order year */
val ALBUM_YEAR_ASC = MediaStore.Audio.Media.YEAR + " ASC"
const val ALBUM_YEAR_ASC = MediaStore.Audio.Media.YEAR + " ASC"
}
}
@ -169,10 +169,10 @@ class SortOrder {
companion object {
/* Genre sort order A-Z */
val GENRE_A_Z = MediaStore.Audio.Genres.DEFAULT_SORT_ORDER
const val GENRE_A_Z = MediaStore.Audio.Genres.DEFAULT_SORT_ORDER
/* Genre sort order Z-A */
val ALBUM_Z_A = "$GENRE_A_Z DESC"
const val ALBUM_Z_A = "$GENRE_A_Z DESC"
}
}

View File

@ -2,18 +2,17 @@ package code.name.monkey.retromusic.loaders
import android.content.Context
import android.text.TextUtils
import java.util.ArrayList
import code.name.monkey.retromusic.R
import io.reactivex.Observable
import java.util.*
object SearchLoader {
fun searchAll(context: Context, query: String): Observable<ArrayList<Any>> {
fun searchAll(context: Context, query: String?): Observable<ArrayList<Any>> {
val results = ArrayList<Any>()
return Observable.create { e ->
if (!TextUtils.isEmpty(query)) {
SongLoader.getSongs(context, query)
SongLoader.getSongs(context, query!!)
.subscribe { songs ->
if (!songs.isEmpty()) {
results.add(context.resources.getString(R.string.songs))

View File

@ -114,7 +114,7 @@ object SongLoader {
return newSelectionValues
}
fun getSong(cursor: Cursor?): Observable<Song> {
private fun getSong(cursor: Cursor?): Observable<Song> {
return Observable.create { e ->
val song: Song = if (cursor != null && cursor.moveToFirst()) {
getSongFromCursorImpl(cursor)

View File

@ -2,8 +2,7 @@ package code.name.monkey.retromusic.mvp.contract
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
import java.util.ArrayList
import java.util.*
/**
@ -14,6 +13,6 @@ interface SearchContract {
interface SearchView : BaseView<ArrayList<Any>>
interface SearchPresenter : BasePresenter<SearchView> {
fun search(query: String)
fun search(query: String?)
}
}

View File

@ -27,7 +27,7 @@ class SearchPresenter(private val view: SearchContract.SearchView) : Presenter()
}
}
override fun search(query: String) {
override fun search(query: String?) {
disposable.add(repository.search(query)
.debounce(500, TimeUnit.MILLISECONDS)
.subscribeOn(schedulerProvider.computation())

View File

@ -1,169 +0,0 @@
package code.name.monkey.retromusic.providers;
import android.content.Context;
import java.io.File;
import java.util.ArrayList;
import code.name.monkey.retromusic.Injection;
import code.name.monkey.retromusic.App;
import code.name.monkey.retromusic.loaders.AlbumLoader;
import code.name.monkey.retromusic.loaders.ArtistLoader;
import code.name.monkey.retromusic.loaders.GenreLoader;
import code.name.monkey.retromusic.loaders.HomeLoader;
import code.name.monkey.retromusic.loaders.LastAddedSongsLoader;
import code.name.monkey.retromusic.loaders.PlaylistLoader;
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader;
import code.name.monkey.retromusic.loaders.SearchLoader;
import code.name.monkey.retromusic.loaders.SongLoader;
import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist;
import code.name.monkey.retromusic.providers.interfaces.Repository;
import code.name.monkey.retromusic.rest.model.KuGouRawLyric;
import code.name.monkey.retromusic.rest.model.KuGouSearchLyricResult;
import code.name.monkey.retromusic.rest.service.KuGouApiService;
import code.name.monkey.retromusic.util.LyricUtil;
import io.reactivex.Observable;
import io.reactivex.schedulers.Schedulers;
public class RepositoryImpl implements Repository {
private static RepositoryImpl INSTANCE;
private Context context;
public RepositoryImpl(Context context) {
this.context = context;
}
public static synchronized RepositoryImpl getInstance() {
if (INSTANCE == null) {
INSTANCE = new RepositoryImpl(App.Companion.getInstance());
}
return INSTANCE;
}
@Override
public Observable<ArrayList<Song>> getAllSongs() {
return SongLoader.INSTANCE.getAllSongs(context);
}
@Override
public Observable<ArrayList<Song>> getSuggestionSongs() {
return SongLoader.INSTANCE.suggestSongs(context);
}
@Override
public Observable<Song> getSong(int id) {
return SongLoader.INSTANCE.getSong(context, id);
}
@Override
public Observable<ArrayList<Album>> getAllAlbums() {
return AlbumLoader.Companion.getAllAlbums(context);
}
@Override
public Observable<ArrayList<Album>> getRecentAlbums() {
return LastAddedSongsLoader.INSTANCE.getLastAddedAlbums(context);
}
@Override
public Observable<ArrayList<Album>> getTopAlbums() {
return TopAndRecentlyPlayedTracksLoader.INSTANCE.getTopAlbums(context);
}
@Override
public Observable<Album> getAlbum(int albumId) {
return AlbumLoader.Companion.getAlbum(context, albumId);
}
@Override
public Observable<ArrayList<Artist>> getAllArtists() {
return ArtistLoader.INSTANCE.getAllArtists(context);
}
@Override
public Observable<ArrayList<Artist>> getRecentArtists() {
return LastAddedSongsLoader.INSTANCE.getLastAddedArtists(context);
}
@Override
public Observable<ArrayList<Artist>> getTopArtists() {
return TopAndRecentlyPlayedTracksLoader.INSTANCE.getTopArtists(context);
}
@Override
public Observable<Artist> getArtistById(long artistId) {
return ArtistLoader.INSTANCE.getArtist(context, (int) artistId);
}
@Override
public Observable<ArrayList<Playlist>> getAllPlaylists() {
return PlaylistLoader.INSTANCE.getAllPlaylists(context);
}
@Override
public Observable<ArrayList<Song>> getFavoriteSongs() {
return null;
}
@Override
public Observable<ArrayList<Object>> search(String query) {
return SearchLoader.INSTANCE.searchAll(context, query);
}
@Override
public Observable<ArrayList<Song>> getPlaylistSongs(Playlist playlist) {
return PlaylistSongsLoader.INSTANCE.getPlaylistSongList(context, playlist);
}
@Override
public Observable<ArrayList<Playlist>> getHomeList() {
return HomeLoader.INSTANCE.getHomeLoader(context);
}
@Override
public Observable<ArrayList<AbsSmartPlaylist>> getAllThings() {
return HomeLoader.INSTANCE.getRecentAndTopThings(context);
}
@Override
public Observable<ArrayList<Genre>> getAllGenres() {
return GenreLoader.INSTANCE.getAllGenres(context);
}
@Override
public Observable<ArrayList<Song>> getGenre(int genreId) {
return GenreLoader.INSTANCE.getSongs(context, genreId);
}
@Override
public Observable<File> downloadLrcFile(String title, String artist, long duration) {
KuGouApiService service = Injection.INSTANCE.provideKuGouApiService();
return service.searchLyric(title, String.valueOf(duration))
.subscribeOn(Schedulers.io())
.flatMap(kuGouSearchLyricResult -> {
if (kuGouSearchLyricResult.status == 200
&& kuGouSearchLyricResult.candidates != null
&& kuGouSearchLyricResult.candidates.size() != 0) {
KuGouSearchLyricResult.Candidates candidates = kuGouSearchLyricResult.candidates.get(0);
return service.getRawLyric(candidates.id, candidates.accesskey);
} else {
return Observable.just(new KuGouRawLyric());
}
}).map(kuGouRawLyric -> {
if (kuGouRawLyric == null) {
return null;
}
String rawLyric = LyricUtil.decryptBASE64(kuGouRawLyric.content);
if (rawLyric != null && rawLyric.isEmpty()) {
return null;
}
return LyricUtil.writeLrcToLoc(title, artist, rawLyric);
});
}
}

View File

@ -0,0 +1,86 @@
package code.name.monkey.retromusic.providers
import android.content.Context
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.loaders.*
import code.name.monkey.retromusic.model.*
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist
import code.name.monkey.retromusic.providers.interfaces.Repository
import io.reactivex.Observable
import java.util.*
class RepositoryImpl(private val context: Context) : Repository {
override val allSongs: Observable<ArrayList<Song>>
get() = SongLoader.getAllSongs(context)
override val suggestionSongs: Observable<ArrayList<Song>>
get() = SongLoader.suggestSongs(context)
override val allAlbums: Observable<ArrayList<Album>>
get() = AlbumLoader.getAllAlbums(context)
override val recentAlbums: Observable<ArrayList<Album>>
get() = LastAddedSongsLoader.getLastAddedAlbums(context)
override val topAlbums: Observable<ArrayList<Album>>
get() = TopAndRecentlyPlayedTracksLoader.getTopAlbums(context)
override val allArtists: Observable<ArrayList<Artist>>
get() = ArtistLoader.getAllArtists(context)
override val recentArtists: Observable<ArrayList<Artist>>
get() = LastAddedSongsLoader.getLastAddedArtists(context)
override val topArtists: Observable<ArrayList<Artist>>
get() = TopAndRecentlyPlayedTracksLoader.getTopArtists(context)
override val allPlaylists: Observable<ArrayList<Playlist>>
get() = PlaylistLoader.getAllPlaylists(context)
override val homeList: Observable<ArrayList<Playlist>>
get() = HomeLoader.getHomeLoader(context)
override val allThings: Observable<ArrayList<AbsSmartPlaylist>>
get() = HomeLoader.getRecentAndTopThings(context)
override val allGenres: Observable<ArrayList<Genre>>
get() = GenreLoader.getAllGenres(context)
override fun getSong(id: Int): Observable<Song> {
return SongLoader.getSong(context, id)
}
override fun getAlbum(albumId: Int): Observable<Album> {
return AlbumLoader.getAlbum(context, albumId)
}
override fun getArtistById(artistId: Long): Observable<Artist> {
return ArtistLoader.getArtist(context, artistId.toInt())
}
override fun search(query: String?): Observable<ArrayList<Any>> {
return SearchLoader.searchAll(context, query)
}
override fun getPlaylistSongs(playlist: Playlist): Observable<ArrayList<Song>> {
return PlaylistSongsLoader.getPlaylistSongList(context, playlist)
}
override fun getGenre(genreId: Int): Observable<ArrayList<Song>> {
return GenreLoader.getSongs(context, genreId)
}
companion object {
private var INSTANCE: RepositoryImpl? = null
val instance: RepositoryImpl
@Synchronized get() {
if (INSTANCE == null) {
INSTANCE = RepositoryImpl(App.instance)
}
return INSTANCE!!
}
}
}

View File

@ -1,14 +1,9 @@
package code.name.monkey.retromusic.providers.interfaces
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.model.*
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist
import io.reactivex.Observable
import java.io.File
import java.util.ArrayList
import java.util.*
/**
* Created by hemanths on 11/08/17.
@ -34,8 +29,6 @@ interface Repository {
val allPlaylists: Observable<ArrayList<Playlist>>
val favoriteSongs: Observable<ArrayList<Song>>
val homeList: Observable<ArrayList<Playlist>>
val allThings: Observable<ArrayList<AbsSmartPlaylist>>
@ -46,15 +39,13 @@ interface Repository {
fun getAlbum(albumId: Int): Observable<Album>
fun getArtistById(artistId: Long): Observable<Artist>
fun search(query: String): Observable<ArrayList<Any>>
fun search(query: String?): Observable<ArrayList<Any>>
fun getPlaylistSongs(playlist: Playlist): Observable<ArrayList<Song>>
fun getGenre(genreId: Int): Observable<ArrayList<Song>>
fun downloadLrcFile(title: String, artist: String, duration: Long): Observable<File>
}

View File

@ -2,6 +2,7 @@ package code.name.monkey.retromusic.service;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@ -47,6 +48,10 @@ import java.util.Random;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.appwidgets.AppWidgetBig;
import code.name.monkey.retromusic.appwidgets.AppWidgetCard;
import code.name.monkey.retromusic.appwidgets.AppWidgetClassic;
import code.name.monkey.retromusic.appwidgets.AppWidgetSmall;
import code.name.monkey.retromusic.glide.BlurTransformation;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.helper.ShuffleHelper;
@ -92,12 +97,10 @@ import static code.name.monkey.retromusic.Constants.SHUFFLE_MODE_CHANGED;
*/
public class MusicService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks {
public static final String TAG = MusicService.class.getSimpleName();
public static final String SAVED_POSITION = "POSITION";
public static final String SAVED_POSITION_IN_TRACK = "POSITION_IN_TRACK";
public static final String SAVED_SHUFFLE_MODE = "SHUFFLE_MODE";
public static final String SAVED_REPEAT_MODE = "REPEAT_MODE";
public static final int RELEASE_WAKELOCK = 0;
public static final int TRACK_ENDED = 1;
public static final int TRACK_WENT_TO_NEXT = 2;
@ -122,11 +125,35 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
| PlaybackStateCompat.ACTION_STOP
| PlaybackStateCompat.ACTION_SEEK_TO;
private final IBinder musicBind = new MusicBinder();
private AppWidgetBig appWidgetBig = AppWidgetBig.Companion.getInstance();
private AppWidgetClassic appWidgetClassic = AppWidgetClassic.Companion.getInstance();
private AppWidgetSmall appWidgetSmall = AppWidgetSmall.Companion.getInstance();
private AppWidgetCard appWidgetCard = AppWidgetCard.Companion.getInstance();
private final BroadcastReceiver widgetIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final String command = intent.getStringExtra(EXTRA_APP_WIDGET_NAME);
final int[] ids = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
switch (command) {
case AppWidgetClassic.NAME: {
appWidgetClassic.performUpdate(MusicService.this, ids);
break;
}
case AppWidgetSmall.NAME: {
appWidgetSmall.performUpdate(MusicService.this, ids);
break;
}
case AppWidgetBig.NAME: {
appWidgetBig.performUpdate(MusicService.this, ids);
break;
}
case AppWidgetCard.NAME: {
appWidgetCard.performUpdate(MusicService.this, ids);
break;
}
}
}
};
private Playback playback;
@ -1083,7 +1110,10 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
private void sendChangeInternal(final String what) {
sendBroadcast(new Intent(what));
appWidgetBig.notifyChange(this, what);
appWidgetClassic.notifyChange(this, what);
appWidgetSmall.notifyChange(this, what);
appWidgetCard.notifyChange(this, what);
}
private void handleChangeInternal(@NonNull final String what) {

View File

@ -45,10 +45,8 @@ class PlayingNotificationImpl : PlayingNotification() {
val isPlaying = service.isPlaying
val notificationLayout = RemoteViews(service.packageName,
R.layout.notification)
val notificationLayoutBig = RemoteViews(service.packageName,
R.layout.notification_big)
val notificationLayout = RemoteViews(service.packageName, R.layout.notification)
val notificationLayoutBig = RemoteViews(service.packageName, R.layout.notification_big)
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) {
notificationLayout.setViewVisibility(R.id.media_titles, View.INVISIBLE)
@ -58,8 +56,7 @@ class PlayingNotificationImpl : PlayingNotification() {
notificationLayout.setTextViewText(R.id.text, song.artistName)
}
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName) && TextUtils
.isEmpty(song.albumName)) {
if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName) && TextUtils.isEmpty(song.albumName)) {
notificationLayoutBig.setViewVisibility(R.id.media_titles, View.INVISIBLE)
} else {
notificationLayoutBig.setViewVisibility(R.id.media_titles, View.VISIBLE)

View File

@ -0,0 +1,82 @@
package code.name.monkey.retromusic.ui.activities
import android.os.Bundle
import android.view.View
import androidx.core.view.ViewCompat
import android.view.WindowManager
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.r0adkll.slidr.Slidr
import com.r0adkll.slidr.model.SlidrConfig
import com.r0adkll.slidr.model.SlidrPosition
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.ui.activities.base.AbsMusicServiceActivity
import code.name.monkey.retromusic.ui.fragments.player.lockscreen.LockScreenPlayerControlsFragment
class LockScreenActivity : AbsMusicServiceActivity() {
private var mFragment: LockScreenPlayerControlsFragment? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
or WindowManager.LayoutParams.FLAG_FULLSCREEN
or WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
setDrawUnderStatusBar()
setContentView(R.layout.activity_lock_screen_old_style)
hideStatusBar()
setStatusbarColorAuto()
setNavigationbarColorAuto()
setTaskDescriptionColorAuto()
setLightNavigationBar(true)
val config = SlidrConfig.Builder()
.position(SlidrPosition.BOTTOM)
.build()
Slidr.attach(this, config)
mFragment = supportFragmentManager.findFragmentById(R.id.playback_controls_fragment) as LockScreenPlayerControlsFragment?
findViewById<View>(R.id.slide).setTranslationY(100f)
findViewById<View>(R.id.slide).setAlpha(0f)
ViewCompat.animate(findViewById<View>(R.id.slide))
.translationY(0f)
.alpha(1f)
.setDuration(1500)
.start()
findViewById<View>(R.id.root_layout).setBackgroundColor(ThemeStore.primaryColor(this))
}
override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged()
updateSongs()
}
override fun onServiceConnected() {
super.onServiceConnected()
updateSongs()
}
private fun updateSongs() {
val song = MusicPlayerRemote.currentSong
SongGlideRequest.Builder.from(Glide.with(this), song)
.checkIgnoreMediaStore(this)
.generatePalette(this)
.build().into(object : RetroMusicColoredTarget(findViewById(R.id.image)) {
override fun onColorReady(color: Int) {
mFragment!!.setDark(color)
}
})
}
}

View File

@ -1,168 +1,104 @@
package code.name.monkey.retromusic.ui.activities
import android.annotation.SuppressLint
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.os.AsyncTask
import android.os.Bundle
import android.text.InputType
import android.text.TextUtils
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import android.widget.RadioButton
import android.view.*
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.model.lyrics.Lyrics
import code.name.monkey.retromusic.ui.activities.base.AbsMusicServiceActivity
import code.name.monkey.retromusic.ui.activities.tageditor.WriteTagsAsyncTask
import code.name.monkey.retromusic.ui.fragments.base.AbsMusicServiceFragment
import code.name.monkey.retromusic.util.LyricUtil
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.RetroUtil
import com.afollestad.materialdialogs.MaterialDialog
import com.bumptech.glide.Glide
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.activity_lyrics.*
import kotlinx.android.synthetic.main.fragment_lyrics.*
import kotlinx.android.synthetic.main.fragment_synced.*
import org.jaudiotagger.tag.FieldKey
import java.io.File
import java.util.*
class LyricsActivity : AbsMusicServiceActivity(), MusicProgressViewUpdateHelper.Callback, View.OnClickListener {
class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener {
override fun onClick(v: View?) {
when (viewPager.currentItem) {
0 -> showSyncedLyrics()
1 -> showLyricsSaveDialog()
}
}
private var updateHelper: MusicProgressViewUpdateHelper? = null
private var updateLyricsAsyncTask: AsyncTask<*, *, *>? = null
private var disposable: CompositeDisposable? = null
private var song: Song? = null
private lateinit var song: Song
private var lyrics: Lyrics? = null
private val googleSearchLrcUrl: String
get() {
var baseUrl = "http://www.google.com/search?"
var query = song!!.title + "+" + song!!.artistName
var query = song.title + "+" + song.artistName
query = "q=" + query.replace(" ", "+") + " .lrc"
baseUrl += query
return baseUrl
}
override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar()
//setDrawUnderNavigationBar();
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_lyrics)
setStatusbarColorAuto()
setTaskDescriptionColorAuto()
setNavigationbarColorAuto()
setLightStatusbar(true)
container.isFit = !PreferenceUtil.getInstance().fullScreenMode
toolbar.setBackgroundColor(ThemeStore.primaryColor(this))
toolbar.navigationIcon = TintHelper.createTintedDrawable(ContextCompat.getDrawable(this@LyricsActivity, R.drawable.ic_keyboard_backspace_black_24dp), ThemeStore.textColorSecondary(this@LyricsActivity))
appBarLayout.setBackgroundColor(ThemeStore.primaryColor(this))
setSupportActionBar(toolbar)
setSupportActionBar(bottomAppBar)
Objects.requireNonNull<Drawable>(bottomAppBar!!.navigationIcon)
.setColorFilter(ThemeStore.textColorPrimary(this), PorterDuff.Mode.SRC_IN)
bottomAppBar!!.backgroundTint = ColorStateList.valueOf(ThemeStore.primaryColor(this))
TintHelper.setTintAuto(fab, ThemeStore.accentColor(this), true)
updateHelper = MusicProgressViewUpdateHelper(this, 500, 1000)
setupLyricsView()
setupWakelock()
loadLrcFile()
actions.setOnCheckedChangeListener { _, checkedId -> selectLyricsTye(checkedId) }
actions.check(PreferenceUtil.getInstance().lastLyricsType)
viewPager.apply {
adapter = PagerAdapter(supportFragmentManager)
}
tabs.apply {
setupWithViewPager(viewPager)
setSelectedTabIndicator(TintHelper.createTintedDrawable(ContextCompat.getDrawable(this@LyricsActivity, R.drawable.tab_indicator), ThemeStore.accentColor(this@LyricsActivity)))
setTabTextColors(ThemeStore.textColorSecondary(this@LyricsActivity), ThemeStore.accentColor(this@LyricsActivity))
setSelectedTabIndicatorColor(ThemeStore.accentColor(context))
}
fab.setOnClickListener(this)
}
private fun selectLyricsTye(group: Int) {
PreferenceUtil.getInstance().lastLyricsType = group
val radioButton = actions.findViewById<RadioButton>(group)
if (radioButton != null) {
radioButton.backgroundTintList = ColorStateList.valueOf(Color.WHITE)
//radioButton.setTextColor(ThemeStore.textColorPrimary(this));
}
offlineLyrics!!.visibility = View.GONE
lyricsView.visibility = View.GONE
when (group) {
R.id.syncedLyrics -> {
loadLRCLyrics()
lyricsView!!.visibility = View.VISIBLE
}
R.id.normalLyrics -> {
loadSongLyrics()
offlineLyrics!!.visibility = View.VISIBLE
}
else -> {
loadSongLyrics()
offlineLyrics!!.visibility = View.VISIBLE
}
}
}
private fun loadLRCLyrics() {
if (LyricUtil.isLrcFileExist(song!!.title, song!!.artistName)) {
showLyricsLocal(LyricUtil.getLocalLyricFile(song!!.title, song!!.artistName))
}
}
private fun setupWakelock() {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
private fun setupLyricsView() {
disposable = CompositeDisposable()
lyricsView!!.apply {
setOnPlayerClickListener { progress, _ -> MusicPlayerRemote.seekTo(progress.toInt()) }
//lyricView.setHighLightTextColor(ThemeStore.accentColor(this));
setDefaultColor(ContextCompat.getColor(this@LyricsActivity, R.color.md_grey_400))
//lyricView.setTouchable(false);
setHintColor(Color.WHITE)
}
}
override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged()
loadLrcFile()
}
override fun onResume() {
super.onResume()
updateHelper!!.start()
}
override fun onPause() {
super.onPause()
updateHelper!!.stop()
song = MusicPlayerRemote.currentSong
toolbar.title = song.title
toolbar.subtitle = song.artistName
}
override fun onServiceConnected() {
super.onServiceConnected()
loadLrcFile()
song = MusicPlayerRemote.currentSong
toolbar.title = song.title
toolbar.subtitle = song.artistName
}
override fun onDestroy() {
super.onDestroy()
disposable!!.clear()
if (updateLyricsAsyncTask != null && !updateLyricsAsyncTask!!.isCancelled) {
updateLyricsAsyncTask!!.cancel(true)
}
private fun setupWakelock() {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -172,84 +108,10 @@ class LyricsActivity : AbsMusicServiceActivity(), MusicProgressViewUpdateHelper.
return super.onOptionsItemSelected(item)
}
override fun onUpdateProgressViews(progress: Int, total: Int) {
lyricsView!!.setCurrentTimeMillis(progress.toLong())
}
private fun loadLrcFile() {
song = MusicPlayerRemote.currentSong
bottomAppBar.title = song!!.title
bottomAppBar.subtitle = song!!.artistName
SongGlideRequest.Builder.from(Glide.with(this), song!!)
.checkIgnoreMediaStore(this)
.generatePalette(this)
.build()
.into(object : RetroMusicColoredTarget(findViewById(R.id.image)) {
override fun onColorReady(color: Int) {
if (PreferenceUtil.getInstance().adaptiveColor) {
//background.setBackgroundColor(color);
}
}
})
}
private fun showLyricsLocal(file: File?) {
if (file == null) {
lyricsView!!.reset()
} else {
lyricsView!!.setLyricFile(file, "UTF-8")
}
}
override fun onClick(view: View) {
when (view.id) {
android.R.id.home -> onBackPressed()
R.id.fab -> when (actions.checkedRadioButtonId) {
R.id.syncedLyrics -> showSyncedLyrics()
R.id.normalLyrics -> showLyricsSaveDialog()
}
}
}
@SuppressLint("StaticFieldLeak")
private fun loadSongLyrics() {
if (updateLyricsAsyncTask != null) {
updateLyricsAsyncTask!!.cancel(false)
}
val song = MusicPlayerRemote.currentSong
updateLyricsAsyncTask = object : AsyncTask<Void, Void, Lyrics>() {
override fun doInBackground(vararg params: Void): Lyrics? {
val data = MusicUtil.getLyrics(song)
return if (TextUtils.isEmpty(data)) {
null
} else Lyrics.parse(song, data)
}
override fun onPreExecute() {
super.onPreExecute()
lyrics = null
}
override fun onPostExecute(l: Lyrics?) {
lyrics = l
offlineLyrics!!.visibility = View.VISIBLE
if (l == null) {
offlineLyrics!!.setText(R.string.no_lyrics_found)
return
}
offlineLyrics!!.text = l.data
}
override fun onCancelled(s: Lyrics) {
onPostExecute(null)
}
}.execute()
}
private fun showSyncedLyrics() {
var content = ""
try {
content = LyricUtil.getStringFromFile(song!!.title, song!!.artistName)
content = LyricUtil.getStringFromFile(song.title, song.artistName)
} catch (e: Exception) {
e.printStackTrace()
}
@ -260,14 +122,12 @@ class LyricsActivity : AbsMusicServiceActivity(), MusicProgressViewUpdateHelper.
.content("Add time frame lyrics")
.negativeText("Delete")
.onNegative { _, _ ->
LyricUtil.deleteLrcFile(song!!.title, song!!.artistName)
loadLrcFile()
LyricUtil.deleteLrcFile(song.title, song.artistName)
}
.onNeutral { _, _ -> RetroUtil.openUrl(this@LyricsActivity, googleSearchLrcUrl) }
.inputType(InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE)
.input("Paste lyrics here", content) { _, input ->
LyricUtil.writeLrcToLoc(song!!.title, song!!.artistName, input.toString())
loadLrcFile()
LyricUtil.writeLrcToLoc(song.title, song.artistName, input.toString())
}.show()
}
@ -280,13 +140,12 @@ class LyricsActivity : AbsMusicServiceActivity(), MusicProgressViewUpdateHelper.
MaterialDialog.Builder(this)
.title("Add lyrics")
.neutralText("Search")
.onNeutral { _, _ -> RetroUtil.openUrl(this@LyricsActivity, getGoogleSearchUrl(song!!.title, song!!.artistName)) }
.onNeutral { _, _ -> RetroUtil.openUrl(this@LyricsActivity, getGoogleSearchUrl(song.title, song.artistName)) }
.inputType(InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_MULTI_LINE)
.input("Paste lyrics here", content) { _, input ->
val fieldKeyValueMap = EnumMap<FieldKey, String>(FieldKey::class.java)
fieldKeyValueMap[FieldKey.LYRICS] = input.toString()
WriteTagsAsyncTask(this@LyricsActivity).execute(WriteTagsAsyncTask.LoadingInfo(getSongPaths(song!!), fieldKeyValueMap, null))
loadLrcFile()
WriteTagsAsyncTask(this@LyricsActivity).execute(WriteTagsAsyncTask.LoadingInfo(getSongPaths(song), fieldKeyValueMap, null))
}
.show()
}
@ -305,3 +164,154 @@ class LyricsActivity : AbsMusicServiceActivity(), MusicProgressViewUpdateHelper.
return baseUrl
}
}
class PagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
override fun getItem(position: Int): Fragment {
return when (position) {
0 -> SyncedLyricsFragment()
1 -> OfflineLyricsFragment()
else -> {
SyncedLyricsFragment()
}
}
}
override fun getPageTitle(position: Int): CharSequence? {
return when (position) {
0 -> App.context.getString(R.string.synced_lyrics)
1 -> App.context.getString(R.string.normal_lyrics)
else -> {
App.context.getString(R.string.synced_lyrics)
}
}
}
override fun getCount(): Int {
return 2
}
}
class OfflineLyricsFragment : AbsMusicServiceFragment() {
private var updateLyricsAsyncTask: AsyncTask<*, *, *>? = null
private var lyrics: Lyrics? = null
@SuppressLint("StaticFieldLeak")
private fun loadSongLyrics() {
if (updateLyricsAsyncTask != null) {
updateLyricsAsyncTask!!.cancel(false)
}
val song = MusicPlayerRemote.currentSong
updateLyricsAsyncTask = object : AsyncTask<Void?, Void?, Lyrics?>() {
override fun doInBackground(vararg params: Void?): Lyrics? {
val data = MusicUtil.getLyrics(song)
return if (TextUtils.isEmpty(data)) {
null
} else Lyrics.parse(song, data)
}
override fun onPreExecute() {
super.onPreExecute()
lyrics = null
}
override fun onPostExecute(l: Lyrics?) {
lyrics = l
offlineLyrics.visibility = View.VISIBLE
if (l == null) {
offlineLyrics.setText(R.string.no_lyrics_found)
return
}
offlineLyrics.text = l.data
}
override fun onCancelled(s: Lyrics?) {
onPostExecute(null)
}
}.execute()
}
override fun onDestroyView() {
super.onDestroyView()
if (updateLyricsAsyncTask != null && !updateLyricsAsyncTask!!.isCancelled) {
updateLyricsAsyncTask!!.cancel(true)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
loadSongLyrics()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_lyrics, container, false)
}
}
class SyncedLyricsFragment : AbsMusicServiceFragment(), MusicProgressViewUpdateHelper.Callback {
private lateinit var updateHelper: MusicProgressViewUpdateHelper
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_synced, container, false)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
updateHelper = MusicProgressViewUpdateHelper(this, 500, 1000)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupLyricsView()
}
private fun setupLyricsView() {
lyricsView.apply {
setOnPlayerClickListener { progress, _ -> MusicPlayerRemote.seekTo(progress.toInt()) }
setDefaultColor(ContextCompat.getColor(context, R.color.md_grey_400))
setHintColor(ThemeStore.textColorPrimary(context))
setHighLightColor(ThemeStore.textColorPrimary(context))
setTextSize(RetroUtil.convertDpToPixel(18f, context).toInt())
}
}
override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged()
loadLRCLyrics()
}
override fun onServiceConnected() {
super.onServiceConnected()
loadLRCLyrics()
}
override fun onResume() {
super.onResume()
updateHelper.start()
}
override fun onPause() {
super.onPause()
updateHelper.stop()
}
override fun onUpdateProgressViews(progress: Int, total: Int) {
lyricsView.setCurrentTimeMillis(progress.toLong())
}
private fun loadLRCLyrics() {
val song = MusicPlayerRemote.currentSong
if (LyricUtil.isLrcFileExist(song.title, song.artistName)) {
showLyricsLocal(LyricUtil.getLocalLyricFile(song.title, song.artistName))
}
}
private fun showLyricsLocal(file: File?) {
if (file == null) {
lyricsView!!.reset()
} else {
lyricsView!!.setLyricFile(file, "UTF-8")
}
}
}

View File

@ -11,6 +11,7 @@ import android.util.Log
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.core.app.ActivityCompat
import androidx.core.app.ShareCompat
import androidx.fragment.app.Fragment
import code.name.monkey.appthemehelper.ThemeStore
@ -49,10 +50,10 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
val action = intent.action
if (action != null && action == Intent.ACTION_SCREEN_OFF) {
if (PreferenceUtil.getInstance().lockScreen && MusicPlayerRemote.isPlaying) {
/*Intent activity = new Intent(context, LockScreenActivity.class);
activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
ActivityCompat.startActivity(context, activity, null);*/
val activity = Intent(context, LockScreenActivity::class.java)
activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
activity.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
ActivityCompat.startActivity(context, activity, null)
}
}
}
@ -210,8 +211,14 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
if (!hasPermissions()) {
requestPermissions()
}
checkSetUpPro(); // good chance that pro version check was delayed on first start
}
REQUEST_CODE_THEME, APP_USER_INFO_REQUEST -> postRecreate()
PURCHASE_REQUEST -> {
if (resultCode == RESULT_OK) {
checkSetUpPro();
}
}
}
}
@ -369,10 +376,6 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
return super.onOptionsItemSelected(item)
}
private fun updateNavigationDrawerHeader() {
}
companion object {
const val APP_INTRO_REQUEST = 2323
const val LIBRARY = 1

View File

@ -21,7 +21,7 @@ class PlayingQueueActivity : AbsMusicServiceActivity() {
private var wrappedAdapter: RecyclerView.Adapter<*>? = null
private var recyclerViewDragDropManager: RecyclerViewDragDropManager? = null
private var playingQueueAdapter: PlayingQueueAdapter? = null
private lateinit var layoutManager: LinearLayoutManager
private lateinit var linearLayoutManager: LinearLayoutManager
private val upNextAndQueueTime: String
get() = resources.getString(R.string.up_next) + "" + MusicUtil.getReadableDurationString(MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.position))
@ -54,16 +54,16 @@ class PlayingQueueActivity : AbsMusicServiceActivity() {
R.layout.item_queue)
wrappedAdapter = recyclerViewDragDropManager!!.createWrappedAdapter(playingQueueAdapter!!)
layoutManager = LinearLayoutManager(this)
linearLayoutManager = LinearLayoutManager(this)
recyclerView.apply {
layoutManager = layoutManager
layoutManager = linearLayoutManager
adapter = wrappedAdapter
itemAnimator = animator
recyclerViewDragDropManager!!.attachRecyclerView(this)
}
layoutManager.scrollToPositionWithOffset(MusicPlayerRemote.position + 1, 0)
linearLayoutManager.scrollToPositionWithOffset(MusicPlayerRemote.position + 1, 0)
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
@ -109,7 +109,7 @@ class PlayingQueueActivity : AbsMusicServiceActivity() {
private fun resetToCurrentPosition() {
recyclerView.stopScroll()
layoutManager.scrollToPositionWithOffset(MusicPlayerRemote.position + 1, 0)
linearLayoutManager.scrollToPositionWithOffset(MusicPlayerRemote.position + 1, 0)
}
override fun onPause() {

View File

@ -78,14 +78,13 @@ class ProVersionActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
override fun onProductPurchased(productId: String, details: TransactionDetails?) {
Toast.makeText(this, R.string.thank_you, Toast.LENGTH_SHORT).show()
setResult(Activity.RESULT_OK)
setResult(RESULT_OK)
}
override fun onPurchaseHistoryRestored() {
if (App.isProVersion) {
Toast.makeText(this, R.string.restored_previous_purchase_please_restart, Toast.LENGTH_LONG)
.show()
setResult(Activity.RESULT_OK)
Toast.makeText(this, R.string.restored_previous_purchase_please_restart, Toast.LENGTH_LONG).show()
setResult(RESULT_OK)
} else {
Toast.makeText(this, R.string.no_purchase_found, Toast.LENGTH_SHORT).show()
}
@ -161,7 +160,6 @@ class ProVersionActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {
}
companion object {
private val TAG: String = "ProVersionActivity"
private const val TAG: String = "ProVersionActivity"
}
}

View File

@ -55,7 +55,7 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, SearchCon
if (intent.getBooleanExtra("mic_search", false)) {
startMicSearch()
}
back.setOnClickListener { onBackPressed() }
voiceSearch.setOnClickListener { startMicSearch() }
}
@ -83,7 +83,7 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, SearchCon
override fun onResume() {
super.onResume()
searchPresenter!!.subscribe()
searchPresenter!!.search(query!!)
searchPresenter!!.search(query)
}
override fun onDestroy() {

View File

@ -9,7 +9,9 @@ import androidx.fragment.app.Fragment
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
import code.name.monkey.retromusic.ui.activities.base.AbsBaseActivity
import code.name.monkey.retromusic.ui.fragments.settings.MainSettingsFragment
import code.name.monkey.retromusic.util.PreferenceUtil
@ -32,6 +34,8 @@ class SettingsActivity : AbsBaseActivity(), ColorChooserDialog.ColorCallback, Sh
}
R.string.accent_color -> ThemeStore.editTheme(this).accentColor(selectedColor).commit()
}
if (VersionUtils.hasNougatMR())
DynamicShortcutManager(this).updateDynamicShortcuts()
recreate()
}

View File

@ -12,6 +12,7 @@ import android.text.TextUtils
import android.view.MenuItem
import android.widget.Toast
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.Constants.USER_BANNER
import code.name.monkey.retromusic.Constants.USER_PROFILE
@ -32,13 +33,11 @@ import java.util.*
class UserInfoActivity : AbsBaseActivity() {
private var disposable: CompositeDisposable? = null
private var disposable = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user_info)
setStatusbarColorAuto()
setNavigationbarColorAuto()
setTaskDescriptionColorAuto()
@ -46,8 +45,6 @@ class UserInfoActivity : AbsBaseActivity() {
setupToolbar()
disposable = CompositeDisposable()
bannerTitle.setTextColor(ThemeStore.textColorPrimary(this))
nameContainer.boxStrokeColor = ThemeStore.accentColor(this)
name!!.setText(PreferenceUtil.getInstance().userName)
@ -58,7 +55,7 @@ class UserInfoActivity : AbsBaseActivity() {
if (!PreferenceUtil.getInstance().bannerImage.isEmpty()) {
loadBannerFromStorage(PreferenceUtil.getInstance().bannerImage)
}
bannerImage.setOnClickListener {
userImage.setOnClickListener {
MaterialDialog.Builder(this)
.title("Set a profile photo")
.items(Arrays.asList(getString(R.string.new_profile_photo), getString(R.string.remove_profile_photo)))
@ -82,6 +79,7 @@ class UserInfoActivity : AbsBaseActivity() {
setResult(Activity.RESULT_OK)
finish()
}
TintHelper.setTintAuto(next, ThemeStore.accentColor(this), true)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -96,11 +94,11 @@ class UserInfoActivity : AbsBaseActivity() {
toolbar.apply {
setNavigationIcon(R.drawable.ic_keyboard_backspace_black_24dp)
setBackgroundColor(primaryColor)
ToolbarContentTintHelper.colorBackButton(this, ThemeStore.accentColor(this@UserInfoActivity))
setSupportActionBar(this)
}
appBarLayout.setBackgroundColor(primaryColor)
ToolbarContentTintHelper.colorBackButton(toolbar, ThemeStore.accentColor(this))
title = null
setSupportActionBar(toolbar)
}
private fun showBannerOptions() {
@ -226,8 +224,8 @@ class UserInfoActivity : AbsBaseActivity() {
companion object {
private val PICK_IMAGE_REQUEST = 9002
private val PICK_BANNER_REQUEST = 9003
private val PROFILE_ICON_SIZE = 400
private const val PICK_IMAGE_REQUEST = 9002
private const val PICK_BANNER_REQUEST = 9003
private const val PROFILE_ICON_SIZE = 400
}
}

View File

@ -0,0 +1,94 @@
package code.name.monkey.retromusic.ui.activities;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.webkit.WebView;
import android.widget.TextView;
import com.afollestad.materialdialogs.internal.ThemeSingleton;
import com.google.android.material.appbar.AppBarLayout;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.ui.activities.base.AbsBaseActivity;
import code.name.monkey.retromusic.util.PreferenceUtil;
public class WhatsNewActivity extends AbsBaseActivity {
WebView webView;
TextView title;
Toolbar toolbar;
AppBarLayout appBarLayout;
private static void setChangelogRead(@NonNull Context context) {
try {
PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
int currentVersion = pInfo.versionCode;
PreferenceUtil.getInstance().setLastChangeLogVersion(currentVersion);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
private static String colorToHex(int color) {
return Integer.toHexString(color).substring(2);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_whats_new);
webView = findViewById(R.id.webView);
title = findViewById(R.id.bannerTitle);
toolbar = findViewById(R.id.toolbar);
appBarLayout= findViewById(R.id.appBarLayout);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
toolbar.setBackgroundColor(ThemeStore.primaryColor(this));
appBarLayout.setBackgroundColor(ThemeStore.primaryColor(this));
setSupportActionBar(toolbar);
setTitle(null);
toolbar.setNavigationOnClickListener(v -> onBackPressed());
title.setTextColor(ThemeStore.textColorPrimary(this));
ToolbarContentTintHelper.colorBackButton(toolbar, ThemeStore.accentColor(this));
try {
// Load from phonograph-changelog.html in the assets folder
StringBuilder buf = new StringBuilder();
InputStream json = getAssets().open("retro-changelog.html");
BufferedReader in = new BufferedReader(new InputStreamReader(json, "UTF-8"));
String str;
while ((str = in.readLine()) != null)
buf.append(str);
in.close();
// Inject color values for WebView body background and links
final String backgroundColor = colorToHex(ThemeStore.primaryColor(this));
final String contentColor = ThemeSingleton.get().darkTheme ? "#ffffff" : "#000000";
webView.loadData(buf.toString()
.replace("{style-placeholder}",
String.format("body { background-color: %s; color: %s; }", backgroundColor, contentColor))
.replace("{link-color}", colorToHex(ThemeSingleton.get().positiveColor.getDefaultColor()))
.replace("{link-color-active}", colorToHex(ColorUtil.lightenColor(ThemeSingleton.get().positiveColor.getDefaultColor())))
, "text/html", "UTF-8");
} catch (Throwable e) {
webView.loadData("<h1>Unable to load</h1><p>" + e.getLocalizedMessage() + "</p>", "text/html", "UTF-8");
}
setChangelogRead(this);
}
}

View File

@ -1,74 +0,0 @@
package code.name.monkey.retromusic.ui.activities
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.ui.activities.base.AbsBaseActivity
import code.name.monkey.retromusic.util.PreferenceUtil
import com.afollestad.materialdialogs.internal.ThemeSingleton
import kotlinx.android.synthetic.main.activity_whats_new.*
import java.io.BufferedReader
import java.io.InputStreamReader
class WhatsNewActivity : AbsBaseActivity() {
private fun setChangelogRead(context: Context) {
try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
val currentVersion = pInfo.versionCode
PreferenceUtil.getInstance().setLastChangeLogVersion(currentVersion)
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
}
}
private fun colorToHex(color: Int): String {
return Integer.toHexString(color).substring(2)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_whats_new)
setStatusbarColorAuto()
setNavigationbarColorAuto()
setTaskDescriptionColorAuto()
toolbar.setBackgroundColor(ThemeStore.primaryColor(this))
appBarLayout.setBackgroundColor(ThemeStore.primaryColor(this))
setSupportActionBar(toolbar)
title = null
toolbar.setNavigationOnClickListener { onBackPressed() }
whatNewtitle.setTextColor(ThemeStore.textColorPrimary(this))
ToolbarContentTintHelper.colorBackButton(toolbar, ThemeStore.accentColor(this))
try {
val buf = StringBuilder()
val json = assets.open("retro-changelog.html")
val inputStream = BufferedReader(InputStreamReader(json, "UTF-8"))
while (inputStream.readLine() != null) {
buf.append(inputStream.readLine())
}
inputStream.close()
// Inject color values for WebView body background and links
val backgroundColor = colorToHex(ThemeStore.primaryColor(this))
val contentColor = if (ThemeSingleton.get().darkTheme) "#ffffff" else "#000000"
webView.loadData(buf.toString()
.replace("{style-placeholder}",
String.format("body { background-color: %s; color: %s; }", backgroundColor, contentColor))
.replace("{link-color}", colorToHex(ThemeSingleton.get().positiveColor.defaultColor))
.replace("{link-color-active}", colorToHex(ColorUtil.lightenColor(ThemeSingleton.get().positiveColor.defaultColor))), "text/html", "UTF-8")
} catch (e: Throwable) {
webView.loadData("<h1>Unable to load</h1><p>" + e.localizedMessage + "</p>", "text/html", "UTF-8")
}
setChangelogRead(this)
}
}

View File

@ -10,6 +10,7 @@ import android.view.ViewTreeObserver
import androidx.annotation.FloatRange
import androidx.annotation.LayoutRes
import androidx.fragment.app.Fragment
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote
@ -28,6 +29,7 @@ import code.name.monkey.retromusic.ui.fragments.player.material.MaterialFragment
import code.name.monkey.retromusic.ui.fragments.player.normal.PlayerFragment
import code.name.monkey.retromusic.ui.fragments.player.plain.PlainPlayerFragment
import code.name.monkey.retromusic.ui.fragments.player.simple.SimplePlayerFragment
import code.name.monkey.retromusic.util.ColorUtils
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.views.BottomNavigationBarTinted
import com.google.android.material.bottomnavigation.BottomNavigationView
@ -268,6 +270,13 @@ abstract class AbsSlidingMusicPanelActivity protected constructor() : AbsMusicSe
currentNowPlayingScreen == NowPlayingScreen.BLUR || currentNowPlayingScreen == NowPlayingScreen.BLUR_CARD) {
super.setLightStatusbar(false)
super.setLightNavigationBar(true)
} else if (currentNowPlayingScreen == NowPlayingScreen.COLOR) {
super.setNavigationbarColor(paletteColor)
super.setLightNavigationBar(isColorLight)
super.setLightStatusbar(isColorLight)
} else {
super.setLightStatusbar(ColorUtil.isColorLight(ThemeStore.primaryColor(this)))
super.setLightNavigationBar(true)
}
}
}

View File

@ -59,7 +59,7 @@ open class MediaEntryViewHolder(w: View) : RecyclerView.ViewHolder(w), View.OnCl
recyclerView = w.findViewById(R.id.recycler_view)
mask = w.findViewById(R.id.mask)
playSongs = w.findViewById(R.id.play_songs)
playSongs = w.findViewById(R.id.playSongs)
w.setOnClickListener(this)
w.setOnLongClickListener(this)

View File

@ -177,17 +177,19 @@ open class SongAdapter @JvmOverloads constructor(protected val activity: AppComp
init {
setImageTransitionName(activity.getString(R.string.transition_album_art))
menu!!.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
override val song: Song
get() = this@ViewHolder.song
if (menu != null) {
menu!!.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
override val song: Song
get() = this@ViewHolder.song
override val menuRes: Int
get() = songMenuRes
override val menuRes: Int
get() = songMenuRes
override fun onMenuItemClick(item: MenuItem): Boolean {
return onSongMenuItemClick(item) || super.onMenuItemClick(item)
}
})
override fun onMenuItemClick(item: MenuItem): Boolean {
return onSongMenuItemClick(item) || super.onMenuItemClick(item)
}
})
}
}
protected open fun onSongMenuItemClick(item: MenuItem): Boolean {

View File

@ -9,17 +9,18 @@ enum class NowPlayingScreen constructor(@param:StringRes @field:StringRes
val titleRes: Int,
@param:DrawableRes @field:DrawableRes val drawableResId: Int,
val id: Int) {
NORMAL(R.string.normal, R.drawable.np_normal, 0),
ADAPTIVE(R.string.adaptive, R.drawable.np_adaptive, 10),
BLUR(R.string.blur, R.drawable.np_blur, 4),
BLUR_CARD(R.string.blur_card, R.drawable.np_blur_card, 9),
CARD(R.string.card, R.drawable.np_card, 6),
COLOR(R.string.color, R.drawable.np_color, 5),
FIT(R.string.fit, R.drawable.np_adaptive, 12),
FLAT(R.string.flat, R.drawable.np_flat, 1),
FULL(R.string.full, R.drawable.np_full, 2),
PLAIN(R.string.plain, R.drawable.np_plain, 3),
BLUR(R.string.blur, R.drawable.np_blur, 4),
COLOR(R.string.color, R.drawable.np_color, 5),
CARD(R.string.card, R.drawable.np_card, 6),
//TINY(R.string.tiny, R.drawable.np_tiny, 7),
SIMPLE(R.string.simple, R.drawable.np_simple, 8),
BLUR_CARD(R.string.blur_card, R.drawable.np_blur_card, 9),
ADAPTIVE(R.string.adaptive, R.drawable.np_adaptive, 10),
MATERIAL(R.string.material, R.drawable.np_material, 11),
FIT(R.string.fit, R.drawable.np_adaptive, 12)
NORMAL(R.string.normal, R.drawable.np_normal, 0),
PLAIN(R.string.plain, R.drawable.np_plain, 3),
//TINY(R.string.tiny, R.drawable.np_tiny, 7),
SIMPLE(R.string.simple, R.drawable.np_simple, 8)
}

View File

@ -1,7 +1,6 @@
package code.name.monkey.retromusic.ui.fragments.base
import android.os.Bundle
import code.name.monkey.retromusic.ui.fragments.mainactivity.LibraryFragment
open class AbsLibraryPagerFragment : AbsMusicServiceFragment() {

View File

@ -41,15 +41,15 @@ abstract class AbsLibraryPagerRecyclerViewCustomGridSizeFragment<A : RecyclerVie
activity!!.resources.getInteger(R.integer.default_list_columns_land)
} else activity!!.resources.getInteger(R.integer.default_list_columns)
protected val isLandscape: Boolean
private val isLandscape: Boolean
get() = RetroUtil.isLandscape()
fun getGridSize(): Int {
if (gridSize == 0) {
if (isLandscape) {
gridSize = loadGridSizeLand()
gridSize = if (isLandscape) {
loadGridSizeLand()
} else {
gridSize = loadGridSize()
loadGridSize()
}
}
return gridSize

View File

@ -0,0 +1,461 @@
package code.name.monkey.retromusic.ui.fragments.mainactivity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.afollestad.materialcab.MaterialCab;
import com.google.android.material.appbar.AppBarLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.common.ATHToolbarActivity;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog;
import code.name.monkey.retromusic.dialogs.SleepTimerDialog;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.SortOrder;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks;
import code.name.monkey.retromusic.loaders.SongLoader;
import code.name.monkey.retromusic.ui.activities.SettingsActivity;
import code.name.monkey.retromusic.ui.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment;
import code.name.monkey.retromusic.ui.fragments.base.AbsMainActivityFragment;
import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.util.RetroColorUtil;
import code.name.monkey.retromusic.util.RetroUtil;
public class LibraryFragment extends AbsMainActivityFragment implements CabHolder, MainActivityFragmentCallbacks {
public static final String TAG = "LibraryFragment";
private static final String CURRENT_TAB_ID = "current_tab_id";
private Toolbar toolbar;
private AppBarLayout appBarLayout;
private TextView bannerTitle;
private View contentContainer;
private MaterialCab cab;
private FragmentManager fragmentManager;
public static Fragment newInstance(int tab) {
Bundle args = new Bundle();
args.putInt(CURRENT_TAB_ID, tab);
LibraryFragment fragment = new LibraryFragment();
fragment.setArguments(args);
return fragment;
}
public static Fragment newInstance() {
return new LibraryFragment();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_library, container, false);
contentContainer = view.findViewById(R.id.fragmentContainer);
bannerTitle = view.findViewById(R.id.bannerTitle);
appBarLayout = view.findViewById(R.id.appBarLayout);
toolbar = view.findViewById(R.id.toolbar);
return view;
}
public void setTitle(@StringRes int name) {
bannerTitle.setText(getString(name));
}
public void addOnAppBarOffsetChangedListener(AppBarLayout.OnOffsetChangedListener onOffsetChangedListener) {
appBarLayout.addOnOffsetChangedListener(onOffsetChangedListener);
}
public void removeOnAppBarOffsetChangedListener(AppBarLayout.OnOffsetChangedListener onOffsetChangedListener) {
appBarLayout.removeOnOffsetChangedListener(onOffsetChangedListener);
}
public int getTotalAppBarScrollingRange() {
return appBarLayout.getTotalScrollRange();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setStatusbarColorAuto(view);
setupToolbar();
inflateFragment();
}
private void inflateFragment() {
if (getArguments() == null) {
selectedFragment(SongsFragment.Companion.newInstance());
return;
}
switch (getArguments().getInt(CURRENT_TAB_ID)) {
default:
case R.id.action_song:
selectedFragment(SongsFragment.Companion.newInstance());
break;
case R.id.action_album:
selectedFragment(AlbumsFragment.Companion.newInstance());
break;
case R.id.action_artist:
selectedFragment(ArtistsFragment.Companion.newInstance());
break;
case R.id.action_playlist:
selectedFragment(PlaylistsFragment.Companion.newInstance());
break;
}
}
@SuppressWarnings("ConstantConditions")
private void setupToolbar() {
bannerTitle.setTextColor(ThemeStore.textColorPrimary(getContext()));
int primaryColor = ThemeStore.primaryColor(getContext());
TintHelper.setTintAuto(contentContainer, primaryColor, true);
toolbar.setBackgroundColor(primaryColor);
toolbar.setNavigationIcon(R.drawable.ic_menu_white_24dp);
appBarLayout.setBackgroundColor(primaryColor);
appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) ->
getMainActivity().setLightStatusbar(!ATHUtil.isWindowBackgroundDark(getContext())));
getMainActivity().setTitle(null);
getMainActivity().setSupportActionBar(toolbar);
}
private Fragment getCurrentFragment() {
if (fragmentManager == null) {
return SongsFragment.Companion.newInstance();
}
return fragmentManager.findFragmentByTag(LibraryFragment.TAG);
}
@Override
public boolean handleBackPress() {
if (cab != null && cab.isActive()) {
cab.finish();
return true;
}
return false;
}
private void selectedFragment(Fragment fragment) {
fragmentManager = getChildFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction
.replace(R.id.fragmentContainer, fragment, TAG)
.commit();
}
@NonNull
@Override
public MaterialCab openCab(int menuRes, MaterialCab.Callback callback) {
if (cab != null && cab.isActive()) {
cab.finish();
}
//noinspection ConstantConditions
cab = new MaterialCab(getMainActivity(), R.id.cab_stub)
.setMenu(menuRes)
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
.setBackgroundColor(
RetroColorUtil.shiftBackgroundColorForLightText(ThemeStore.primaryColor(getActivity())))
.start(callback);
return cab;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_main, menu);
Fragment currentFragment = getCurrentFragment();
if (currentFragment instanceof AbsLibraryPagerRecyclerViewCustomGridSizeFragment
&& currentFragment.isAdded()) {
AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment = (AbsLibraryPagerRecyclerViewCustomGridSizeFragment) currentFragment;
MenuItem gridSizeItem = menu.findItem(R.id.action_grid_size);
if (RetroUtil.isLandscape()) {
gridSizeItem.setTitle(R.string.action_grid_size_land);
}
setUpGridSizeMenu(fragment, gridSizeItem.getSubMenu());
setUpSortOrderMenu(fragment, menu.findItem(R.id.action_sort_order).getSubMenu());
} else {
menu.add(0, R.id.action_new_playlist, 0, R.string.new_playlist_title);
menu.removeItem(R.id.action_grid_size);
}
Activity activity = getActivity();
if (activity == null) {
return;
}
ToolbarContentTintHelper.handleOnCreateOptionsMenu(getActivity(), toolbar, menu, ATHToolbarActivity.getToolbarBackgroundColor(toolbar));
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
Activity activity = getActivity();
if (activity == null) {
return;
}
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(activity, toolbar);
}
private void setUpSortOrderMenu(
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment,
@NonNull SubMenu sortOrderMenu) {
String currentSortOrder = fragment.getSortOrder();
sortOrderMenu.clear();
if (fragment instanceof AlbumsFragment) {
sortOrderMenu.add(0, R.id.action_album_sort_order_asc, 0, R.string.sort_order_a_z)
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_A_Z));
sortOrderMenu.add(0, R.id.action_album_sort_order_desc, 1, R.string.sort_order_z_a)
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_Z_A));
sortOrderMenu.add(0, R.id.action_album_sort_order_artist, 2, R.string.sort_order_artist)
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_ARTIST));
sortOrderMenu.add(0, R.id.action_album_sort_order_year, 3, R.string.sort_order_year)
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_YEAR));
} else if (fragment instanceof ArtistsFragment) {
sortOrderMenu.add(0, R.id.action_artist_sort_order_asc, 0, R.string.sort_order_a_z)
.setChecked(currentSortOrder.equals(SortOrder.ArtistSortOrder.ARTIST_A_Z));
sortOrderMenu.add(0, R.id.action_artist_sort_order_desc, 1, R.string.sort_order_z_a)
.setChecked(currentSortOrder.equals(SortOrder.ArtistSortOrder.ARTIST_Z_A));
} else if (fragment instanceof SongsFragment) {
sortOrderMenu.add(0, R.id.action_song_sort_order_asc, 0, R.string.sort_order_a_z)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_A_Z));
sortOrderMenu.add(0, R.id.action_song_sort_order_desc, 1, R.string.sort_order_z_a)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_Z_A));
sortOrderMenu.add(0, R.id.action_song_sort_order_artist, 2, R.string.sort_order_artist)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_ARTIST));
sortOrderMenu.add(0, R.id.action_song_sort_order_album, 3, R.string.sort_order_album)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_ALBUM));
sortOrderMenu.add(0, R.id.action_song_sort_order_year, 4, R.string.sort_order_year)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_YEAR));
sortOrderMenu.add(0, R.id.action_song_sort_order_date, 4, R.string.sort_order_date)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_DATE));
}
sortOrderMenu.setGroupCheckable(0, true, true);
}
private boolean handleSortOrderMenuItem(
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment
fragment, @NonNull MenuItem item) {
String sortOrder = null;
if (fragment instanceof AlbumsFragment) {
switch (item.getItemId()) {
case R.id.action_album_sort_order_asc:
sortOrder = SortOrder.AlbumSortOrder.ALBUM_A_Z;
break;
case R.id.action_album_sort_order_desc:
sortOrder = SortOrder.AlbumSortOrder.ALBUM_Z_A;
break;
case R.id.action_album_sort_order_artist:
sortOrder = SortOrder.AlbumSortOrder.ALBUM_ARTIST;
break;
case R.id.action_album_sort_order_year:
sortOrder = SortOrder.AlbumSortOrder.ALBUM_YEAR;
break;
}
} else if (fragment instanceof ArtistsFragment) {
switch (item.getItemId()) {
case R.id.action_artist_sort_order_asc:
sortOrder = SortOrder.ArtistSortOrder.ARTIST_A_Z;
break;
case R.id.action_artist_sort_order_desc:
sortOrder = SortOrder.ArtistSortOrder.ARTIST_Z_A;
break;
}
} else if (fragment instanceof SongsFragment) {
switch (item.getItemId()) {
case R.id.action_song_sort_order_asc:
sortOrder = SortOrder.SongSortOrder.SONG_A_Z;
break;
case R.id.action_song_sort_order_desc:
sortOrder = SortOrder.SongSortOrder.SONG_Z_A;
break;
case R.id.action_song_sort_order_artist:
sortOrder = SortOrder.SongSortOrder.SONG_ARTIST;
break;
case R.id.action_song_sort_order_album:
sortOrder = SortOrder.SongSortOrder.SONG_ALBUM;
break;
case R.id.action_song_sort_order_year:
sortOrder = SortOrder.SongSortOrder.SONG_YEAR;
break;
case R.id.action_song_sort_order_date:
sortOrder = SortOrder.SongSortOrder.SONG_DATE;
break;
}
}
if (sortOrder != null) {
item.setChecked(true);
fragment.setAndSaveSortOrder(sortOrder);
return true;
}
return false;
}
@SuppressWarnings("ConstantConditions")
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
//if (pager == null) return false;
Fragment currentFragment = getCurrentFragment();
if (currentFragment instanceof AbsLibraryPagerRecyclerViewCustomGridSizeFragment) {
AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment = (AbsLibraryPagerRecyclerViewCustomGridSizeFragment) currentFragment;
if (handleGridSizeMenuItem(fragment, item)) {
return true;
}
if (handleSortOrderMenuItem(fragment, item)) {
return true;
}
}
int id = item.getItemId();
switch (id) {
case R.id.action_new_playlist:
CreatePlaylistDialog.Companion.create().show(getChildFragmentManager(), "CREATE_PLAYLIST");
return true;
case R.id.action_shuffle_all:
MusicPlayerRemote.INSTANCE.openAndShuffleQueue(SongLoader.INSTANCE.getAllSongs(getContext())
.blockingFirst(), true);
return true;
case R.id.action_search:
NavigationUtil.goToSearch(getMainActivity());
break;
case R.id.action_equalizer:
NavigationUtil.openEqualizer(getActivity());
return true;
case R.id.action_sleep_timer:
if (getFragmentManager() != null) {
new SleepTimerDialog().show(getFragmentManager(), TAG);
}
return true;
case R.id.action_settings:
startActivity(new Intent(getContext(), SettingsActivity.class));
break;
}
return super.onOptionsItemSelected(item);
}
private void setUpGridSizeMenu(
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment,
@NonNull SubMenu gridSizeMenu) {
switch (fragment.getGridSize()) {
case 1:
gridSizeMenu.findItem(R.id.action_grid_size_1).setChecked(true);
break;
case 2:
gridSizeMenu.findItem(R.id.action_grid_size_2).setChecked(true);
break;
case 3:
gridSizeMenu.findItem(R.id.action_grid_size_3).setChecked(true);
break;
case 4:
gridSizeMenu.findItem(R.id.action_grid_size_4).setChecked(true);
break;
case 5:
gridSizeMenu.findItem(R.id.action_grid_size_5).setChecked(true);
break;
case 6:
gridSizeMenu.findItem(R.id.action_grid_size_6).setChecked(true);
break;
case 7:
gridSizeMenu.findItem(R.id.action_grid_size_7).setChecked(true);
break;
case 8:
gridSizeMenu.findItem(R.id.action_grid_size_8).setChecked(true);
break;
}
int maxGridSize = fragment.getMaxGridSize();
if (maxGridSize < 8) {
gridSizeMenu.findItem(R.id.action_grid_size_8).setVisible(false);
}
if (maxGridSize < 7) {
gridSizeMenu.findItem(R.id.action_grid_size_7).setVisible(false);
}
if (maxGridSize < 6) {
gridSizeMenu.findItem(R.id.action_grid_size_6).setVisible(false);
}
if (maxGridSize < 5) {
gridSizeMenu.findItem(R.id.action_grid_size_5).setVisible(false);
}
if (maxGridSize < 4) {
gridSizeMenu.findItem(R.id.action_grid_size_4).setVisible(false);
}
if (maxGridSize < 3) {
gridSizeMenu.findItem(R.id.action_grid_size_3).setVisible(false);
}
}
private boolean handleGridSizeMenuItem(
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment
fragment, @NonNull MenuItem item) {
int gridSize = 0;
switch (item.getItemId()) {
case R.id.action_grid_size_1:
gridSize = 1;
break;
case R.id.action_grid_size_2:
gridSize = 2;
break;
case R.id.action_grid_size_3:
gridSize = 3;
break;
case R.id.action_grid_size_4:
gridSize = 4;
break;
case R.id.action_grid_size_5:
gridSize = 5;
break;
case R.id.action_grid_size_6:
gridSize = 6;
break;
case R.id.action_grid_size_7:
gridSize = 7;
break;
case R.id.action_grid_size_8:
gridSize = 8;
break;
}
if (gridSize > 0) {
item.setChecked(true);
fragment.setAndSaveGridSize(gridSize);
return true;
}
return false;
}
}

View File

@ -1,364 +0,0 @@
package code.name.monkey.retromusic.ui.fragments.mainactivity
import android.content.Intent
import android.os.Bundle
import android.view.*
import android.widget.TextView
import androidx.annotation.StringRes
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.common.ATHToolbarActivity
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog
import code.name.monkey.retromusic.dialogs.SleepTimerDialog
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.SortOrder
import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
import code.name.monkey.retromusic.loaders.SongLoader
import code.name.monkey.retromusic.ui.activities.SettingsActivity
import code.name.monkey.retromusic.ui.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment
import code.name.monkey.retromusic.ui.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.RetroColorUtil
import code.name.monkey.retromusic.util.RetroUtil
import com.afollestad.materialcab.MaterialCab
import com.google.android.material.appbar.AppBarLayout
class LibraryFragment : AbsMainActivityFragment(), CabHolder, MainActivityFragmentCallbacks, AppBarLayout.OnOffsetChangedListener {
override fun onOffsetChanged(p0: AppBarLayout?, p1: Int) {
mainActivity.setLightStatusbar(!ATHUtil.isWindowBackgroundDark(context))
}
lateinit var toolbar: Toolbar
lateinit var appbar: AppBarLayout
lateinit var title: TextView
lateinit var contentContainer: View
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_library, container, false)
toolbar = view.findViewById(R.id.toolbar)
appbar = view.findViewById(R.id.app_bar)
title = view.findViewById(R.id.title)
contentContainer = view.findViewById(R.id.fragment_container)
return view
}
private var cab: MaterialCab? = null
val totalAppBarScrollingRange: Int
get() = appbar.totalScrollRange
private fun getCurrentFragment(): Fragment? {
return if (fragmentManager == null) {
SongsFragment.newInstance()
} else fragmentManager!!.findFragmentById(R.id.fragment_container)
}
private fun selectedFragment(fragment: Fragment) {
val fragmentManager = childFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction
.replace(R.id.fragment_container, fragment, TAG)
.commit()
fragmentManager.executePendingTransactions()
}
fun setTitle(@StringRes name: Int) {
title.text = getString(name)
}
fun addOnAppBarOffsetChangedListener(onOffsetChangedListener: AppBarLayout.OnOffsetChangedListener) {
appbar.addOnOffsetChangedListener(onOffsetChangedListener)
}
fun removeOnAppBarOffsetChangedListener(onOffsetChangedListener: AppBarLayout.OnOffsetChangedListener) {
appbar.removeOnOffsetChangedListener(onOffsetChangedListener)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setStatusbarColorAuto(view)
setupToolbar()
inflateFragment()
}
private fun inflateFragment() {
if (arguments == null) {
selectedFragment(SongsFragment.newInstance())
return
}
when (arguments!!.getInt(CURRENT_TAB_ID)) {
R.id.action_song -> selectedFragment(SongsFragment.newInstance())
R.id.action_album -> selectedFragment(AlbumsFragment.newInstance())
R.id.action_artist -> selectedFragment(ArtistsFragment.newInstance())
R.id.action_playlist -> selectedFragment(PlaylistsFragment.newInstance())
else -> selectedFragment(SongsFragment.newInstance())
}
}
private fun setupToolbar() {
title.setTextColor(ThemeStore.textColorPrimary(context!!))
val primaryColor = ThemeStore.primaryColor(context!!)
TintHelper.setTintAuto(contentContainer, primaryColor, true)
toolbar.setBackgroundColor(primaryColor)
appbar.setBackgroundColor(primaryColor)
appbar.addOnOffsetChangedListener(this)
mainActivity.title = null
mainActivity.setSupportActionBar(toolbar)
toolbar.navigationIcon = RetroUtil.getTintedDrawable(mainActivity, R.drawable.ic_menu_white_24dp, ThemeStore.textColorPrimary(mainActivity))
}
override fun handleBackPress(): Boolean {
if (cab != null && cab!!.isActive) {
cab!!.finish()
return true
}
return false
}
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
if (cab != null && cab!!.isActive) {
cab!!.finish()
}
cab = MaterialCab(mainActivity, R.id.cab_stub)
.setMenu(menuRes)
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
.setBackgroundColor(
RetroColorUtil.shiftBackgroundColorForLightText(ThemeStore.primaryColor(activity!!)))
.start(callback)
return cab as MaterialCab
}
private fun isPlaylistFragment(): Boolean {
return true
}
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
super.onCreateOptionsMenu(menu, inflater)
inflater!!.inflate(R.menu.menu_main, menu)
if (isPlaylistFragment()) {
menu!!.add(0, R.id.action_new_playlist, 0, R.string.new_playlist_title)
}
val currentFragment = getCurrentFragment()
if (currentFragment is AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *> && currentFragment.isAdded) {
val fragment = currentFragment as AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>?
val gridSizeItem = menu!!.findItem(R.id.action_grid_size)
if (RetroUtil.isLandscape()) {
gridSizeItem.setTitle(R.string.action_grid_size_land)
}
setUpGridSizeMenu(fragment!!, gridSizeItem.subMenu)
setUpSortOrderMenu(fragment, menu.findItem(R.id.action_sort_order).subMenu)
} else {
menu!!.removeItem(R.id.action_grid_size)
}
ToolbarContentTintHelper.handleOnCreateOptionsMenu(activity!!, toolbar, menu, ATHToolbarActivity.getToolbarBackgroundColor(toolbar))
}
override fun onPrepareOptionsMenu(menu: Menu?) {
super.onPrepareOptionsMenu(menu)
val activity = activity ?: return
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(activity, toolbar)
}
private fun setUpSortOrderMenu(
fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
sortOrderMenu: SubMenu) {
val currentSortOrder = fragment.getSortOrder()
sortOrderMenu.clear()
when (fragment) {
is AlbumsFragment -> {
sortOrderMenu.add(0, R.id.action_album_sort_order_asc, 0, R.string.sort_order_a_z).isChecked = currentSortOrder == SortOrder.AlbumSortOrder.ALBUM_A_Z
sortOrderMenu.add(0, R.id.action_album_sort_order_desc, 1, R.string.sort_order_z_a).isChecked = currentSortOrder == SortOrder.AlbumSortOrder.ALBUM_Z_A
sortOrderMenu.add(0, R.id.action_album_sort_order_artist, 2, R.string.sort_order_artist).isChecked = currentSortOrder == SortOrder.AlbumSortOrder.ALBUM_ARTIST
sortOrderMenu.add(0, R.id.action_album_sort_order_year, 3, R.string.sort_order_year).isChecked = currentSortOrder == SortOrder.AlbumSortOrder.ALBUM_YEAR
}
is ArtistsFragment -> {
sortOrderMenu.add(0, R.id.action_artist_sort_order_asc, 0, R.string.sort_order_a_z).isChecked = currentSortOrder == SortOrder.ArtistSortOrder.ARTIST_A_Z
sortOrderMenu.add(0, R.id.action_artist_sort_order_desc, 1, R.string.sort_order_z_a).isChecked = currentSortOrder == SortOrder.ArtistSortOrder.ARTIST_Z_A
}
is SongsFragment -> {
sortOrderMenu.add(0, R.id.action_song_sort_order_asc, 0, R.string.sort_order_a_z).isChecked = currentSortOrder == SortOrder.SongSortOrder.SONG_A_Z
sortOrderMenu.add(0, R.id.action_song_sort_order_desc, 1, R.string.sort_order_z_a).isChecked = currentSortOrder == SortOrder.SongSortOrder.SONG_Z_A
sortOrderMenu.add(0, R.id.action_song_sort_order_artist, 2, R.string.sort_order_artist).isChecked = currentSortOrder == SortOrder.SongSortOrder.SONG_ARTIST
sortOrderMenu.add(0, R.id.action_song_sort_order_album, 3, R.string.sort_order_album).isChecked = currentSortOrder == SortOrder.SongSortOrder.SONG_ALBUM
sortOrderMenu.add(0, R.id.action_song_sort_order_year, 4, R.string.sort_order_year).isChecked = currentSortOrder == SortOrder.SongSortOrder.SONG_YEAR
sortOrderMenu.add(0, R.id.action_song_sort_order_date, 4, R.string.sort_order_date).isChecked = currentSortOrder == SortOrder.SongSortOrder.SONG_DATE
}
}
sortOrderMenu.setGroupCheckable(0, true, true)
}
private fun handleSortOrderMenuItem(
fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>, item: MenuItem): Boolean {
var sortOrder: String? = null
when (fragment) {
is AlbumsFragment -> when (item.itemId) {
R.id.action_album_sort_order_asc -> sortOrder = SortOrder.AlbumSortOrder.ALBUM_A_Z
R.id.action_album_sort_order_desc -> sortOrder = SortOrder.AlbumSortOrder.ALBUM_Z_A
R.id.action_album_sort_order_artist -> sortOrder = SortOrder.AlbumSortOrder.ALBUM_ARTIST
R.id.action_album_sort_order_year -> sortOrder = SortOrder.AlbumSortOrder.ALBUM_YEAR
}
is ArtistsFragment -> when (item.itemId) {
R.id.action_artist_sort_order_asc -> sortOrder = SortOrder.ArtistSortOrder.ARTIST_A_Z
R.id.action_artist_sort_order_desc -> sortOrder = SortOrder.ArtistSortOrder.ARTIST_Z_A
}
is SongsFragment -> when (item.itemId) {
R.id.action_song_sort_order_asc -> sortOrder = SortOrder.SongSortOrder.SONG_A_Z
R.id.action_song_sort_order_desc -> sortOrder = SortOrder.SongSortOrder.SONG_Z_A
R.id.action_song_sort_order_artist -> sortOrder = SortOrder.SongSortOrder.SONG_ARTIST
R.id.action_song_sort_order_album -> sortOrder = SortOrder.SongSortOrder.SONG_ALBUM
R.id.action_song_sort_order_year -> sortOrder = SortOrder.SongSortOrder.SONG_YEAR
R.id.action_song_sort_order_date -> sortOrder = SortOrder.SongSortOrder.SONG_DATE
}
}
if (sortOrder != null) {
item.isChecked = true
fragment.setAndSaveSortOrder(sortOrder)
return true
}
return false
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
//if (pager == null) return false;
val currentFragment = getCurrentFragment()
if (currentFragment is AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>) {
val fragment = currentFragment as AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>?
if (handleGridSizeMenuItem(fragment!!, item)) {
return true
}
if (handleSortOrderMenuItem(fragment, item)) {
return true
}
}
val id = item.itemId
when (id) {
R.id.action_new_playlist -> {
CreatePlaylistDialog.create().show(childFragmentManager, "CREATE_PLAYLIST")
return true
}
R.id.action_shuffle_all -> {
MusicPlayerRemote.openAndShuffleQueue(SongLoader.getAllSongs(context!!).blockingFirst(), true)
return true
}
R.id.action_equalizer -> {
NavigationUtil.openEqualizer(activity!!)
return true
}
R.id.action_sleep_timer -> {
if (fragmentManager != null) {
SleepTimerDialog().show(fragmentManager!!, TAG)
}
return true
}
R.id.action_settings -> startActivity(Intent(context, SettingsActivity::class.java))
}
return super.onOptionsItemSelected(item)
}
private fun setUpGridSizeMenu(
fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
gridSizeMenu: SubMenu) {
when (fragment.getGridSize()) {
1 -> gridSizeMenu.findItem(R.id.action_grid_size_1).isChecked = true
2 -> gridSizeMenu.findItem(R.id.action_grid_size_2).isChecked = true
3 -> gridSizeMenu.findItem(R.id.action_grid_size_3).isChecked = true
4 -> gridSizeMenu.findItem(R.id.action_grid_size_4).isChecked = true
5 -> gridSizeMenu.findItem(R.id.action_grid_size_5).isChecked = true
6 -> gridSizeMenu.findItem(R.id.action_grid_size_6).isChecked = true
7 -> gridSizeMenu.findItem(R.id.action_grid_size_7).isChecked = true
8 -> gridSizeMenu.findItem(R.id.action_grid_size_8).isChecked = true
}
val maxGridSize = fragment.maxGridSize
if (maxGridSize < 8) {
gridSizeMenu.findItem(R.id.action_grid_size_8).isVisible = false
}
if (maxGridSize < 7) {
gridSizeMenu.findItem(R.id.action_grid_size_7).isVisible = false
}
if (maxGridSize < 6) {
gridSizeMenu.findItem(R.id.action_grid_size_6).isVisible = false
}
if (maxGridSize < 5) {
gridSizeMenu.findItem(R.id.action_grid_size_5).isVisible = false
}
if (maxGridSize < 4) {
gridSizeMenu.findItem(R.id.action_grid_size_4).isVisible = false
}
if (maxGridSize < 3) {
gridSizeMenu.findItem(R.id.action_grid_size_3).isVisible = false
}
}
private fun handleGridSizeMenuItem(
fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>, item: MenuItem): Boolean {
var gridSize = 0
when (item.itemId) {
R.id.action_grid_size_1 -> gridSize = 1
R.id.action_grid_size_2 -> gridSize = 2
R.id.action_grid_size_3 -> gridSize = 3
R.id.action_grid_size_4 -> gridSize = 4
R.id.action_grid_size_5 -> gridSize = 5
R.id.action_grid_size_6 -> gridSize = 6
R.id.action_grid_size_7 -> gridSize = 7
R.id.action_grid_size_8 -> gridSize = 8
}
if (gridSize > 0) {
item.isChecked = true
fragment.setAndSaveGridSize(gridSize)
return true
}
return false
}
companion object {
const val TAG: String = "LibraryFragment"
private const val CURRENT_TAB_ID = "current_tab_id"
fun newInstance(tab: Int): Fragment {
val args = Bundle()
args.putInt(CURRENT_TAB_ID, tab)
val fragment = LibraryFragment()
fragment.arguments = args
return fragment
}
fun newInstance(): Fragment {
return LibraryFragment()
}
}
}

View File

@ -40,6 +40,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.abs_playlists.*
import kotlinx.android.synthetic.main.fragment_banner_home.*
import kotlinx.android.synthetic.main.home_section_content.*
import java.io.File
@ -181,6 +182,10 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
loadImageFromStorage(userImage)
getTimeOfTheDay()
searchView.setOnClickListener {
NavigationUtil.goToSearch(activity!!)
}
}
private fun setupToolbar() {
@ -212,7 +217,7 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
}
override fun showData(homes: ArrayList<Any>) {
override fun showData(list: ArrayList<Any>) {
//homeAdapter.swapDataSet(homes);
}

View File

@ -7,8 +7,10 @@ import android.view.ViewGroup
import androidx.viewpager.widget.ViewPager
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.transform.CarousalPagerTransformer
import code.name.monkey.retromusic.transform.ParallaxPagerTransformer
import code.name.monkey.retromusic.ui.adapter.album.AlbumCoverPagerAdapter
import code.name.monkey.retromusic.ui.fragments.NowPlayingScreen
import code.name.monkey.retromusic.ui.fragments.base.AbsMusicServiceFragment
import code.name.monkey.retromusic.util.PreferenceUtil
import kotlinx.android.synthetic.main.fragment_player_album_cover.*
@ -40,7 +42,15 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(), ViewPager.OnPageChan
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewPager.addOnPageChangeListener(this)
viewPager.setPageTransformer(true, PreferenceUtil.getInstance().getAlbumCoverTransform(context))
//noinspection ConstantConditions
if (PreferenceUtil.getInstance().carouselEffect() && !((PreferenceUtil.getInstance().nowPlayingScreen == NowPlayingScreen.FULL) || (PreferenceUtil.getInstance().nowPlayingScreen == NowPlayingScreen.FIT))) {
viewPager.clipToPadding = false;
viewPager.setPadding(96, 0, 96, 0);
viewPager.pageMargin = 18;
viewPager.setPageTransformer(false, CarousalPagerTransformer(context!!));
} else {
viewPager.setPageTransformer(true, PreferenceUtil.getInstance().getAlbumCoverTransform(context!!));
}
}
override fun onDestroyView() {

View File

@ -34,8 +34,8 @@ class AdaptiveFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks
}
private fun setUpSubFragments() {
playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playback_controls_fragment) as AdaptivePlaybackControlsFragment
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.player_album_cover_fragment) as PlayerAlbumCoverFragment
playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as AdaptivePlaybackControlsFragment
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
playerAlbumCoverFragment.apply {
removeSlideEffect()
}.setCallbacks(this)

View File

@ -210,14 +210,14 @@ class ColorFragment : AbsPlayerFragment() {
updateLyricsAsyncTask!!.cancel(false)
}
val song = MusicPlayerRemote.currentSong
updateLyricsAsyncTask = object : AsyncTask<Void, Void, Lyrics>() {
updateLyricsAsyncTask = object : AsyncTask<Void?, Void?, Lyrics?>() {
override fun onPreExecute() {
super.onPreExecute()
lyrics = null
playerToolbar.menu.removeItem(R.id.action_show_lyrics)
}
override fun doInBackground(vararg params: Void): Lyrics? {
override fun doInBackground(vararg params: Void?): Lyrics? {
val data = MusicUtil.getLyrics(song)
return if (TextUtils.isEmpty(data)) {
null
@ -233,7 +233,7 @@ class ColorFragment : AbsPlayerFragment() {
}
}
override fun onCancelled(s: Lyrics) {
override fun onCancelled(s: Lyrics?) {
onPostExecute(null)
}
}.execute()

View File

@ -0,0 +1,229 @@
package code.name.monkey.retromusic.ui.fragments.player.lockscreen
import android.animation.ObjectAnimator
import android.graphics.PorterDuff
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
import android.view.animation.LinearInterpolator
import android.widget.SeekBar
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.util.MusicUtil
import kotlinx.android.synthetic.main.fragment_lock_screen_playback_controls.*
import kotlinx.android.synthetic.main.media_button.*
import kotlinx.android.synthetic.main.player_time.*
/**
* @author Hemanth S (h4h13).
*/
class LockScreenPlayerControlsFragment : AbsPlayerControlsFragment() {
private var progressViewUpdateHelper: MusicProgressViewUpdateHelper? = null
private var lastPlaybackControlsColor: Int = 0
private var lastDisabledPlaybackControlsColor: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_lock_screen_playback_controls, container, false)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setUpMusicControllers()
}
private fun updateSong() {
val song = MusicPlayerRemote.currentSong
title.text = song.title
text.text = String.format("%s - %s", song.artistName, song.albumName)
}
override fun onResume() {
super.onResume()
progressViewUpdateHelper!!.start()
}
override fun onPause() {
super.onPause()
progressViewUpdateHelper!!.stop()
}
override fun onServiceConnected() {
updatePlayPauseDrawableState()
updateRepeatState()
updateShuffleState()
updateSong()
}
override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged()
updateSong()
}
override fun onPlayStateChanged() {
updatePlayPauseDrawableState()
}
override fun onRepeatModeChanged() {
updateRepeatState()
}
override fun onShuffleModeChanged() {
updateShuffleState()
}
override fun setDark(color: Int) {
setProgressBarColor(progressSlider, color)
val colorBg = ATHUtil.resolveColor(activity, android.R.attr.colorBackground)
if (ColorUtil.isColorLight(colorBg)) {
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(activity, true)
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(activity, true)
} else {
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(activity, false)
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(activity, false)
}
updatePrevNextColor()
val isDark = ColorUtil.isColorLight(color)
text!!.setTextColor(color)
TintHelper.setTintAuto(playPauseButton, MaterialValueHelper.getPrimaryTextColor(context, isDark), false)
TintHelper.setTintAuto(playPauseButton, color, true)
}
fun setProgressBarColor(progressBar: SeekBar?, newColor: Int) {
TintHelper.setTintAuto(progressBar!!, newColor, false)
//LayerDrawable ld = (LayerDrawable) progressBar.getProgressDrawable();
//ClipDrawable clipDrawable = (ClipDrawable) ld.findDrawableByLayerId(android.R.id.progress);
//clipDrawable.setColorFilter(newColor, PorterDuff.Mode.SRC_IN);
}
private fun setUpPlayPauseFab() {
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
}
private fun updatePlayPauseDrawableState() {
if (MusicPlayerRemote.isPlaying) {
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
} else {
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
}
}
private fun setUpMusicControllers() {
setUpPlayPauseFab()
setUpPrevNext()
setUpProgressSlider()
setUpShuffleButton()
setUpRepeatButton()
}
private fun setUpPrevNext() {
updatePrevNextColor()
nextButton.setOnClickListener { MusicPlayerRemote.playNextSong() }
previousButton.setOnClickListener { MusicPlayerRemote.back() }
}
private fun updatePrevNextColor() {
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
}
private fun setUpShuffleButton() {
shuffleButton.setOnClickListener { MusicPlayerRemote.toggleShuffleMode() }
}
override fun updateShuffleState() {
when (MusicPlayerRemote.shuffleMode) {
MusicService.SHUFFLE_MODE_SHUFFLE -> shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
}
}
private fun setUpRepeatButton() {
repeatButton.setOnClickListener { MusicPlayerRemote.cycleRepeatMode() }
}
override fun updateRepeatState() {
when (MusicPlayerRemote.repeatMode) {
MusicService.REPEAT_MODE_NONE -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
}
MusicService.REPEAT_MODE_ALL -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
}
MusicService.REPEAT_MODE_THIS -> {
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp)
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
}
}
}
public override fun show() {
playPauseButton!!.animate()
.scaleX(1f)
.scaleY(1f)
.rotation(360f)
.setInterpolator(DecelerateInterpolator())
.start()
}
public override fun hide() {
if (playPauseButton != null) {
playPauseButton!!.apply {
scaleX = 0f
scaleY = 0f
rotation = 0f
}
}
}
override fun setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress)
onUpdateProgressViews(MusicPlayerRemote.songProgressMillis,
MusicPlayerRemote.songDurationMillis)
}
}
})
}
override fun onUpdateProgressViews(progress: Int, total: Int) {
progressSlider.max = total
val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
animator.duration = 1500
animator.interpolator = LinearInterpolator()
animator.start()
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
}
}

View File

@ -121,9 +121,9 @@ class MaterialControlsFragment : AbsPlayerControlsFragment() {
private fun updatePlayPauseDrawableState() {
if (MusicPlayerRemote.isPlaying) {
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
playPauseButton.setImageResource(R.drawable.ic_pause_white_big);
} else {
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp)
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_big);
}
}

View File

@ -96,6 +96,7 @@ class PlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
super.onViewCreated(view, savedInstanceState)
setUpSubFragments()
setUpPlayerToolbar()
snowfall.visibility= if (PreferenceUtil.getInstance().isSnowFall) View.VISIBLE else View.GONE
}
private fun setUpSubFragments() {

View File

@ -1,16 +1,28 @@
package code.name.monkey.retromusic.ui.fragments.settings
import android.graphics.Bitmap
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.Constants.USER_PROFILE
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.ui.activities.SettingsActivity
import code.name.monkey.retromusic.util.Compressor
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.fragment_main_settings.*
import java.io.File
import java.util.*
class MainSettingsFragment : Fragment(), View.OnClickListener {
override fun onClick(v: View) {
@ -44,6 +56,12 @@ class MainSettingsFragment : Fragment(), View.OnClickListener {
imageSettings.setOnClickListener(this)
notificationSettings.setOnClickListener(this)
otherSettings.setOnClickListener(this)
text.setTextColor(ThemeStore.textColorSecondary(context!!));
titleWelcome.setTextColor(ThemeStore.textColorPrimary(context!!));
titleWelcome.text = String.format("%s %s!", getTimeOfTheDay(), PreferenceUtil.getInstance().userName);
loadImageFromStorage();
userInfoContainer.setOnClickListener { NavigationUtil.goToUserInfo(activity!!) }
}
private fun inflateFragment(fragment: Fragment, @StringRes title: Int) {
@ -51,4 +69,42 @@ class MainSettingsFragment : Fragment(), View.OnClickListener {
(activity as SettingsActivity).setupFragment(fragment, title)
}
}
private fun getTimeOfTheDay(): String {
var message = getString(R.string.title_good_day)
val c = Calendar.getInstance()
val timeOfDay = c.get(Calendar.HOUR_OF_DAY)
when (timeOfDay) {
in 0..5 -> message = getString(R.string.title_good_night)
in 6..11 -> message = getString(R.string.title_good_morning)
in 12..15 -> message = getString(R.string.title_good_afternoon)
in 16..19 -> message = getString(R.string.title_good_evening)
in 20..23 -> message = getString(R.string.title_good_night)
}
return message
}
override fun onDestroyView() {
super.onDestroyView()
disposable.clear()
}
private val disposable = CompositeDisposable()
private fun loadImageFromStorage() {
disposable.add(Compressor(context!!)
.setMaxHeight(300)
.setMaxWidth(300)
.setQuality(75)
.setCompressFormat(Bitmap.CompressFormat.WEBP)
.compressToBitmapAsFlowable(
File(PreferenceUtil.getInstance().profileImage, USER_PROFILE))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ userImage.setImageBitmap(it) }, {
userImage.setImageDrawable(ContextCompat.getDrawable(context!!, R.drawable.ic_person_flat))
}))
}
}

View File

@ -11,6 +11,7 @@ import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
import code.name.monkey.retromusic.util.PreferenceUtil
import com.afollestad.materialdialogs.color.ColorChooserDialog
@ -64,6 +65,7 @@ class ThemeSettingsFragment : AbsSettingsFragment() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
activity!!.setTheme(PreferenceUtil.getThemeResFromPrefValue(theme))
DynamicShortcutManager(activity!!).updateDynamicShortcuts()
}
activity!!.recreate()
//invalidateSettings();
@ -92,6 +94,7 @@ class ThemeSettingsFragment : AbsSettingsFragment() {
colorAppShortcuts.setOnPreferenceChangeListener { _, newValue ->
// Save preference
PreferenceUtil.getInstance().setColoredAppShortcuts(newValue as Boolean)
DynamicShortcutManager(activity!!).updateDynamicShortcuts()
true
}
}

View File

@ -113,6 +113,7 @@ public final class PreferenceUtil {
private static final String ALBUM_DETAIL_STYLE = "album_detail_style";
private static final String PAUSE_ON_ZERO_VOLUME = "pause_on_zero_volume";
private static final String NOW_PLAYING_SCREEN = "now_playing_screen";
private static final String SNOW_FALL_EFFECT = "snow_fall_effect";
private static PreferenceUtil sInstance;
private final SharedPreferences mPreferences;
@ -144,8 +145,12 @@ public final class PreferenceUtil {
}
}
public boolean isSnowFall() {
return mPreferences.getBoolean(SNOW_FALL_EFFECT, false);
}
public final String getArtistSortOrder() {
return mPreferences.getString(ARTIST_SORT_ORDER, SortOrder.ArtistSortOrder.Companion.getARTIST_A_Z());
return mPreferences.getString(ARTIST_SORT_ORDER, SortOrder.ArtistSortOrder.ARTIST_A_Z);
}
public void setArtistSortOrder(final String sortOrder) {
@ -155,7 +160,7 @@ public final class PreferenceUtil {
}
public final String getArtistSongSortOrder() {
return mPreferences.getString(ARTIST_SONG_SORT_ORDER, SortOrder.ArtistSongSortOrder.Companion.getSONG_A_Z());
return mPreferences.getString(ARTIST_SONG_SORT_ORDER, SortOrder.ArtistSongSortOrder.SONG_A_Z);
}
public final boolean isHomeBanner() {
@ -164,11 +169,11 @@ public final class PreferenceUtil {
public final String getArtistAlbumSortOrder() {
return mPreferences
.getString(ARTIST_ALBUM_SORT_ORDER, SortOrder.ArtistAlbumSortOrder.Companion.getALBUM_YEAR());
.getString(ARTIST_ALBUM_SORT_ORDER, SortOrder.ArtistAlbumSortOrder.ALBUM_YEAR);
}
public final String getAlbumSortOrder() {
return mPreferences.getString(ALBUM_SORT_ORDER, SortOrder.AlbumSortOrder.Companion.getALBUM_A_Z());
return mPreferences.getString(ALBUM_SORT_ORDER, SortOrder.AlbumSortOrder.ALBUM_A_Z);
}
public void setAlbumSortOrder(final String sortOrder) {
@ -179,11 +184,11 @@ public final class PreferenceUtil {
public final String getAlbumSongSortOrder() {
return mPreferences
.getString(ALBUM_SONG_SORT_ORDER, SortOrder.AlbumSongSortOrder.Companion.getSONG_TRACK_LIST());
.getString(ALBUM_SONG_SORT_ORDER, SortOrder.AlbumSongSortOrder.SONG_TRACK_LIST);
}
public final String getSongSortOrder() {
return mPreferences.getString(SONG_SORT_ORDER, SortOrder.SongSortOrder.Companion.getSONG_A_Z());
return mPreferences.getString(SONG_SORT_ORDER, SortOrder.SongSortOrder.SONG_A_Z);
}
public void setSongSortOrder(final String sortOrder) {
@ -193,7 +198,7 @@ public final class PreferenceUtil {
}
public final String getGenreSortOrder() {
return mPreferences.getString(GENRE_SORT_ORDER, SortOrder.GenreSortOrder.Companion.getGENRE_A_Z());
return mPreferences.getString(GENRE_SORT_ORDER, SortOrder.GenreSortOrder.GENRE_A_Z);
}
public boolean isScreenOnEnabled() {
@ -288,9 +293,6 @@ public final class PreferenceUtil {
editor.apply();
}
public int getLastLyricsType() {
return mPreferences.getInt(LAST_KNOWN_LYRICS_TYPE, R.id.normalLyrics);
}
public void setLastLyricsType(int group) {
final SharedPreferences.Editor editor = mPreferences.edit();
@ -632,7 +634,7 @@ public final class PreferenceUtil {
public String getAlbumDetailSongSortOrder() {
return mPreferences
.getString(ALBUM_DETAIL_SONG_SORT_ORDER, SortOrder.AlbumSongSortOrder.Companion.getSONG_TRACK_LIST());
.getString(ALBUM_DETAIL_SONG_SORT_ORDER, SortOrder.AlbumSongSortOrder.SONG_TRACK_LIST);
}
public void setAlbumDetailSongSortOrder(String sortOrder) {
@ -643,7 +645,7 @@ public final class PreferenceUtil {
public String getArtistDetailSongSortOrder() {
return mPreferences
.getString(ARTIST_DETAIL_SONG_SORT_ORDER, SortOrder.ArtistSongSortOrder.Companion.getSONG_A_Z());
.getString(ARTIST_DETAIL_SONG_SORT_ORDER, SortOrder.ArtistSongSortOrder.SONG_A_Z);
}
public void setArtistDetailSongSortOrder(String sortOrder) {