App shortcut fixed

main
h4h13 2018-12-25 20:28:47 +05:30
parent 1425bfe612
commit 0b6f043995
181 changed files with 1616 additions and 2052 deletions

View File

@ -32,8 +32,8 @@ android {
vectorDrawables.useSupportLibrary = true
applicationId "code.name.monkey.retromusic"
versionCode 263
versionName '3.0.130'
versionCode 272
versionName '3.0.501'
multiDexEnabled true
@ -134,10 +134,6 @@ dependencies {
implementation "androidx.legacy:legacy-preference-v14:$supportLibVersion"
implementation "com.google.android.material:material:$supportLibVersion"
//For casting
implementation 'androidx.mediarouter:mediarouter:1.0.0'
implementation 'com.google.android.gms:play-services-cast-framework:16.1.0'
implementation "com.squareup.retrofit2:retrofit:2.4.0"
implementation "com.squareup.retrofit2:converter-gson:2.4.0"
implementation "com.squareup.retrofit2:adapter-rxjava2:2.4.0"
@ -145,10 +141,13 @@ dependencies {
implementation "com.afollestad.material-dialogs:core:$materialDialog"
implementation "com.afollestad.material-dialogs:commons:$materialDialog"
implementation 'com.afollestad:material-cab:0.1.12'
implementation 'com.github.bumptech.glide:glide:4.8.0'
implementation 'com.github.bumptech.glide:okhttp3-integration:4.8.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'io.reactivex.rxjava2:rxjava:2.1.17'
implementation('com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.11.0@aar') {
transitive = true
}

BIN
app/normal/release/app.aab Normal file

Binary file not shown.

View File

@ -41,17 +41,6 @@
public *;
}
# ButterKnife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
-keep class !android.support.v7.internal.view.menu.**,** {*;}
-dontwarn

View File

@ -0,0 +1 @@
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":268,"versionName":"3.0.330_1218","enabled":true,"outputFile":"app-sans-release.apk","fullName":"sansRelease","baseName":"sans-release"},"path":"app-sans-release.apk","properties":{}}]

View File

@ -15,7 +15,7 @@
<application
android:name=".App"
android:allowBackup="false"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
@ -116,14 +116,12 @@
<activity android:name=".ui.activities.EqualizerActivity" />
<activity android:name=".ui.activities.ErrorHandlerActivity" />
<activity android:name=".ui.activities.WhatsNewActivity" />
<activity
android:name=".cast.ExpandedCastControlsActivity"
android:label="@string/app_name"
android:launchMode="singleInstance"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.ExpandedCastController" />
<activity android:name=".ui.activities.bugreport.BugReportActivity" />
<activity android:name=".ui.activities.LockScreenActivity" />
<activity
android:name=".appshortcuts.AppShortcutLauncherActivity"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
<service
android:name=".service.MusicService"

View File

@ -35,7 +35,6 @@
<p><b><a href="https://github.com/JetradarMobile/android-snowfall" title="Android-Snowfall"> Android-Snowfall</a></b> by JetRadar</p>
<p><b><a href="https://github.com/umano/AndroidSlidingUpPanel" title="Android Sliding Up Panel"> Android Sliding Up Panel</a></b>by The Umano Team</p>
<p><b><a href="http://developer.android.com/tools/support-library/index.html" title="AOSP Support Libraries"> AOSP Support Libraries</a></b>by AOSP contributors</p>
<p><b><a href="https://github.com/JakeWharton/butterknife" title="Butter Knife"> Butter Knife</a></b> by Jake Wharton</p>
<p><b><a href="https://github.com/bumptech/glide" title="Glide"> Glide</a></b> by Sam Judd</p>
<p><b><a href="https://github.com/square/retrofit" title="Retrofit"> Retrofit</a></b> by Square team</p>
<p><b><a href="https://github.com/afollestad/material-cab" title="Material Contextual Action Bar"> Material Contextual Action Bar</a></b> by Aidan Michael Follestad</p>

View File

@ -1 +1 @@
<html> <head> <style type="text/css"> * { word-wrap: break-word; } {style-placeholder} a { color: #{link-color}; } a:active { color: #{link-color-active}; } ul { list-style-position: outside; padding-left: 0; padding-right: 0; margin-left: 1em; } li { padding-top: 8px; } </style> </head> <body> <h3>Version 3.0.00</h3> <ul style="line-height:150%"> <li>Converted app to kotlin</li> <li>Now you can add plain text home screen widget</li> <li>Good old side navigation bar for options</li> <li>Bug report for better tracking with milestones</li> <li>Snow fall effect can be enable from other settings(Works only one normal theme)</li> <li>Click new music mix to play songs</li> <li>Gradient image option for gird list</li> <li>Clear button for playing queue</li> <li>Folder list back button</li> <li>New theme Fit</li> <li>On library click on toolbar for accessing main menu </li> <li>On home click on toolbar for accessing search </li> <li>BottomSheetDialogue is now adaptable to screens, background colour and text size consistency. </li> <li>Removed coloured navigation bar option to making app adapt the primary colour</li> <li>Swipe up gesture for now playing removed, replaced with "tap to open", To achieve transparent navigation bar for desired themes. </li> <li>Improved tablet UI and home screen by adding suggestions toggle banner issues.</li> <li>Improving lyrics page</li> </ul> <p style="line-height:150%"><a href="https://github.com/h4h13/RetroMusicPlayer/wiki/FAQ">FAQ's</a> </p> <p style="line-height:150%">*If you face any UI related issues you clear app data and cache, if its not working try to uninstall and install again. </p> </body>
<html> <head> <style type="text/css"> * { word-wrap: break-word; } {style-placeholder} a { color: #{link-color}; } a:active { color: #{link-color-active}; } ul { list-style-position: outside; padding-left: 0; padding-right: 0; margin-left: 1em; } li { padding-top: 8px; } </style> </head> <body> <h4>v3.0.501</h4> <h3>Highlights</h3> <ul style="line-height=150%"> <li>Kotlin conversion from Good old Java</li> <li>Outline style system icons</li> <li>New Material Design principles and Guide lines</li> </style> <h3>Version 3.0.00</h3> </style> <ul style="line-height:150%"> </style> <li>Converted app to kotlin<ul style="line-height:150%"> <li>By default theme will be dark</li> <li>Now you can add search app shortcut in home screen</li> <li>Last selected Lyrics options saved</li> <li>Now you can add plain text home screen widget</li> <li>Good old side navigation bar for options</li> <li>Bug report for better tracking with milestones</li> <li>Snow fall effect can be enable from other settings(Works only one normal theme)</li> <li>Click new music mix to play songs</li> <li>Gradient image option for gird list</li> <li>Clear button for playing queue</li> <li>Folder list back button</li> <li>New theme Fit</li> <li>On library click on toolbar for accessing main menu </li> <li>On home click on toolbar for accessing search </li> <li>BottomSheetDialogue is now adaptable to screens, background colour and text size consistency. </li> <li>Removed coloured navigation bar option to making app adapt the primary colour</li> <li>Swipe up gesture for now playing removed, replaced with "tap to open", To achieve transparent navigation bar for desired themes. </li> <li>Improved tablet UI and home screen by adding suggestions toggle banner issues.</li> <li>Improving lyrics page</li> <li>Updated image loading libraries(might loose your current artist images)</li> </ul> <p>If you see entire app white or dark or black select same theme in settings to fix </p> <p style="line-height:150%"><a href="https://github.com/h4h13/RetroMusicPlayer/wiki/FAQ">FAQ's</a> </p> <p style="line-height:150%">*If you face any UI related issues you clear app data and cache, if its not working try to uninstall and install again. </p> </body>

View File

@ -1,70 +0,0 @@
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,67 @@
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
@RequiresApi(Build.VERSION_CODES.N_MR1)
object AppShortcutIconGenerator {
fun generateThemedIcon(context: Context, iconId: Int): Icon {
return if (PreferenceUtil.getInstance().coloredAppShortcuts()) {
generateUserThemedIcon(context, iconId)
} else {
generateDefaultThemedIcon(context, iconId)
}
}
private fun generateDefaultThemedIcon(context: Context, iconId: Int): Icon {
// 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 fun generateUserThemedIcon(context: Context, iconId: Int): Icon {
// Get background color from context's theme
val typedColorBackground = TypedValue()
context.theme.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 fun generateThemedIcon(context: Context, iconId: Int, foregroundColor: Int, backgroundColor: Int): Icon {
// Get and tint foreground and background drawables
val vectorDrawable = RetroUtil.getTintedVectorDrawable(context, iconId, foregroundColor)
val backgroundDrawable = RetroUtil.getTintedVectorDrawable(context, R.drawable.ic_app_shortcut_background, backgroundColor)
// Squash the two drawables together
val layerDrawable = LayerDrawable(arrayOf(backgroundDrawable, vectorDrawable))
// Return as an Icon
return Icon.createWithBitmap(drawableToBitmap(layerDrawable))
}
private fun drawableToBitmap(drawable: Drawable): Bitmap {
val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
return bitmap
}
}

View File

@ -1,77 +0,0 @@
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,79 @@
package code.name.monkey.retromusic.appshortcuts
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import code.name.monkey.retromusic.Constants.ACTION_PLAY_PLAYLIST
import code.name.monkey.retromusic.Constants.INTENT_EXTRA_PLAYLIST
import code.name.monkey.retromusic.Constants.INTENT_EXTRA_SHUFFLE_MODE
import code.name.monkey.retromusic.appshortcuts.shortcuttype.LastAddedShortcutType
import code.name.monkey.retromusic.appshortcuts.shortcuttype.SearchShortCutType
import code.name.monkey.retromusic.appshortcuts.shortcuttype.ShuffleAllShortcutType
import code.name.monkey.retromusic.appshortcuts.shortcuttype.TopTracksShortcutType
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.service.MusicService
import code.name.monkey.retromusic.ui.activities.SearchActivity
class AppShortcutLauncherActivity : Activity() {
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var shortcutType = SHORTCUT_TYPE_NONE
// Set shortcutType from the intent extras
val extras = intent.extras
if (extras != null) {
shortcutType = extras.getInt(KEY_SHORTCUT_TYPE, SHORTCUT_TYPE_NONE)
}
when (shortcutType) {
SHORTCUT_TYPE_SHUFFLE_ALL -> {
startServiceWithPlaylist(MusicService.SHUFFLE_MODE_SHUFFLE,
ShuffleAllPlaylist(applicationContext))
DynamicShortcutManager.reportShortcutUsed(this, ShuffleAllShortcutType.id)
}
SHORTCUT_TYPE_TOP_TRACKS -> {
startServiceWithPlaylist(MusicService.SHUFFLE_MODE_NONE,
MyTopTracksPlaylist(applicationContext))
DynamicShortcutManager.reportShortcutUsed(this, TopTracksShortcutType.id)
}
SHORTCUT_TYPE_LAST_ADDED -> {
startServiceWithPlaylist(MusicService.SHUFFLE_MODE_NONE,
LastAddedPlaylist(applicationContext))
DynamicShortcutManager.reportShortcutUsed(this, LastAddedShortcutType.id)
}
SHORTCUT_TYPE_SEARCH -> {
startActivity(Intent(this, SearchActivity::class.java))
DynamicShortcutManager.reportShortcutUsed(this, SearchShortCutType.id)
}
}
finish()
}
private fun startServiceWithPlaylist(shuffleMode: Int, playlist: Playlist) {
val intent = Intent(this, MusicService::class.java)
intent.action = ACTION_PLAY_PLAYLIST
val bundle = Bundle()
bundle.putParcelable(INTENT_EXTRA_PLAYLIST, playlist)
bundle.putInt(INTENT_EXTRA_SHUFFLE_MODE, shuffleMode)
intent.putExtras(bundle)
startService(intent)
}
companion object {
const val KEY_SHORTCUT_TYPE = "code.name.monkey.retromusic.appshortcuts.ShortcutType"
const val SHORTCUT_TYPE_SHUFFLE_ALL = 0
const val SHORTCUT_TYPE_TOP_TRACKS = 1
const val SHORTCUT_TYPE_LAST_ADDED = 2
const val SHORTCUT_TYPE_SEARCH = 3
const val SHORTCUT_TYPE_NONE = 4
}
}

View File

@ -1,63 +0,0 @@
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,56 @@
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 code.name.monkey.retromusic.appshortcuts.shortcuttype.LastAddedShortcutType
import code.name.monkey.retromusic.appshortcuts.shortcuttype.SearchShortCutType
import code.name.monkey.retromusic.appshortcuts.shortcuttype.ShuffleAllShortcutType
import code.name.monkey.retromusic.appshortcuts.shortcuttype.TopTracksShortcutType
@TargetApi(Build.VERSION_CODES.N_MR1)
class DynamicShortcutManager(private val context: Context) {
private val shortcutManager: ShortcutManager = this.context.getSystemService(ShortcutManager::class.java)
private val defaultShortcuts: List<ShortcutInfo>
get() = Arrays.asList(
SearchShortCutType(context).shortcutInfo,
ShuffleAllShortcutType(context).shortcutInfo,
TopTracksShortcutType(context).shortcutInfo,
LastAddedShortcutType(context).shortcutInfo
)
fun initDynamicShortcuts() {
//if (shortcutManager.dynamicShortcuts.size == 0) {
shortcutManager.dynamicShortcuts = defaultShortcuts
//}
}
fun updateDynamicShortcuts() {
shortcutManager.updateShortcuts(defaultShortcuts)
}
companion object {
fun createShortcut(context: Context, id: String, shortLabel: String, longLabel: String, icon: Icon, intent: Intent): ShortcutInfo {
return ShortcutInfo.Builder(context, id)
.setShortLabel(shortLabel)
.setLongLabel(longLabel)
.setIcon(icon)
.setIntent(intent)
.build()
}
fun reportShortcutUsed(context: Context, shortcutId: String) {
context.getSystemService(ShortcutManager::class.java).reportShortcutUsed(shortcutId)
}
}
}

View File

@ -1,50 +0,0 @@
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,41 @@
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)
abstract class BaseShortcutType(internal var context: Context) {
internal abstract val shortcutInfo: ShortcutInfo
/**
* 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
*/
internal fun getPlaySongsIntent(shortcutType: Int): Intent {
val intent = Intent(context, AppShortcutLauncherActivity::class.java)
intent.action = Intent.ACTION_VIEW
val b = Bundle()
b.putInt(AppShortcutLauncherActivity.KEY_SHORTCUT_TYPE, shortcutType)
intent.putExtras(b)
return intent
}
companion object {
internal const val ID_PREFIX = "code.name.monkey.retromusic.appshortcuts.id."
val id: String
get() = ID_PREFIX + "invalid"
}
}

View File

@ -1,34 +0,0 @@
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,27 @@
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
@TargetApi(Build.VERSION_CODES.N_MR1)
class LastAddedShortcutType(context: Context) : BaseShortcutType(context) {
override val shortcutInfo: ShortcutInfo
get() = ShortcutInfo.Builder(context, id)
.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()
companion object {
val id: String
get() = BaseShortcutType.ID_PREFIX + "last_added"
}
}

View File

@ -0,0 +1,26 @@
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
@TargetApi(Build.VERSION_CODES.N_MR1)
class SearchShortCutType(context: Context) : BaseShortcutType(context) {
companion object {
val id: String
get() = BaseShortcutType.ID_PREFIX + "search"
}
override val shortcutInfo: ShortcutInfo
get() = ShortcutInfo.Builder(context, id)
.setShortLabel(context.getString(R.string.action_search))
.setLongLabel(context.getString(R.string.search_hint))
.setIcon(AppShortcutIconGenerator.generateThemedIcon(context, R.drawable.ic_app_shortcut_search))
.setIntent(getPlaySongsIntent(AppShortcutLauncherActivity.SHORTCUT_TYPE_SEARCH))
.build()
}

View File

@ -1,35 +0,0 @@
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,29 @@
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
import java.security.AccessController.getContext
@TargetApi(Build.VERSION_CODES.N_MR1)
class ShuffleAllShortcutType(context: Context) : BaseShortcutType(context) {
override val shortcutInfo: ShortcutInfo
get() = ShortcutInfo.Builder(context, id)
.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()
companion object {
val id: String
get() = BaseShortcutType.ID_PREFIX + "shuffle_all"
}
}

View File

@ -1,35 +0,0 @@
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,27 @@
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
@TargetApi(Build.VERSION_CODES.N_MR1)
class TopTracksShortcutType(context: Context) : BaseShortcutType(context) {
override val shortcutInfo: ShortcutInfo
get() = ShortcutInfo.Builder(context, id)
.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()
companion object {
val id: String
get() = BaseShortcutType.ID_PREFIX + "top_tracks"
}
}

View File

@ -136,16 +136,7 @@ abstract class BaseAppWidget : AppWidgetProvider() {
}
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)

View File

@ -1,61 +0,0 @@
package code.name.monkey.retromusic.cast;
import android.net.Uri;
import com.google.android.gms.cast.MediaInfo;
import com.google.android.gms.cast.MediaLoadOptions;
import com.google.android.gms.cast.MediaMetadata;
import com.google.android.gms.cast.framework.CastSession;
import com.google.android.gms.cast.framework.media.RemoteMediaClient;
import com.google.android.gms.common.images.WebImage;
import java.net.MalformedURLException;
import java.net.URL;
import code.name.monkey.retromusic.Constants;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.util.RetroUtil;
import static code.name.monkey.retromusic.Constants.CAST_SERVER_PORT;
public class CastHelper {
public static void startCasting(CastSession castSession, Song song) {
String ipAddress = RetroUtil.getIPAddress(true);
URL baseUrl;
try {
baseUrl = new URL("https", ipAddress,CAST_SERVER_PORT, "");
} catch (MalformedURLException e) {
e.printStackTrace();
return;
}
String songUrl = baseUrl.toString() + "/song?id=" + song.getId();
String albumArtUrl = baseUrl.toString() + "/albumart?id=" + song.getAlbumId();
MediaMetadata musicMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MUSIC_TRACK);
musicMetadata.putString(MediaMetadata.KEY_TITLE, song.getTitle());
musicMetadata.putString(MediaMetadata.KEY_ARTIST, song.getArtistName());
musicMetadata.putString(MediaMetadata.KEY_ALBUM_TITLE, song.getAlbumName());
musicMetadata.putInt(MediaMetadata.KEY_TRACK_NUMBER, song.getTrackNumber());
musicMetadata.addImage(new WebImage(Uri.parse(albumArtUrl)));
try {
MediaInfo mediaInfo = new MediaInfo.Builder(songUrl)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType("audio/mpeg")
.setMetadata(musicMetadata)
.setStreamDuration(song.getDuration())
.build();
RemoteMediaClient remoteMediaClient = castSession.getRemoteMediaClient();
remoteMediaClient.load(mediaInfo, new MediaLoadOptions.Builder()
.build());
//remoteMediaClient.load(mediaInfo, true, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -1,45 +0,0 @@
package code.name.monkey.retromusic.cast;
import android.content.Context;
import com.google.android.gms.cast.framework.CastOptions;
import com.google.android.gms.cast.framework.OptionsProvider;
import com.google.android.gms.cast.framework.SessionProvider;
import com.google.android.gms.cast.framework.media.CastMediaOptions;
import com.google.android.gms.cast.framework.media.MediaIntentReceiver;
import com.google.android.gms.cast.framework.media.NotificationOptions;
import java.util.ArrayList;
import java.util.List;
import code.name.monkey.retromusic.R;
public class CastOptionsProvider implements OptionsProvider {
@Override
public CastOptions getCastOptions(Context context) {
List<String> buttonActions = new ArrayList<>();
buttonActions.add(MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK);
buttonActions.add(MediaIntentReceiver.ACTION_STOP_CASTING);
int[] compatButtonActionsIndicies = new int[]{ 0, 1 };
NotificationOptions notificationOptions = new NotificationOptions.Builder()
.setActions(buttonActions, compatButtonActionsIndicies)
.setTargetActivityClassName(ExpandedCastControlsActivity.class.getName())
.build();
CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
.setNotificationOptions(notificationOptions)
.setExpandedControllerActivityClassName(ExpandedCastControlsActivity.class.getName())
.build();
return new CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.cast_app_id))
.setCastMediaOptions(mediaOptions)
.build();
}
@Override
public List<SessionProvider> getAdditionalSessionProviders(Context context) {
return null;
}
}

View File

@ -1,28 +0,0 @@
package code.name.monkey.retromusic.cast;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import com.google.android.gms.cast.framework.CastButtonFactory;
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity;
import code.name.monkey.retromusic.R;
public class ExpandedCastControlsActivity extends ExpandedControllerActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_expanded_controller, menu);
CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item);
return true;
}
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
}

View File

@ -1,77 +0,0 @@
package code.name.monkey.retromusic.cast;
import android.content.Context;
import android.net.Uri;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Map;
import code.name.monkey.retromusic.Constants;
import code.name.monkey.retromusic.util.RetroUtil;
import fi.iki.elonen.NanoHTTPD;
import static code.name.monkey.retromusic.Constants.CAST_SERVER_PORT;
public class WebServer extends NanoHTTPD {
private Context context;
private Uri songUri, albumArtUri;
public WebServer(Context context) {
super(CAST_SERVER_PORT);
this.context = context;
}
@Override
public Response serve(String uri, Method method,
Map<String, String> header,
Map<String, String> parameters,
Map<String, String> files) {
if (uri.contains("albumart")) {
//serve the picture
String albumId = parameters.get("id");
this.albumArtUri = RetroUtil.getAlbumArtUri(Long.parseLong(albumId));
if (albumArtUri != null) {
String mediasend = "image/jpg";
InputStream fisAlbumArt = null;
try {
fisAlbumArt = context.getContentResolver().openInputStream(albumArtUri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Response.Status st = Response.Status.OK;
//serve the song
return newChunkedResponse(st, mediasend, fisAlbumArt);
}
} else if (uri.contains("song")) {
String songId = parameters.get("id");
this.songUri = RetroUtil.getSongUri(context, Long.parseLong(songId));
if (songUri != null) {
String mediasend = "audio/mp3";
FileInputStream fisSong = null;
File song = new File(songUri.getPath());
try {
fisSong = new FileInputStream(song);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Response.Status st = Response.Status.OK;
//serve the song
return newFixedLengthResponse(st, mediasend, fisSong, song.length());
}
}
return newFixedLengthResponse("Error");
}
}

View File

@ -32,7 +32,7 @@ class AddToPlaylistDialog : RoundedBottomSheetDialogFragment() {
actionAddPlaylist.setOnClickListener {
val songs = arguments!!.getParcelableArrayList<Song>("songs")
CreatePlaylistDialog.create(songs).show(activity!!.supportFragmentManager, "ADD_TO_PLAYLIST")
CreatePlaylistDialog.create(songs!!).show(activity!!.supportFragmentManager, "ADD_TO_PLAYLIST")
dismiss()
}

View File

@ -20,8 +20,8 @@ class DeleteSongsDialog : RoundedBottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
title.setTextColor(ThemeStore.textColorPrimary(context!!))
MaterialUtil.setTint(actionDelete, true)
MaterialUtil.setTint(actionCancel, false)
MaterialUtil.setTint(actionDelete)
MaterialUtil.setTint(actionCancel)
//noinspection unchecked,ConstantConditions
val songs = arguments!!.getParcelableArrayList<Song>("songs")

View File

@ -1,6 +1,7 @@
package code.name.monkey.retromusic.dialogs
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Bitmap
import android.os.Bundle
import android.view.LayoutInflater
@ -57,7 +58,11 @@ class OptionsSheetDialogFragment : RoundedBottomSheetDialogFragment(), View.OnCl
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
actionBuyPro.visibility = if (!App.isProVersion) View.VISIBLE else View.GONE
actionBuyPro.let {
it.visibility = if (!App.isProVersion) View.VISIBLE else View.GONE
it.iconTint = ColorStateList.valueOf(ThemeStore.accentColor(it.context))
it.setTextColor(ColorStateList.valueOf(ThemeStore.accentColor(it.context)))
}
text!!.setTextColor(ThemeStore.textColorSecondary(context!!))
titleWelcome!!.setTextColor(ThemeStore.textColorPrimary(context!!))
titleWelcome!!.text = String.format("%s %s!", timeOfTheDay, PreferenceUtil.getInstance().userName)

View File

@ -85,8 +85,8 @@ class BlurTransformation : BitmapTransformation {
return StackBlur.blur(out, blurRadius)
}
override fun equals(o: Any?): Boolean {
return o is BlurTransformation
override fun equals(other: Any?): Boolean {
return other is BlurTransformation
}
override fun hashCode(): Int {
@ -138,7 +138,7 @@ class BlurTransformation : BitmapTransformation {
companion object {
val DEFAULT_BLUR_RADIUS = 5f
private val ID = "com.poupa.vinylmusicplayer.glide.BlurTransformation"
const val DEFAULT_BLUR_RADIUS = 5f
private const val ID = "code.name.monkey.retromusic.glide.BlurTransformation"
}
}

View File

@ -1,5 +1,7 @@
package code.name.monkey.retromusic.glide;
import androidx.annotation.NonNull;
import com.bumptech.glide.GenericTransitionOptions;
import com.bumptech.glide.Priority;
import com.bumptech.glide.RequestBuilder;
@ -8,11 +10,11 @@ import com.bumptech.glide.annotation.GlideOption;
import com.bumptech.glide.annotation.GlideType;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.signature.MediaStoreSignature;
import androidx.annotation.NonNull;
import code.name.monkey.retromusic.App;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.artistimage.ArtistImage;
@ -34,6 +36,7 @@ public final class RetroGlideExtension {
public static void asBitmapPalette(RequestBuilder<BitmapPaletteWrapper> requestBuilder) {
}
@NonNull
@GlideOption
public static RequestOptions artistOptions(@NonNull RequestOptions requestOptions, Artist artist) {
return requestOptions
@ -46,11 +49,12 @@ public final class RetroGlideExtension {
}
@GlideOption
@NonNull
public static RequestOptions songOptions(@NonNull RequestOptions requestOptions, Song song) {
return requestOptions
.diskCacheStrategy(DiskCacheStrategy.NONE)
.error(R.drawable.default_album_art)
.placeholder(R.drawable.default_album_art)
//.placeholder(R.drawable.default_album_art)
.signature(createSignature(song));
}
@ -93,4 +97,5 @@ public final class RetroGlideExtension {
public static <TranscodeType> GenericTransitionOptions<TranscodeType> getDefaultTransition() {
return new GenericTransitionOptions<TranscodeType>().transition(android.R.anim.fade_in);
}
}

View File

@ -1,4 +0,0 @@
package code.name.monkey.retromusic.glide.artistimage
class ArtistImage(val artistName: String, val skipOkHttpCache: Boolean)

View File

@ -1,98 +0,0 @@
package code.name.monkey.retromusic.glide.artistimage
import android.content.Context
import android.text.TextUtils
import code.name.monkey.retromusic.rest.LastFMRestClient
import code.name.monkey.retromusic.rest.model.LastFmArtist
import code.name.monkey.retromusic.util.LastFMUtil
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.RetroUtil
import com.bumptech.glide.Priority
import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.GlideUrl
import okhttp3.OkHttpClient
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import java.io.InputStream
class ArtistImageFetcher(private val context: Context, private val lastFMRestClient: LastFMRestClient, private val okHttp: OkHttpClient, private val model: ArtistImage, width: Int, height: Int) : DataFetcher<InputStream> {
@Volatile
private var isCancelled: Boolean = false
private var call: Call<LastFmArtist>? = null
private var streamFetcher: OkHttpStreamFetcher? = null
override fun getDataClass(): Class<InputStream> {
return InputStream::class.java
}
override fun getDataSource(): DataSource {
return DataSource.REMOTE
}
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
try {
if (!MusicUtil.isArtistNameUnknown(model.artistName) && RetroUtil.isAllowedToDownloadMetadata(context)) {
call = lastFMRestClient.apiService.getArtistInfo(model.artistName, null, if (model.skipOkHttpCache) "no-cache" else null)
call!!.enqueue(object : Callback<LastFmArtist> {
override fun onResponse(call: Call<LastFmArtist>, response: Response<LastFmArtist>) {
if (isCancelled) {
callback.onDataReady(null)
return
}
val lastFmArtist = response.body()
if (lastFmArtist == null || lastFmArtist.artist == null || lastFmArtist.artist.image == null) {
callback.onLoadFailed(Exception("No artist image url found"))
return
}
val url = LastFMUtil.getLargestArtistImageUrl(lastFmArtist.artist.image)
if (TextUtils.isEmpty(url) || TextUtils.isEmpty(url.trim { it <= ' ' })) {
callback.onLoadFailed(Exception("No artist image url found"))
return
}
streamFetcher = OkHttpStreamFetcher(okHttp, GlideUrl(url))
streamFetcher!!.loadData(priority, callback)
}
override fun onFailure(call: Call<LastFmArtist>, throwable: Throwable) {
callback.onLoadFailed(Exception(throwable))
}
})
}
} catch (e: Exception) {
callback.onLoadFailed(e)
}
}
override fun cleanup() {
if (streamFetcher != null) {
streamFetcher!!.cleanup()
}
}
override fun cancel() {
isCancelled = true
if (call != null) {
call!!.cancel()
}
if (streamFetcher != null) {
streamFetcher!!.cancel()
}
}
companion object {
val TAG: String = ArtistImageFetcher::class.java.simpleName
}
}

View File

@ -1,17 +1,109 @@
package code.name.monkey.retromusic.glide.artistimage
import android.content.Context
import android.text.TextUtils
import code.name.monkey.retromusic.rest.LastFMRestClient
import code.name.monkey.retromusic.rest.model.LastFmArtist
import code.name.monkey.retromusic.util.LastFMUtil
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.RetroUtil
import com.bumptech.glide.Priority
import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey
import okhttp3.OkHttpClient
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.InputStream
import java.util.concurrent.TimeUnit
class ArtistImage(val artistName: String, val skipOkHttpCache: Boolean)
class ArtistImageFetcher(private val context: Context, private val lastFMRestClient: LastFMRestClient, private val okHttp: OkHttpClient, private val model: ArtistImage, width: Int, height: Int) : DataFetcher<InputStream> {
@Volatile
private var isCancelled: Boolean = false
private var call: Call<LastFmArtist>? = null
private var streamFetcher: OkHttpStreamFetcher? = null
override fun getDataClass(): Class<InputStream> {
return InputStream::class.java
}
override fun getDataSource(): DataSource {
return DataSource.REMOTE
}
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
try {
if (!MusicUtil.isArtistNameUnknown(model.artistName) && RetroUtil.isAllowedToDownloadMetadata(context)) {
call = lastFMRestClient.apiService.getArtistInfo(model.artistName, null, if (model.skipOkHttpCache) "no-cache" else null)
call!!.enqueue(object : Callback<LastFmArtist> {
override fun onResponse(call: Call<LastFmArtist>, response: Response<LastFmArtist>) {
if (isCancelled) {
callback.onDataReady(null)
return
}
val lastFmArtist = response.body()
if (lastFmArtist == null || lastFmArtist.artist == null || lastFmArtist.artist.image == null) {
callback.onLoadFailed(Exception("No artist image url found"))
return
}
val url = LastFMUtil.getLargestArtistImageUrl(lastFmArtist.artist.image)
if (TextUtils.isEmpty(url) || TextUtils.isEmpty(url.trim { it <= ' ' })) {
callback.onLoadFailed(Exception("No artist image url found"))
return
}
streamFetcher = OkHttpStreamFetcher(okHttp, GlideUrl(url))
streamFetcher!!.loadData(priority, callback)
}
override fun onFailure(call: Call<LastFmArtist>, throwable: Throwable) {
callback.onLoadFailed(Exception(throwable))
}
})
}
} catch (e: Exception) {
callback.onLoadFailed(e)
}
}
override fun cleanup() {
if (streamFetcher != null) {
streamFetcher!!.cleanup()
}
}
override fun cancel() {
isCancelled = true
if (call != null) {
call!!.cancel()
}
if (streamFetcher != null) {
streamFetcher!!.cancel()
}
}
companion object {
val TAG: String = ArtistImageFetcher::class.java.simpleName
}
}
class ArtistImageLoader(private val context: Context, private val lastFMClient: LastFMRestClient, private val okhttp: OkHttpClient) : ModelLoader<ArtistImage, InputStream> {
override fun buildLoadData(model: ArtistImage, width: Int, height: Int, options: Options): ModelLoader.LoadData<InputStream>? {

View File

@ -1,4 +0,0 @@
package code.name.monkey.retromusic.glide.audiocover
class AudioFileCover(val filePath: String)

View File

@ -1,92 +0,0 @@
package code.name.monkey.retromusic.glide.audiocover
import android.media.MediaMetadataRetriever
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.data.DataFetcher
import org.jaudiotagger.audio.mp3.MP3File
import java.io.*
/**
* @author Karim Abou Zeid (kabouzeid)
*/
class AudioFileCoverFetcher(private val model: AudioFileCover) : DataFetcher<InputStream> {
private var stream: FileInputStream? = null
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
val retriever = MediaMetadataRetriever()
val data: InputStream?
try {
retriever.setDataSource(model.filePath)
val picture = retriever.embeddedPicture
if (picture != null) {
data = ByteArrayInputStream(picture)
} else {
data = fallback(model.filePath)
}
callback.onDataReady(data)
} catch (e: FileNotFoundException) {
callback.onLoadFailed(e)
} finally {
retriever.release()
}
}
override fun getDataClass(): Class<InputStream> {
return InputStream::class.java
}
override fun getDataSource(): DataSource {
return DataSource.LOCAL
}
@Throws(FileNotFoundException::class)
private fun fallback(path: String): InputStream? {
try {
val mp3File = MP3File(path)
if (mp3File.hasID3v2Tag()) {
val art = mp3File.tag.firstArtwork
if (art != null) {
val imageData = art.binaryData
return ByteArrayInputStream(imageData)
}
}
// If there are any exceptions, we ignore them and continue to the other fallback method
} catch (ignored: Exception) {
}
// Method 2: look for album art in external files
val parent = File(path).parentFile
for (fallback in FALLBACKS) {
val cover = File(parent, fallback)
if (cover.exists()) {
stream = FileInputStream(cover)
return stream
}
}
return null
}
override fun cleanup() {
// already cleaned up in loadData and ByteArrayInputStream will be GC'd
if (stream != null) {
try {
stream!!.close()
} catch (ignore: IOException) {
// can't do much about it
}
}
}
override fun cancel() {
// cannot cancel
}
companion object {
private val FALLBACKS = arrayOf("cover.jpg", "album.jpg", "folder.jpg", "cover.png", "album.png", "folder.png")
}
}

View File

@ -1,14 +1,102 @@
package code.name.monkey.retromusic.glide.audiocover
import android.media.MediaMetadataRetriever
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoader.LoadData
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey
import java.io.InputStream
import org.jaudiotagger.audio.mp3.MP3File
import java.io.*
class AudioFileCover(val filePath: String)
class AudioFileCoverFetcher(private val model: AudioFileCover) : DataFetcher<InputStream> {
private var stream: FileInputStream? = null
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
val retriever = MediaMetadataRetriever()
val data: InputStream?
try {
retriever.setDataSource(model.filePath)
val picture = retriever.embeddedPicture
if (picture != null) {
data = ByteArrayInputStream(picture)
} else {
data = fallback(model.filePath)
}
callback.onDataReady(data)
} catch (e: FileNotFoundException) {
callback.onLoadFailed(e)
} finally {
retriever.release()
}
}
override fun getDataClass(): Class<InputStream> {
return InputStream::class.java
}
override fun getDataSource(): DataSource {
return DataSource.LOCAL
}
@Throws(FileNotFoundException::class)
private fun fallback(path: String): InputStream? {
try {
val mp3File = MP3File(path)
if (mp3File.hasID3v2Tag()) {
val art = mp3File.tag.firstArtwork
if (art != null) {
val imageData = art.binaryData
return ByteArrayInputStream(imageData)
}
}
// If there are any exceptions, we ignore them and continue to the other fallback method
} catch (ignored: Exception) {
}
// Method 2: look for album art in external files
val parent = File(path).parentFile
for (fallback in FALLBACKS) {
val cover = File(parent, fallback)
if (cover.exists()) {
stream = FileInputStream(cover)
return stream
}
}
return null
}
override fun cleanup() {
// already cleaned up in loadData and ByteArrayInputStream will be GC'd
if (stream != null) {
try {
stream!!.close()
} catch (ignore: IOException) {
// can't do much about it
}
}
}
override fun cancel() {
// cannot cancel
}
companion object {
private val FALLBACKS = arrayOf("cover.jpg", "album.jpg", "folder.jpg", "cover.png", "album.png", "folder.png")
}
}
class AudioFileCoverLoader : ModelLoader<AudioFileCover, InputStream> {
override fun buildLoadData(model: AudioFileCover, width: Int, height: Int,
options: Options): LoadData<InputStream>? {

View File

@ -1,8 +1,33 @@
package code.name.monkey.retromusic.glide.palette
import android.graphics.Bitmap
import android.widget.ImageView
import androidx.palette.graphics.Palette
import code.name.monkey.retromusic.util.RetroColorUtil
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder
import com.bumptech.glide.request.target.ImageViewTarget
import com.bumptech.glide.util.Util
class BitmapPaletteTranscoder : ResourceTranscoder<Bitmap, BitmapPaletteWrapper> {
override fun transcode(bitmapResource: Resource<Bitmap>, options: Options): Resource<BitmapPaletteWrapper>? {
val bitmap = bitmapResource.get()
val bitmapPaletteWrapper = BitmapPaletteWrapper(bitmap, RetroColorUtil.generatePalette(bitmap)!!)
return BitmapPaletteResource(bitmapPaletteWrapper)
}
}
class BitmapPaletteWrapper(val bitmap: Bitmap, val palette: Palette)
open class BitmapPaletteTarget(view: ImageView) : ImageViewTarget<BitmapPaletteWrapper>(view) {
override fun setResource(bitmapPaletteWrapper: BitmapPaletteWrapper?) {
if (bitmapPaletteWrapper != null) {
view.setImageBitmap(bitmapPaletteWrapper.bitmap)
}
}
}
class BitmapPaletteResource(private val bitmapPaletteWrapper: BitmapPaletteWrapper) : Resource<BitmapPaletteWrapper> {

View File

@ -1,14 +0,0 @@
package code.name.monkey.retromusic.glide.palette
import android.widget.ImageView
import com.bumptech.glide.request.target.ImageViewTarget
open class BitmapPaletteTarget(view: ImageView) : ImageViewTarget<BitmapPaletteWrapper>(view) {
override fun setResource(bitmapPaletteWrapper: BitmapPaletteWrapper?) {
if (bitmapPaletteWrapper != null) {
view.setImageBitmap(bitmapPaletteWrapper.bitmap)
}
}
}

View File

@ -1,16 +0,0 @@
package code.name.monkey.retromusic.glide.palette
import android.graphics.Bitmap
import code.name.monkey.retromusic.util.RetroColorUtil
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder
class BitmapPaletteTranscoder : ResourceTranscoder<Bitmap, BitmapPaletteWrapper> {
override fun transcode(bitmapResource: Resource<Bitmap>, options: Options): Resource<BitmapPaletteWrapper>? {
val bitmap = bitmapResource.get()
val bitmapPaletteWrapper = BitmapPaletteWrapper(bitmap, RetroColorUtil.generatePalette(bitmap)!!)
return BitmapPaletteResource(bitmapPaletteWrapper)
}
}

View File

@ -1,6 +0,0 @@
package code.name.monkey.retromusic.glide.palette
import android.graphics.Bitmap
import androidx.palette.graphics.Palette
class BitmapPaletteWrapper(val bitmap: Bitmap, val palette: Palette)

View File

@ -12,13 +12,10 @@ import android.provider.MediaStore
import android.util.Log
import android.widget.Toast
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.loaders.SongLoader
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.PreferenceUtil
import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.cast.framework.CastSession
import io.reactivex.schedulers.Schedulers
import java.io.File
import java.util.*
@ -28,19 +25,6 @@ object MusicPlayerRemote {
val TAG = MusicPlayerRemote::class.java.simpleName
private val mConnectionMap = WeakHashMap<Context, ServiceBinder>()
var musicService: MusicService? = null
private var playbackLocation = PlaybackLocation.LOCAL
private val castSession: CastSession?
get() {
val castSession = CastContext.getSharedInstance(App.instance).sessionManager.currentCastSession
if (castSession != null) {
playbackLocation = PlaybackLocation.REMOTE
} else {
playbackLocation = PlaybackLocation.LOCAL
}
return castSession
}
val isPlaying: Boolean
get() = musicService != null && musicService!!.isPlaying

View File

@ -88,7 +88,7 @@ class AboutActivity : AbsBaseActivity(), View.OnClickListener {
toolbar.setBackgroundColor(ThemeStore.primaryColor(this))
setSupportActionBar(toolbar)
title = null
ToolbarContentTintHelper.colorBackButton(toolbar, ThemeStore.accentColor(this))
ToolbarContentTintHelper.colorBackButton(toolbar, ThemeStore.textColorSecondary(this))
}
private fun openUrl(url: String) {
@ -161,8 +161,7 @@ class AboutActivity : AbsBaseActivity(), View.OnClickListener {
.setText(String.format(getString(R.string.app_share), packageName))
.intent
if (shareIntent.resolveActivity(packageManager) != null) {
startActivity(
Intent.createChooser(shareIntent, resources.getText(R.string.action_share)))
startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.action_share)))
}
}

View File

@ -6,6 +6,7 @@ import android.os.Bundle
import android.transition.Slide
import android.view.*
import android.view.animation.AnimationUtils
import android.widget.ImageView
import androidx.core.app.ActivityCompat
import androidx.core.util.Pair
import androidx.core.widget.NestedScrollView
@ -39,6 +40,9 @@ import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.RetroUtil
import com.google.android.material.appbar.AppBarLayout
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_album.*
import kotlinx.android.synthetic.main.activity_album_content.*
import java.util.*
@ -47,6 +51,7 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsContrac
private lateinit var albumDetailsPresenter: AlbumDetailsPresenter
private lateinit var simpleSongAdapter: SimpleSongAdapter
private var disposable = CompositeDisposable()
var album: Album? = null
private set
@ -68,11 +73,11 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsContrac
setDrawUnderStatusBar()
setupWindowTransition()
super.onCreate(savedInstanceState)
toggleBottomNavigationView(true)
setLightNavigationBar(true)
setNavigationbarColorAuto()
toggleBottomNavigationView(true)
ActivityCompat.postponeEnterTransition(this)
@ -95,6 +100,8 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsContrac
}
actionShuffleAll.setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(album!!.songs!!, true) }
artistImage = findViewById(R.id.artistImage)
artistImage.setOnClickListener {
val artistPairs = arrayOf<Pair<*, *>>(Pair.create(image, resources.getString(R.string.transition_artist_image)))
NavigationUtil.goToArtist(this, album!!.artistId, *artistPairs)
@ -134,24 +141,22 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsContrac
toolbar!!.layoutParams = params
}
if (appBarLayout != null) {
appBarLayout!!.apply {
addOnOffsetChangedListener(object : AppBarStateChangeListener() {
override fun onStateChanged(appBarLayout: AppBarLayout, state: AppBarStateChangeListener.State) {
val color: Int = when (state) {
AppBarStateChangeListener.State.COLLAPSED -> {
setLightStatusbar(ColorUtil.isColorLight(ThemeStore.primaryColor(this@AlbumDetailsActivity)))
ThemeStore.primaryColor(this@AlbumDetailsActivity)
}
AppBarStateChangeListener.State.EXPANDED, AppBarStateChangeListener.State.IDLE -> {
setLightStatusbar(false)
Color.TRANSPARENT
}
appBarLayout!!.apply {
addOnOffsetChangedListener(object : AppBarStateChangeListener() {
override fun onStateChanged(appBarLayout: AppBarLayout, state: AppBarStateChangeListener.State) {
val color: Int = when (state) {
AppBarStateChangeListener.State.COLLAPSED -> {
setLightStatusbar(ColorUtil.isColorLight(ThemeStore.primaryColor(this@AlbumDetailsActivity)))
ThemeStore.primaryColor(this@AlbumDetailsActivity)
}
AppBarStateChangeListener.State.EXPANDED, AppBarStateChangeListener.State.IDLE -> {
setLightStatusbar(false)
Color.TRANSPARENT
}
ToolbarContentTintHelper.setToolbarContentColorBasedOnToolbarColor(this@AlbumDetailsActivity, toolbar, color)
}
})
}
ToolbarContentTintHelper.setToolbarContentColorBasedOnToolbarColor(this@AlbumDetailsActivity, toolbar, color)
}
})
}
}
@ -160,6 +165,11 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsContrac
albumDetailsPresenter.unsubscribe()
}
override fun onDestroy() {
super.onDestroy()
disposable.dispose()
}
override fun loading() {
}
@ -188,33 +198,42 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsContrac
simpleSongAdapter.swapDataSet(list.songs)
}
private lateinit var artistImage: ImageView
private fun loadMoreFrom(album: Album) {
if (artistImage != null) {
/*ArtistGlideRequest.Builder.from(Glide.with(this),
ArtistLoader.getArtist(this, album.artistId).blockingFirst())
.forceDownload(false)
.generatePalette(this).build()
.dontAnimate()
.into(object : RetroMusicColoredTarget(artistImage as CircularImageView) {
override fun onColorReady(color: Int) {
//setColors(color);
}
})*/
}
disposable.add(ArtistLoader.getArtist(this, album.artistId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map {
GlideApp.with(this@AlbumDetailsActivity)
.asBitmapPalette()
.load(RetroGlideExtension.getArtistModel(it))
.transition(RetroGlideExtension.getDefaultTransition())
.artistOptions(it)
.dontAnimate()
.into(object : RetroMusicColoredTarget(artistImage) {
override fun onColorReady(color: Int) {
val albums = ArtistLoader.getArtist(this, album.artistId).blockingFirst().albums
albums!!.remove(album)
if (!albums.isEmpty()) {
moreTitle.visibility = View.VISIBLE
moreRecyclerView.visibility = View.VISIBLE
} else {
return
}
moreTitle.text = String.format("More from %s", album.artistName)
}
})
return@map it.albums!!
}
.subscribe {
val albumAdapter = HorizontalAlbumAdapter(this, albums, false, null)
moreRecyclerView.layoutManager = GridLayoutManager(this, 1, GridLayoutManager.HORIZONTAL, false)
moreRecyclerView.adapter = albumAdapter
it.remove(album)
if (!it.isEmpty()) {
moreTitle.visibility = View.VISIBLE
moreRecyclerView.visibility = View.VISIBLE
} else {
return@subscribe
}
moreTitle.text = String.format("More from %s", album.artistName)
val albumAdapter = HorizontalAlbumAdapter(this, it, false, null)
moreRecyclerView.layoutManager = GridLayoutManager(this, 1, GridLayoutManager.HORIZONTAL, false)
moreRecyclerView.adapter = albumAdapter
})
}
private fun loadAlbumCover() {

View File

@ -55,7 +55,7 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailContrac
private var albumAdapter: AlbumAdapter? = null
private var forceDownload: Boolean = false
private fun setupWindowTransistion() {
private fun setupWindowTransitions() {
val slide = Slide(Gravity.BOTTOM)
slide.interpolator = AnimationUtils.loadInterpolator(this, android.R.interpolator.linear_out_slow_in)
window.enterTransition = slide
@ -68,7 +68,7 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailContrac
override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar()
setupWindowTransistion()
setupWindowTransitions()
super.onCreate(savedInstanceState)
@ -143,15 +143,14 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailContrac
if (appBarLayout != null) {
appBarLayout!!.addOnOffsetChangedListener(object : AppBarStateChangeListener() {
override fun onStateChanged(appBarLayout: AppBarLayout, state: AppBarStateChangeListener.State) {
val color: Int
when (state) {
val color: Int = when (state) {
AppBarStateChangeListener.State.COLLAPSED -> {
setLightStatusbar(ColorUtil.isColorLight(ThemeStore.primaryColor(appBarLayout.context)))
color = ThemeStore.primaryColor(appBarLayout.context)
ThemeStore.primaryColor(appBarLayout.context)
}
AppBarStateChangeListener.State.EXPANDED, AppBarStateChangeListener.State.IDLE -> {
setLightStatusbar(false)
color = Color.TRANSPARENT
Color.TRANSPARENT
}
}
@ -204,8 +203,8 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailContrac
ActivityCompat.startPostponedEnterTransition(this)
}
override fun showData(artist: Artist) {
setArtist(artist)
override fun showData(list: Artist) {
setArtist(list)
}
private fun getArtist(): Artist {
@ -296,7 +295,6 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailContrac
actionShuffleAll.setColor(textColor)
findViewById<View>(R.id.root).setBackgroundColor(ThemeStore.primaryColor(this))
}

View File

@ -10,6 +10,7 @@ import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.viewpager.widget.ViewPager
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.App
@ -23,6 +24,7 @@ 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 kotlinx.android.synthetic.main.activity_lyrics.*
@ -32,7 +34,19 @@ import org.jaudiotagger.tag.FieldKey
import java.io.File
import java.util.*
class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener {
class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener, ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
PreferenceUtil.getInstance().lyricsOptions = position
}
override fun onClick(v: View?) {
when (viewPager.currentItem) {
0 -> showSyncedLyrics()
@ -41,7 +55,7 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener {
}
private lateinit var song: Song
private var lyrics: Lyrics? = null
private var lyricsString: String? = null
private val googleSearchLrcUrl: String
get() {
@ -73,7 +87,10 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener {
viewPager.apply {
adapter = PagerAdapter(supportFragmentManager)
currentItem = PreferenceUtil.getInstance().lyricsOptions
addOnPageChangeListener(this@LyricsActivity)
}
tabs.apply {
setupWithViewPager(viewPager)
setSelectedTabIndicator(TintHelper.createTintedDrawable(ContextCompat.getDrawable(this@LyricsActivity, R.drawable.tab_indicator), ThemeStore.accentColor(this@LyricsActivity)))
@ -132,10 +149,10 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener {
}
private fun showLyricsSaveDialog() {
val content: String = if (lyrics == null) {
val content: String = if (lyricsString == null) {
""
} else {
lyrics!!.data
lyricsString!!
}
MaterialDialog.Builder(this)
.title("Add lyrics")
@ -163,155 +180,160 @@ class LyricsActivity : AbsMusicServiceActivity(), View.OnClickListener {
baseUrl += query
return baseUrl
}
}
class PagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
override fun getItem(position: Int): Fragment {
return when (position) {
0 -> SyncedLyricsFragment()
1 -> OfflineLyricsFragment()
else -> {
SyncedLyricsFragment()
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
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)
}
offlineLyrics.text = l.data
}
}
override fun onCancelled(s: Lyrics?) {
onPostExecute(null)
override fun getCount(): Int {
return 2
}
}
abstract class BaseLyricsFragment : AbsMusicServiceFragment() {
abstract fun upDateSong()
override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged()
upDateSong()
}
override fun onServiceConnected() {
super.onServiceConnected()
upDateSong()
}
}
class OfflineLyricsFragment : BaseLyricsFragment() {
override fun upDateSong() {
loadSongLyrics()
}
private var updateLyricsAsyncTask: AsyncTask<*, *, *>? = null
private var lyrics: Lyrics? = null
@SuppressLint("StaticFieldLeak")
private fun loadSongLyrics() {
if (updateLyricsAsyncTask != null) {
updateLyricsAsyncTask!!.cancel(false)
}
}.execute()
}
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 onDestroyView() {
super.onDestroyView()
if (updateLyricsAsyncTask != null && !updateLyricsAsyncTask!!.isCancelled) {
updateLyricsAsyncTask!!.cancel(true)
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
}
(activity as LyricsActivity).lyricsString = l.data
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 onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_lyrics, container, false)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
loadSongLyrics()
}
class SyncedLyricsFragment : BaseLyricsFragment(), MusicProgressViewUpdateHelper.Callback {
override fun upDateSong() {
loadLRCLyrics()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_lyrics, container, false)
}
}
private lateinit var updateHelper: MusicProgressViewUpdateHelper
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_synced, container, false)
}
class SyncedLyricsFragment : AbsMusicServiceFragment(), MusicProgressViewUpdateHelper.Callback {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
updateHelper = MusicProgressViewUpdateHelper(this, 500, 1000)
}
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 onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupLyricsView()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
updateHelper = MusicProgressViewUpdateHelper(this, 500, 1000)
}
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 onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupLyricsView()
}
override fun onResume() {
super.onResume()
updateHelper.start()
}
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 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")
}
}
}
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

@ -37,7 +37,6 @@ import java.util.*
class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, PlaylistSongsContract.PlaylistSongsView {
private var playlist: Playlist? = null
private var cab: MaterialCab? = null
private lateinit var adapter: SongAdapter
@ -49,7 +48,6 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
setStatusbarColor(Color.TRANSPARENT)
setNavigationbarColorAuto()
setTaskDescriptionColorAuto()
@ -203,6 +201,7 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
private fun checkIsEmpty() {
empty.visibility = if (adapter.itemCount == 0) View.VISIBLE else View.GONE
emptyText.visibility = if (adapter.itemCount == 0) View.VISIBLE else View.GONE
}
public override fun onPause() {
@ -239,7 +238,8 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
override fun loading() {}
override fun showEmptyView() {
empty!!.visibility = View.VISIBLE
empty.visibility = View.VISIBLE
emptyText.visibility = View.VISIBLE
}
override fun completed() {}

View File

@ -5,6 +5,7 @@ import android.app.SearchManager
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.res.ColorStateList
import android.os.Bundle
import android.speech.RecognizerIntent
import android.text.Editable
@ -15,6 +16,8 @@ import android.widget.Toast
import androidx.appcompat.widget.SearchView.OnQueryTextListener
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.mvp.contract.SearchContract
import code.name.monkey.retromusic.mvp.presenter.SearchPresenter
@ -35,7 +38,6 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, SearchCon
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search)
searchPresenter = SearchPresenter(this)
setStatusbarColorAuto()
@ -57,10 +59,12 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, SearchCon
}
back.setOnClickListener { onBackPressed() }
voiceSearch.setOnClickListener { startMicSearch() }
searchContainer.setCardBackgroundColor(ColorStateList.valueOf(ColorUtil.darkenColor(ThemeStore.primaryColor(this))))
}
private fun setupRecyclerView() {
searchAdapter = SearchAdapter(this, emptyList())
searchAdapter!!.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() {

View File

@ -1,10 +1,7 @@
package code.name.monkey.retromusic.ui.activities
import android.app.Activity
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import android.view.MenuItem
import androidx.annotation.ColorInt
import androidx.annotation.StringRes
@ -13,6 +10,7 @@ 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.App.Companion.context
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
import code.name.monkey.retromusic.ui.activities.base.AbsBaseActivity
@ -67,11 +65,13 @@ class SettingsActivity : AbsBaseActivity(), ColorChooserDialog.ColorCallback, Sh
private fun setupToolbar() {
setSupportActionBar(toolbar)
title = null
toolbar.setBackgroundColor(ThemeStore.primaryColor(this))
toolbar.apply {
setBackgroundColor(ThemeStore.primaryColor(context))
setNavigationOnClickListener { onBackPressed() }
ToolbarContentTintHelper.colorBackButton(toolbar, ThemeStore.textColorSecondary(context))
}
appBarLayout.setBackgroundColor(ThemeStore.primaryColor(this))
toolbar.setNavigationOnClickListener { onBackPressed() }
settingsTitle.setTextColor(ThemeStore.textColorPrimary(this))
ToolbarContentTintHelper.colorBackButton(toolbar, ThemeStore.accentColor(this))
}
fun setupFragment(fragment: Fragment, @StringRes titleName: Int) {
@ -126,6 +126,6 @@ class SettingsActivity : AbsBaseActivity(), ColorChooserDialog.ColorCallback, Sh
companion object {
const val TAG: String = "SettingsActivity"
const val TAG: String = "SettingsActivity"
}
}

View File

@ -180,7 +180,7 @@ class UserInfoActivity : AbsBaseActivity() {
}
private fun loadBannerFromStorage(profileImagePath: String) {
disposable!!.add(Compressor(this)
disposable.add(Compressor(this)
.setQuality(100)
.setCompressFormat(Bitmap.CompressFormat.WEBP)
.compressToBitmapAsFlowable(File(profileImagePath, USER_BANNER))
@ -190,7 +190,7 @@ class UserInfoActivity : AbsBaseActivity() {
}
private fun loadImageFromStorage(path: String) {
disposable!!.add(Compressor(this)
disposable.add(Compressor(this)
.setMaxHeight(300)
.setMaxWidth(300)
.setQuality(75)

View File

@ -1,135 +0,0 @@
package code.name.monkey.retromusic.ui.activities.base
import android.os.Bundle
import android.util.Log
import code.name.monkey.retromusic.cast.WebServer
import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.cast.framework.SessionManagerListener
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import java.io.IOException
abstract class AbsCastActivity : AbsCheckPiracy() {
var playServicesAvailable = false
private var castContext: CastContext? = null
private var sessionManagerListener: SessionManagerListener<CastSession>? = null
var castSession: CastSession? = null
private set
private var castServer: WebServer? = null
private fun setupCastListener() {
sessionManagerListener = object : SessionManagerListener<CastSession> {
override fun onSessionEnded(session: CastSession, error: Int) {
onApplicationDisconnected()
Log.i(TAG, "onSessionEnded: ")
}
override fun onSessionResumed(session: CastSession, wasSuspended: Boolean) {
onApplicationConnected(session)
Log.i(TAG, "onSessionResumed: ")
}
override fun onSessionResumeFailed(session: CastSession, error: Int) {
onApplicationDisconnected()
Log.i(TAG, "onSessionResumeFailed: ")
}
override fun onSessionStarted(session: CastSession, sessionId: String) {
onApplicationConnected(session)
Log.i(TAG, "onSessionStarted: ")
}
override fun onSessionStartFailed(session: CastSession, error: Int) {
onApplicationDisconnected()
Log.i(TAG, "onSessionStartFailed: ")
}
override fun onSessionStarting(session: CastSession) {}
override fun onSessionEnding(session: CastSession) {}
override fun onSessionResuming(session: CastSession, sessionId: String) {}
override fun onSessionSuspended(session: CastSession, reason: Int) {}
private fun onApplicationConnected(castSession: CastSession) {
this@AbsCastActivity.castSession = castSession
castServer = WebServer(applicationContext)
try {
castServer!!.start()
} catch (e: IOException) {
e.printStackTrace()
}
invalidateOptionsMenu()
showCastMiniController()
}
private fun onApplicationDisconnected() {
if (castServer != null) {
castServer!!.stop()
}
invalidateOptionsMenu()
hideCastMiniController()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
try {
playServicesAvailable = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS
} catch (ignored: Exception) {
}
if (playServicesAvailable)
initCast()
}
override fun onResume() {
if (playServicesAvailable) {
castContext!!.sessionManager.addSessionManagerListener(sessionManagerListener!!, CastSession::class.java)
}
super.onResume()
}
override fun onPause() {
super.onPause()
if (playServicesAvailable) {
castContext!!.sessionManager.removeSessionManagerListener(sessionManagerListener, CastSession::class.java)
}
}
private fun initCast() {
setupCastListener()
castContext = CastContext.getSharedInstance(this)
castSession = castContext!!.sessionManager.currentCastSession
}
/* @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_cast, menu);
if (playServicesAvailable) {
CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), menu, R.id.media_route_menu_item);
}
return true;
}*/
open fun showCastMiniController() {
//implement by overriding in activities
}
open fun hideCastMiniController() {
//implement by overriding in activities
}
companion object {
private val TAG = "AbsCastActivity"
}
}

View File

@ -1,5 +0,0 @@
package code.name.monkey.retromusic.ui.activities.base;
abstract public class AbsCheckPiracy extends AbsBaseActivity {
}

View File

@ -17,7 +17,7 @@ import java.lang.ref.WeakReference
import java.util.*
abstract class AbsMusicServiceActivity : AbsCastActivity(), MusicServiceEventListener {
abstract class AbsMusicServiceActivity : AbsBaseActivity(), MusicServiceEventListener {
private val mMusicServiceEventListeners = ArrayList<MusicServiceEventListener>()

View File

@ -31,7 +31,6 @@ 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.PreferenceUtil
import code.name.monkey.retromusic.views.BottomNavigationBarTinted
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.sothree.slidinguppanel.SlidingUpPanelLayout
import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelState
import kotlinx.android.synthetic.main.sliding_music_panel_layout.*
@ -125,13 +124,6 @@ abstract class AbsSlidingMusicPanelActivity protected constructor() : AbsMusicSe
return false
}
override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged()
castSession ?: return
//MusicPlayerRemote.setZeroVolume();
//CastHelper.startCasting(castSession, MusicPlayerRemote.getCurrentSong());
}
fun toggleBottomNavigationView(toggle: Boolean) {
bottomNavigationView.visibility = if (toggle) View.GONE else View.VISIBLE
}
@ -189,7 +181,7 @@ abstract class AbsSlidingMusicPanelActivity protected constructor() : AbsMusicSe
playerFragment!!.onHide()
}
open fun onPanelExpanded() {
open fun onPanelExpanded() {
val playerFragmentColor = playerFragment!!.paletteColor
super.setTaskDescriptionColor(playerFragmentColor)

View File

@ -110,7 +110,7 @@ open class BugReportActivity : AbsThemeActivity() {
})
}
inputPassword!!.setOnEditorActionListener { _, actionId, event ->
inputPassword!!.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEND) {
reportIssue()
return@setOnEditorActionListener true

View File

@ -4,7 +4,9 @@ import android.net.Uri
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import androidx.core.content.ContextCompat
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.loaders.SongLoader
import kotlinx.android.synthetic.main.activity_song_tag_editor.*
@ -19,11 +21,14 @@ class SongTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
private fun setupToolbar() {
appBarLayout.setBackgroundColor(ThemeStore.primaryColor(this))
toolbar.setBackgroundColor(ThemeStore.primaryColor(this))
toolbar.setNavigationOnClickListener { onBackPressed() }
toolbar.apply {
setBackgroundColor(ThemeStore.primaryColor(context))
navigationIcon = TintHelper.createTintedDrawable(ContextCompat.getDrawable(context, R.drawable.ic_keyboard_backspace_black_24dp), ThemeStore.textColorPrimary(context))
setNavigationOnClickListener { onBackPressed() }
setSupportActionBar(toolbar)
}
title = null
bannerTitle!!.setTextColor(ThemeStore.textColorPrimary(this))
setSupportActionBar(toolbar)
bannerTitle.setTextColor(ThemeStore.textColorPrimary(this))
}
override fun onCreate(savedInstanceState: Bundle?) {
@ -113,5 +118,4 @@ class SongTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
companion object {
val TAG: String = SongTagEditorActivity::class.java.simpleName
}
}

View File

@ -26,7 +26,7 @@ import code.name.monkey.retromusic.ui.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
import java.util.*
@ -131,6 +131,7 @@ open class AlbumAdapter(protected val activity: AppCompatActivity,
GlideApp.with(activity)
.asBitmapPalette()
.load(RetroGlideExtension.getSongModel(album.safeGetFirstSong()))
.transition(RetroGlideExtension.getDefaultTransition())
.songOptions(album.safeGetFirstSong())
.dontAnimate()

View File

@ -44,12 +44,15 @@ class HorizontalAlbumAdapter(activity: AppCompatActivity, dataSet: ArrayList<Alb
.dontAnimate()
.into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onColorReady(color: Int) {
setColors(color, holder)
if (usePalette)
setColors(color, holder)
else
setColors(albumArtistFooterColor, holder)
}
override fun onLoadFailed(errorDrawable: Drawable?) {
super.onLoadFailed(errorDrawable)
setColors(defaultFooterColor, holder)
setColors(albumArtistFooterColor, holder)
}
})
}

View File

@ -32,7 +32,8 @@ open class MiniPlayerFragment : AbsMusicServiceFragment(), MusicProgressViewUpda
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_mini_player, container, false)
}
override fun onClick(view: View) {
override fun onClick(view: View) {
when (view.id) {
R.id.actionPlayingQueue -> NavigationUtil.goToPlayingQueue(activity!!)
R.id.actionNext -> MusicPlayerRemote.playNextSong()
@ -49,13 +50,13 @@ open class MiniPlayerFragment : AbsMusicServiceFragment(), MusicProgressViewUpda
setUpMiniPlayer()
if (RetroUtil.isTablet()) {
actionNext!!.visibility = View.VISIBLE
actionPrevious!!.visibility = View.VISIBLE
actionPlayingQueue!!.visibility = View.VISIBLE
actionNext.visibility = View.VISIBLE
actionPrevious.visibility = View.VISIBLE
actionPlayingQueue.visibility = View.VISIBLE
} else {
actionNext!!.visibility = if (PreferenceUtil.getInstance().isExtraMiniExtraControls) View.VISIBLE else View.GONE
actionPlayingQueue!!.visibility = if (PreferenceUtil.getInstance().isExtraMiniExtraControls) View.GONE else View.VISIBLE
actionPrevious!!.visibility = if (PreferenceUtil.getInstance().isExtraMiniExtraControls) View.VISIBLE else View.GONE
actionNext.visibility = if (PreferenceUtil.getInstance().isExtraMiniExtraControls) View.VISIBLE else View.GONE
actionPlayingQueue.visibility = if (PreferenceUtil.getInstance().isExtraMiniExtraControls) View.GONE else View.VISIBLE
actionPrevious.visibility = if (PreferenceUtil.getInstance().isExtraMiniExtraControls) View.VISIBLE else View.GONE
}
actionPlayingQueue.setOnClickListener(this)
@ -65,7 +66,7 @@ open class MiniPlayerFragment : AbsMusicServiceFragment(), MusicProgressViewUpda
private fun setUpMiniPlayer() {
setUpPlayPauseButton()
progressBar!!.progressTintList = ColorStateList.valueOf(ThemeStore.accentColor(activity!!))
progressBar.progressTintList = ColorStateList.valueOf(ThemeStore.accentColor(activity!!))
}
private fun setUpPlayPauseButton() {
@ -128,14 +129,13 @@ open class MiniPlayerFragment : AbsMusicServiceFragment(), MusicProgressViewUpda
}
fun setColor(playerFragmentColor: Int) {
view!!.setBackgroundColor(playerFragmentColor)
}
class FlingPlayBackController(context: Context) : View.OnTouchListener {
internal var flingPlayBackController: GestureDetector
var flingPlayBackController: GestureDetector
init {
flingPlayBackController = GestureDetector(context,

View File

@ -1,6 +1,7 @@
package code.name.monkey.retromusic.ui.fragments
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.PorterDuff
import android.media.AudioManager
@ -10,7 +11,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.SeekBar
import androidx.fragment.app.Fragment
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.helper.MusicPlayerRemote
@ -33,7 +34,7 @@ class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolum
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setTintable(ATHUtil.resolveColor(context, R.attr.iconColor))
setTintable(ThemeStore.textColorSecondary(context!!))
volumeDown.setOnClickListener(this)
volumeUp.setOnClickListener(this)
}
@ -98,7 +99,13 @@ class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolum
}
private fun setProgressBarColor(newColor: Int) {
TintHelper.setTintAuto(volumeSeekBar, newColor, false)
val text = ColorStateList(arrayOf(intArrayOf(-android.R.attr.state_checked), intArrayOf(android.R.attr.state_checked)), intArrayOf(ThemeStore.textColorSecondary(context!!), ThemeStore.textColorPrimary(context!!)))
volumeSeekBar.progressTintList = text
volumeSeekBar.progressBackgroundTintList = text
//TintHelper.setTint(volumeSeekBar, newColor, false)
volumeDown.setColorFilter(newColor, PorterDuff.Mode.SRC_IN)
volumeUp.setColorFilter(newColor, PorterDuff.Mode.SRC_IN)
}

View File

@ -58,7 +58,7 @@ abstract class AbsLibraryPagerRecyclerViewFragment<A : RecyclerView.Adapter<*>,
get() = R.string.empty
private fun checkIsEmpty() {
empty.setText(emptyMessage)
emptyText.setText(emptyMessage)
empty.visibility = if (adapter!!.itemCount == 0) View.VISIBLE else View.GONE
}

View File

@ -71,6 +71,12 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
private ImageView userImage;
private CompositeDisposable disposable = new CompositeDisposable();
@Override
public void onDestroyView() {
super.onDestroyView();
disposable.dispose();
}
public static Fragment newInstance(int tab) {
Bundle args = new Bundle();
args.putInt(CURRENT_TAB_ID, tab);

View File

@ -17,6 +17,7 @@ import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.Constants.USER_BANNER
import code.name.monkey.retromusic.Constants.USER_PROFILE
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
import code.name.monkey.retromusic.loaders.SongLoader
@ -35,7 +36,6 @@ import code.name.monkey.retromusic.util.Compressor
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.RetroUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
@ -91,11 +91,11 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
private fun loadTimeImage(day: String) {
if (bannerImage != null) {
if (PreferenceUtil.getInstance().bannerImage.isEmpty()) {
/*Glide.with(activity).load(day)
.asBitmap()
GlideApp.with(activity!!)
.load(day)
.placeholder(R.drawable.material_design_default)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(bannerImage!!)*/
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(bannerImage!!)
} else {
disposable.add(Compressor(context!!)
.setQuality(100)
@ -176,7 +176,7 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
}
private fun setupToolbar() {
toolbar.navigationIcon = TintHelper.createTintedDrawable(ContextCompat.getDrawable(context!!, R.drawable.ic_search_white_24dp), ThemeStore.textColorPrimary(context!!))
toolbar.navigationIcon = TintHelper.createTintedDrawable(ContextCompat.getDrawable(context!!, R.drawable.ic_search_white_24dp), ThemeStore.textColorSecondary(context!!))
mainActivity.title = null
mainActivity.setSupportActionBar(toolbar)
toolbar.setBackgroundColor(Color.TRANSPARENT)
@ -188,7 +188,7 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
override fun onDestroyView() {
super.onDestroyView()
disposable.clear()
disposable.dispose()
homePresenter.unsubscribe()
}
@ -236,8 +236,7 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
override fun topAlbums(albums: ArrayList<Album>) {
topAlbumsContainer.visibility = View.VISIBLE
val artistAdapter = AlbumFullWithAdapter(mainActivity,
displayMetrics)
val artistAdapter = AlbumFullWithAdapter(mainActivity, displayMetrics)
artistAdapter.swapData(albums)
topAlbum.adapter = artistAdapter
}

View File

@ -8,6 +8,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import android.widget.SeekBar
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper

View File

@ -1,16 +1,21 @@
package code.name.monkey.retromusic.ui.fragments.player.normal
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewAnimationUtils
import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil
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.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment
@ -19,6 +24,8 @@ import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
import code.name.monkey.retromusic.views.DrawableGradient
import kotlinx.android.synthetic.main.fragment_player.*
import kotlinx.android.synthetic.main.fragment_player_playback_controls.*
import kotlinx.android.synthetic.main.media_button.*
class PlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
@ -59,7 +66,7 @@ class PlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
}
override fun toolbarIconColor(): Int {
return ATHUtil.resolveColor(context, R.attr.iconColor)
return ATHUtil.resolveColor(context, code.name.monkey.retromusic.R.attr.iconColor)
}
override fun onColorChanged(color: Int) {
@ -67,7 +74,7 @@ class PlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
lastColor = color
callbacks!!.onPaletteColorChanged()
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context, R.attr.iconColor), activity)
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context, code.name.monkey.retromusic.R.attr.iconColor), activity)
if (PreferenceUtil.getInstance().adaptiveColor) {
colorize(color)
@ -89,28 +96,28 @@ class PlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_player, container, false)
return inflater.inflate(code.name.monkey.retromusic.R.layout.fragment_player, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setUpSubFragments()
setUpPlayerToolbar()
snowfall.visibility= if (PreferenceUtil.getInstance().isSnowFall) View.VISIBLE else View.GONE
snowfall.visibility = if (PreferenceUtil.getInstance().isSnowFall) View.VISIBLE else View.GONE
}
private fun setUpSubFragments() {
playbackControlsFragment = childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as PlayerPlaybackControlsFragment
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
playbackControlsFragment = childFragmentManager.findFragmentById(code.name.monkey.retromusic.R.id.playbackControlsFragment) as PlayerPlaybackControlsFragment
val playerAlbumCoverFragment = childFragmentManager.findFragmentById(code.name.monkey.retromusic.R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
playerAlbumCoverFragment.setCallbacks(this)
}
private fun setUpPlayerToolbar() {
playerToolbar.inflateMenu(R.menu.menu_player)
playerToolbar.inflateMenu(code.name.monkey.retromusic.R.menu.menu_player)
playerToolbar.setNavigationOnClickListener { activity!!.onBackPressed() }
playerToolbar.setOnMenuItemClickListener(this)
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context, R.attr.iconColor), activity)
ToolbarContentTintHelper.colorizeToolbar(playerToolbar, ATHUtil.resolveColor(context, code.name.monkey.retromusic.R.attr.iconColor), activity)
}
override fun onServiceConnected() {
@ -133,3 +140,4 @@ class PlayerFragment : AbsPlayerFragment(), PlayerAlbumCoverFragment.Callbacks {
}
}
}

View File

@ -4,12 +4,12 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.annotation.NonNull;
import com.bumptech.glide.signature.ObjectKey;
import androidx.annotation.NonNull;
import code.name.monkey.retromusic.App;
public class ArtistSignatureUtil {
private static final String ARTIST_SIGNATURE_PREFS = "artist_signatures";

View File

@ -43,7 +43,7 @@ class CustomArtistImageUtil private constructor(context: Context) {
object : AsyncTask<Void, Void, Void>() {
@SuppressLint("ApplySharedPref")
override fun doInBackground(vararg params: Void): Void? {
val dir = File(App.context.getFilesDir(), FOLDER_NAME)
val dir = File(App.context.filesDir, FOLDER_NAME)
if (!dir.exists()) {
if (!dir.mkdirs()) { // create the folder
return null
@ -63,7 +63,7 @@ class CustomArtistImageUtil private constructor(context: Context) {
if (succesful) {
mPreferences.edit().putBoolean(getFileName(artist), true).commit()
ArtistSignatureUtil.getInstance().updateArtistSignature(artist.name)
App.context.getContentResolver().notifyChange(Uri.parse("content://media"), null) // trigger media store changed to force artist image reload
App.context.contentResolver.notifyChange(Uri.parse("content://media"), null) // trigger media store changed to force artist image reload
}
return null
}
@ -118,7 +118,7 @@ class CustomArtistImageUtil private constructor(context: Context) {
@JvmStatic
fun getFile(artist: Artist): File {
val dir = File(App.context.getFilesDir(), FOLDER_NAME)
val dir = File(App.context.filesDir, FOLDER_NAME)
return File(dir, getFileName(artist))
}
}

View File

@ -2,7 +2,6 @@ package code.name.monkey.retromusic.util;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.media.audiofx.AudioEffect;
import android.widget.Toast;
@ -12,8 +11,8 @@ import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.util.Pair;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.cast.ExpandedCastControlsActivity;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.model.Playlist;
@ -137,20 +136,7 @@ public class NavigationUtil {
openUrl(activity, RATE_ON_GOOGLE_PLAY);
}
public static void gotoExpandedController(Activity activity) {
ActivityCompat.startActivity(activity, new Intent(activity, ExpandedCastControlsActivity.class), null);
}
public static void gotoWhatNews(Activity activity) {
ActivityCompat.startActivity(activity, new Intent(activity, WhatsNewActivity.class), null);
}
public static void gotoNowPlayingActivity(Context context, @Nullable Pair... sharedElements) {
//ActivityCompat.startActivity(context, new Intent(context, NowPayingActivity.class), ActivityOptionsCompat.makeSceneTransitionAnimation((Activity) context, sharedElements).toBundle());
}
public static void gotoNowPlaying(Activity activity) {
//ActivityCompat.startActivity(activity, new Intent(activity, NowPayingActivity.class),null);
}
}

View File

@ -7,30 +7,24 @@ import android.content.SharedPreferences.Editor;
import android.content.res.TypedArray;
import android.preference.PreferenceManager;
import com.google.android.material.bottomnavigation.LabelVisibilityMode;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Objects;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.StyleRes;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.bottomnavigation.LabelVisibilityMode;
import java.io.File;
import java.util.Objects;
import code.name.monkey.retromusic.App;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.SortOrder;
import code.name.monkey.retromusic.model.CategoryInfo;
import code.name.monkey.retromusic.transform.CascadingPageTransformer;
import code.name.monkey.retromusic.transform.DepthTransformation;
import code.name.monkey.retromusic.transform.HingeTransformation;
import code.name.monkey.retromusic.transform.HorizontalFlipTransformation;
import code.name.monkey.retromusic.transform.NormalPageTransformer;
import code.name.monkey.retromusic.transform.StackPagerTransformer;
import code.name.monkey.retromusic.transform.StackTransformer;
import code.name.monkey.retromusic.transform.VerticalFlipTransformation;
import code.name.monkey.retromusic.ui.activities.MainActivity;
@ -71,7 +65,6 @@ public final class PreferenceUtil {
public static final String ALBUM_COVER_TRANSFORM = "album_cover_transform";
public static final String TAB_TEXT_MODE = "tab_text_mode";
private static final String GENRE_SORT_ORDER = "genre_sort_order";
private static final String LIBRARY_CATEGORIES = "library_categories";
private static final String LAST_PAGE = "last_start_page";
private static final String LAST_MUSIC_CHOOSER = "last_music_chooser";
private static final String DEFAULT_START_PAGE = "default_start_page";
@ -106,7 +99,7 @@ public final class PreferenceUtil {
private static final String LOCK_SCREEN = "lock_screen";
private static final String ALBUM_DETAIL_SONG_SORT_ORDER = "album_detail_song_sort_order";
private static final String ARTIST_DETAIL_SONG_SORT_ORDER = "artist_detail_song_sort_order";
private static final String LYRICS_OPTIONS = "lyrics_options";
private static final String LYRICS_OPTIONS = "lyrics_tab_position";
private static final String CHOOSE_EQUALIZER = "choose_equalizer";
private static final String TOGGLE_SHUFFLE = "toggle_shuffle";
private static final String SONG_GRID_STYLE = "song_grid_style";
@ -133,17 +126,17 @@ public final class PreferenceUtil {
@StyleRes
public static int getThemeResFromPrefValue(String themePrefValue) {
switch (themePrefValue) {
case "dark":
return R.style.Theme_RetroMusic;
case "light":
return R.style.Theme_RetroMusic_Light;
case "color":
return R.style.Theme_RetroMusic_Color;
case "acolor":
return R.style.Theme_RetroMusic_Black;
case "black":
return R.style.Theme_RetroMusic_Black;
case "light":
case "dark":
default:
return R.style.Theme_RetroMusic_Light;
return R.style.Theme_RetroMusic;
}
}
@ -170,8 +163,7 @@ public final class PreferenceUtil {
}
public final String getArtistAlbumSortOrder() {
return mPreferences
.getString(ARTIST_ALBUM_SORT_ORDER, SortOrder.ArtistAlbumSortOrder.ALBUM_YEAR);
return mPreferences.getString(ARTIST_ALBUM_SORT_ORDER, SortOrder.ArtistAlbumSortOrder.ALBUM_YEAR);
}
public final String getAlbumSortOrder() {
@ -221,51 +213,10 @@ public final class PreferenceUtil {
return mPreferences.getBoolean(TOGGLE_ADD_CONTROLS, false);
}
public boolean circularAlbumArt() {
return mPreferences.getBoolean(CIRCULAR_ALBUM_ART, false);
}
public boolean carouselEffect() {
return mPreferences.getBoolean(CAROUSEL_EFFECT, false);
}
public ArrayList<CategoryInfo> getLibraryCategoryInfos() {
String data = mPreferences.getString(LIBRARY_CATEGORIES, null);
if (data != null) {
Gson gson = new Gson();
Type collectionType = new TypeToken<ArrayList<CategoryInfo>>() {
}.getType();
try {
return gson.fromJson(data, collectionType);
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
}
return getDefaultLibraryCategoryInfos();
}
public void setLibraryCategoryInfos(ArrayList<CategoryInfo> categories) {
Gson gson = new Gson();
Type collectionType = new TypeToken<ArrayList<CategoryInfo>>() {
}.getType();
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putString(LIBRARY_CATEGORIES, gson.toJson(categories, collectionType));
editor.apply();
}
public ArrayList<CategoryInfo> getDefaultLibraryCategoryInfos() {
ArrayList<CategoryInfo> defaultCategoryInfos = new ArrayList<>(5);
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.SONGS, true));
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.ALBUMS, true));
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.ARTISTS, true));
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.GENRES, true));
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.PLAYLISTS, true));
return defaultCategoryInfos;
}
public boolean isRoundCorners() {
return mPreferences.getBoolean(ROUND_CORNERS, false);
}
@ -552,7 +503,7 @@ public final class PreferenceUtil {
}
public int getGeneralTheme() {
return getThemeResFromPrefValue(mPreferences.getString(GENERAL_THEME, "light"));
return getThemeResFromPrefValue(mPreferences.getString(GENERAL_THEME, "dark"));
}
public void setGeneralTheme(String theme) {
@ -611,10 +562,6 @@ public final class PreferenceUtil {
mPreferences.edit().putInt(TOGGLE_FULL_SCREEN, newValue).apply();
}
public String lyricsOptions() {
return mPreferences.getString(LYRICS_OPTIONS, "offline");
}
public void saveProfileImage(String profileImagePath) {
mPreferences.edit().putString(PROFILE_IMAGE_PATH, profileImagePath)
.apply();

View File

@ -1,24 +1,53 @@
package code.name.monkey.retromusic.util;
import android.animation.Animator;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import androidx.core.view.ViewCompat;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.PathInterpolator;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.core.view.ViewCompat;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import code.name.monkey.appthemehelper.util.ATHUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.retromusic.R;
public class ViewUtil {
public final static int RETRO_MUSIC_ANIM_TIME = 1000;
public static Animator createTextColorTransition(final TextView v, @ColorInt final int startColor, @ColorInt final int endColor) {
return createColorAnimator(v, "textColor", startColor, endColor);
}
private static Animator createColorAnimator(Object target, String propertyName, @ColorInt int startColor, @ColorInt int endColor) {
ObjectAnimator animator;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animator = ObjectAnimator.ofArgb(target, propertyName, startColor, endColor);
} else {
animator = ObjectAnimator.ofInt(target, propertyName, startColor, endColor);
animator.setEvaluator(new ArgbEvaluator());
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animator.setInterpolator(new PathInterpolator(0.4f, 0f, 1f, 1f));
}
animator.setDuration(RETRO_MUSIC_ANIM_TIME);
return animator;
}
public static void setStatusBarHeight(final Context context, View statusBar) {
ViewGroup.LayoutParams lp = statusBar.getLayoutParams();
lp.height = getStatusBarHeight(context);
@ -59,4 +88,9 @@ public class ViewUtil {
DisplayMetrics metrics = resources.getDisplayMetrics();
return dp * metrics.density;
}
@NotNull
public static Animator createBackgroundColorTransition(@Nullable View colorGradientBackground, int lastColor, int newColor) {
return null;
}
}

View File

@ -13,7 +13,6 @@ import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Looper;
import androidx.annotation.IntDef;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
@ -25,7 +24,12 @@ import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import code.name.monkey.retromusic.R;
import androidx.annotation.IntDef;
import androidx.core.content.res.ResourcesCompat;
import org.mozilla.universalchardet.UniversalDetector;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@ -38,7 +42,8 @@ import java.lang.annotation.RetentionPolicy;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import org.mozilla.universalchardet.UniversalDetector;
import code.name.monkey.retromusic.R;
/**
* Created by zhengken.me on 2016/11/27.
@ -588,7 +593,7 @@ public class LyricView extends View {
mTextPaint = new TextPaint();
mTextPaint.setDither(true);
mTextPaint.setAntiAlias(true);
Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/circular_std_book.otf");
Typeface typeface = ResourcesCompat.getFont(getContext(), R.font.font);
mTextPaint.setTypeface(typeface);
switch (mTextAlign) {

View File

@ -1,25 +0,0 @@
package code.name.monkey.retromusic.views;
import android.content.Context;
import android.util.AttributeSet;
import com.google.android.material.button.MaterialButton;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
public class MaterialButtonTextColor extends MaterialButton {
public MaterialButtonTextColor(Context context) {
this(context, null);
}
public MaterialButtonTextColor(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public MaterialButtonTextColor(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setTextColor(MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(ThemeStore.primaryColor(getContext()))));
}
}

View File

@ -0,0 +1,23 @@
package code.name.monkey.retromusic.views
import android.content.Context
import android.content.res.ColorStateList
import android.util.AttributeSet
import code.name.monkey.appthemehelper.ThemeStore
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.retromusic.R
import code.name.monkey.retromusic.util.RetroUtil
import com.google.android.material.button.MaterialButton
class MaterialButtonTextColor @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = -1) : MaterialButton(context, attrs, defStyleAttr) {
init {
setTextColor(MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(ThemeStore.primaryColor(getContext()))))
iconTint = ColorStateList.valueOf(ATHUtil.resolveColor(context, R.attr.iconColor))
iconPadding = RetroUtil.convertDpToPixel(16f, getContext()).toInt()
rippleColor = ColorStateList.valueOf(ColorUtil.withAlpha(ThemeStore.accentColor(context), 0.4f))
minHeight = RetroUtil.convertDpToPixel(52f, context).toInt()
}
}

View File

@ -4,9 +4,8 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import com.bumptech.glide.Glide;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.GlideApp;
/**
* @author Hemanth S (h4h13).
@ -33,10 +32,11 @@ public class NetworkImageView extends CircularImageView {
}
public void setImageUrl(Context context, String imageUrl) {
/*Glide.with(context).load(imageUrl).asBitmap()
GlideApp.with(context)
.load(imageUrl)
.error(R.drawable.ic_person_flat)
.placeholder(R.drawable.ic_person_flat)
.into(this);*/
.into(this);
}
private void init(Context context, AttributeSet attributeSet) {

View File

@ -0,0 +1,33 @@
package code.name.monkey.retromusic.views;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.WindowInsets;
import android.widget.FrameLayout;
public class StatusBarMarginFrameLayout extends FrameLayout {
public StatusBarMarginFrameLayout(Context context) {
super(context);
}
public StatusBarMarginFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public StatusBarMarginFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
lp.topMargin = insets.getSystemWindowInsetTop();
setLayoutParams(lp);
}
return super.onApplyWindowInsets(insets);
}
}

View File

@ -1,49 +0,0 @@
package code.name.monkey.retromusic.views;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import androidx.annotation.Nullable;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.mediarouter.app.MediaRouteActionProvider;
import androidx.mediarouter.app.MediaRouteButton;
import androidx.appcompat.view.ContextThemeWrapper;
import code.name.monkey.appthemehelper.ThemeStore;
public class ThemeableMediaRouteActionProvider extends MediaRouteActionProvider {
public ThemeableMediaRouteActionProvider(Context context) {
super(context);
}
@Override
public MediaRouteButton onCreateMediaRouteButton() {
MediaRouteButton button = super.onCreateMediaRouteButton();
colorWorkaroundForCastIcon(button);
return button;
}
@Nullable
@Override
public MediaRouteButton getMediaRouteButton() {
MediaRouteButton button = super.getMediaRouteButton();
colorWorkaroundForCastIcon(button);
return button;
}
private void colorWorkaroundForCastIcon(MediaRouteButton button) {
if (button == null) return;
Context castContext = new ContextThemeWrapper(getContext(), androidx.mediarouter.R.style.Theme_MediaRouter);
TypedArray a = castContext.obtainStyledAttributes(null,
androidx.mediarouter.R.styleable.MediaRouteButton, androidx.mediarouter.R.attr.mediaRouteButtonStyle, 0);
Drawable drawable = a.getDrawable(
androidx.mediarouter.R.styleable.MediaRouteButton_externalRouteEnabledDrawable);
a.recycle();
if (drawable != null) {
DrawableCompat.setTint(drawable, ThemeStore.textColorPrimary(getContext()));
drawable.setState(button.getDrawableState());
button.setRemoteIndicatorDrawable(drawable);
}
}
}

View File

@ -17,6 +17,6 @@ class TintIconColorToolbar : Toolbar {
override fun setNavigationIcon(icon: Drawable?) {
super.setNavigationIcon(icon)
icon?.setColorFilter(ThemeStore.accentColor(context), PorterDuff.Mode.SRC_IN)
icon?.setColorFilter(ThemeStore.textColorSecondary(context), PorterDuff.Mode.SRC_IN)
}
}

View File

@ -4,12 +4,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:pathData="M0,0h24v24H0V0z" />
<path
android:fillColor="@color/md_white_1000"
android:pathData="M11.99,2C6.47,2,2,6.48,2,12c0,5.52,4.47,10,9.99,10C17.52,22,22,17.52,22,12C22,6.48,17.52,2,11.99,2z M12,20 c-4.42,0-8-3.58-8-8c0-4.42,3.58-8,8-8s8,3.58,8,8C20,16.42,16.42,20,12,20z" />
<path
android:fillColor="@color/md_white_1000"
android:pathData="M11.78,7h-0.06C11.32,7,11,7.32,11,7.72v4.72c0,0.35,0.18,0.68,0.49,0.86l4.15,2.49c0.34,0.2,0.78,0.1,0.98-0.24v0 c0.21-0.34,0.1-0.79-0.25-0.99l-3.87-2.3V7.72C12.5,7.32,12.18,7,11.78,7z" />
android:pathData="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm0.5-13H11v6l5.25 3.15 0.75 -1.23-4.5-2.67z" />
</vector>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M18 20H4V6h9V4H4c-1.1 0-2 0.9-2 2v14c0 1.1 0.9 2 2 2h14c1.1 0 2-0.9 2-2v-9h-2v9zm-7.79-3.17l-1.96-2.36L5.5 18h11l-3.54-4.71zM20 4V1h-2v3h-3c0.01 0.01 0 2 0 2h3v2.99c0.01 0.01 2 0 2 0V6h3V4h-3z" />
</vector>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14.5c-2.49 0-4.5-2.01-4.5-4.5S9.51 7.5 12 7.5s4.5 2.01 4.5 4.5-2.01 4.5-4.5 4.5zm0-5.5c-0.55 0-1 0.45-1 1s0.45 1 1 1 1-0.45 1-1-0.45-1-1-1z" />
</vector>

View File

@ -5,7 +5,8 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14.5c-2.49 0-4.5-2.01-4.5-4.5S9.51 7.5 12 7.5s4.5 2.01 4.5 4.5-2.01 4.5-4.5 4.5zm0-5.5c-0.55 0-1 0.45-1 1s0.45 1 1 1 1-0.45 1-1-0.45-1-1-1z" />
android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-12.5c-2.49 0-4.5 2.01-4.5 4.5s2.01 4.5 4.5 4.5 4.5-2.01 4.5-4.5-2.01-4.5-4.5-4.5zm0 5.5c-0.55 0-1-0.45-1-1s0.45-1 1-1 1 0.45 1 1-0.45 1-1 1z" />
</vector>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M 2,5 C 1.45,5 1,5.45 1,6 l 0,12 c 0,0.55 0.45,1 1,1 l 12,0 c 0.55,0 1,-0.45 1,-1 L 15,6 C 15,5.45 14.55,5 14,5 L 2,5 Z m 7.390625,8.289062 c 0.2,-0.259999 0.589063,-0.26 0.789063,0 l 2.210937,2.900391 c 0.25,0.33 0.01961,0.800781 -0.400391,0.800781 l -7.960937,0 c -0.41,0.01 -0.648672,-0.470781 -0.388672,-0.800781 l 1.46875,-1.859375 c 0.2,-0.25 0.57125,-0.249766 0.78125,-0.0098 L 7.289062,16 9.390625,13.289062 Z" />
<path
android:fillColor="@color/md_white_1000"
android:pathData="M 22,5 c -0.55,0 -1,0.45 -1,1 l 0,12 c 0,0.55 0.45,1 1,1 0.55,0 1,-0.45 1,-1 L 23,6 C 23,5.45 22.55,5 22,5 Z" />
<path
android:fillColor="@color/md_white_1000"
android:pathData="M 18,5 c -0.55,0 -1,0.45 -1,1 l 0,12 c 0,0.55 0.45,1 1,1 0.55,0 1,-0.45 1,-1 L 19,6 C 19,5.45 18.55,5 18,5 Z" />
</vector>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="176dp"
android:height="176dp"
android:viewportWidth="176"
android:viewportHeight="176">
<group
android:pivotX="88"
android:pivotY="88"
android:scaleX="0.916"
android:scaleY="0.916"
android:translateX="-8"
android:translateY="-8">
<path
android:name="ic_app_shortcut_search_ic"
android:fillColor="#000"
android:pathData="M104.333 97.3333H100.647L99.34 96.0733C103.913 90.7533 106.667 83.8467 106.667 76.3333C106.667 59.58 93.0867 46 76.3333 46C59.58 46 46 59.58 46 76.3333C46 93.0867 59.58 106.667 76.3333 106.667C83.8467 106.667 90.7533 103.913 96.0733 99.34L97.3333 100.647V104.333L120.667 127.62L127.62 120.667L104.333 97.3333V97.3333ZM76.3333 97.3333C64.7133 97.3333 55.3333 87.9533 55.3333 76.3333C55.3333 64.7133 64.7133 55.3333 76.3333 55.3333C87.9533 55.3333 97.3333 64.7133 97.3333 76.3333C97.3333 87.9533 87.9533 97.3333 76.3333 97.3333Z" />
</group>
</vector>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M 10 4 C 7.79 4 6 5.79 6 8 C 6 10.21 7.79 12 10 12 C 12.21 12 14 10.21 14 8 C 14 5.79 12.21 4 10 4 z M 10 14 C 7.33 14 2 15.34 2 18 L 2 19 C 2 19.55 2.45 20 3 20 L 12.007812 20 A 5 5 0 0 1 11 17 A 5 5 0 0 1 11.867188 14.1875 C 11.186145 14.077427 10.532166 14 10 14 z" />
<path
android:fillColor="@color/md_white_1000"
android:pathData="M 19 8 A 2 2 0 0 0 17 10 L 17 14.173828 C 16.678959 14.059508 16.340787 14.000724 16 14 C 14.343146 14 13 15.343146 13 17 C 13 18.656854 14.343146 20 16 20 C 17.656854 20 19 18.656854 19 17 L 19 10 L 21 10 C 21.554 10 22 9.554 22 9 C 22 8.446 21.554 8 21 8 L 19 8 z" />
</vector>

View File

@ -4,11 +4,10 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M 10 4 C 7.79 4 6 5.79 6 8 C 6 10.21 7.79 12 10 12 C 12.21 12 14 10.21 14 8 C 14 5.79 12.21 4 10 4 z M 10 14 C 7.33 14 2 15.34 2 18 L 2 19 C 2 19.55 2.45 20 3 20 L 12.007812 20 A 5 5 0 0 1 11 17 A 5 5 0 0 1 11.867188 14.1875 C 11.186145 14.077427 10.532166 14 10 14 z" />
android:pathData="M 10 4 C 7.789999 4 6 5.79 6 8 C 6 10.21 7.789999 12 10 12 C 12.21 12 14 10.21 14 8 C 14 5.79 12.21 4 10 4 z M 10 6 C 11.1 6 12 6.9 12 8 C 12 9.1 11.1 10 10 10 C 8.899999 10 8 9.1 8 8 C 8 6.9 8.899999 6 10 6 z M 10 14 C 7.329999 14 2 15.34 2 18 L 2 20 L 13.007812 20 A 5 5 0 0 1 12.105469 18 L 4 18 C 4.23 17.28 7.309999 16 10 16 C 10.681642 16 11.388828 16.082448 12.068359 16.216797 A 5 5 0 0 1 12.771484 14.34375 C 11.755351 14.12326 10.766662 14 10 14 z" />
<path
android:fillColor="@color/md_white_1000"
android:pathData="M 19 8 A 2 2 0 0 0 17 10 L 17 14.173828 C 16.678959 14.059508 16.340787 14.000724 16 14 C 14.343146 14 13 15.343146 13 17 C 13 18.656854 14.343146 20 16 20 C 17.656854 20 19 18.656854 19 17 L 19 10 L 21 10 C 21.554 10 22 9.554 22 9 C 22 8.446 21.554 8 21 8 L 19 8 z" />
android:pathData="M 18 8 L 18 10 L 18 14.173828 A 3 3 0 0 0 17 14 A 3 3 0 0 0 14 17 A 3 3 0 0 0 17 20 A 3 3 0 0 0 20 17 L 20 10 L 22 10 L 22 8 L 20 8 L 18 8 z M 17 16 A 1 1 0 0 1 18 17 A 1 1 0 0 1 17 18 A 1 1 0 0 1 16 17 A 1 1 0 0 1 17 16 z" />
</vector>

View File

@ -6,5 +6,5 @@
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M12 5v8.55c-0.94-0.54-2.1-0.75-3.33-0.32-1.34 0.48 -2.37 1.67-2.61 3.07-0.46 2.74 1.86 5.08 4.59 4.65 1.96-0.31 3.35-2.11 3.35-4.1V7h2c1.1 0 2-0.9 2-2s-0.9-2-2-2h-2c-1.1 0-2 0.9-2 2z" />
android:pathData="M12 3v10.55c-0.59-0.34-1.27-0.55-2-0.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6zm-2 16c-1.1 0-2-0.9-2-2s0.9-2 2-2 2 0.9 2 2-0.9 2-2 2z" />
</vector>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M12 3v9.28c-0.47-0.17-0.97-0.28-1.5-0.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7z" />
</vector>

View File

@ -5,7 +5,8 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M19 8h-1.81c-0.45-0.78-1.07-1.45-1.82-1.96l0.93-0.93c0.39-0.39 0.39 -1.02 0-1.41-0.39-0.39-1.02-0.39-1.41 0l-1.47 1.47C12.96 5.06 12.49 5 12 5s-0.96 0.06 -1.41 0.17 L9.11 3.7c-0.39-0.39-1.02-0.39-1.41 0-0.39 0.39 -0.39 1.02 0 1.41l0.92 0.93 C7.88 6.55 7.26 7.22 6.81 8H5c-0.55 0-1 0.45-1 1s0.45 1 1 1h1.09c-0.05 0.33 -0.09 0.66 -0.09 1v1H5c-0.55 0-1 0.45-1 1s0.45 1 1 1h1v1c0 0.34 0.04 0.67 0.09 1H5c-0.55 0-1 0.45-1 1s0.45 1 1 1h1.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H19c0.55 0 1-0.45 1-1s-0.45-1-1-1h-1.09c0.05-0.33 0.09 -0.66 0.09 -1v-1h1c0.55 0 1-0.45 1-1s-0.45-1-1-1h-1v-1c0-0.34-0.04-0.67-0.09-1H19c0.55 0 1-0.45 1-1s-0.45-1-1-1zm-6 8h-2c-0.55 0-1-0.45-1-1s0.45-1 1-1h2c0.55 0 1 0.45 1 1s-0.45 1-1 1zm0-4h-2c-0.55 0-1-0.45-1-1s0.45-1 1-1h2c0.55 0 1 0.45 1 1s-0.45 1-1 1z" />
android:pathData="M20 8h-2.81c-0.45-0.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5s-0.96 0.06 -1.41 0.17 L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-0.05 0.33 -0.09 0.66 -0.09 1v1H4v2h2v1c0 0.34 0.04 0.67 0.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c0.05-0.33 0.09 -0.66 0.09 -1v-1h2v-2h-2v-1c0-0.34-0.04-0.67-0.09-1H20V8zm-4 4v3c0 0.22-0.03 0.47 -0.07 0.7 l-0.1 0.65 -0.37 0.65 c-0.72 1.24-2.04 2-3.46 2s-2.74-0.77-3.46-2l-0.37-0.64-0.1-0.65C8.03 15.48 8 15.23 8 15v-4c0-0.23 0.03 -0.48 0.07 -0.7l0.1-0.65 0.37 -0.65c0.3-0.52 0.72 -0.97 1.21-1.31l0.57-0.39 0.74 -0.18c0.31-0.08 0.63 -0.12 0.94 -0.12 0.32 0 0.63 0.04 0.95 0.12 l0.68 0.16 0.61 0.42 c0.5 0.34 0.91 0.78 1.21 1.31l0.38 0.65 0.1 0.65 c0.04 0.22 0.07 0.47 0.07 0.69 v1zm-6 2h4v2h-4zm0-4h4v2h-4z" />
</vector>

View File

@ -7,5 +7,5 @@
<path
android:fillColor="@color/md_white_1000"
android:pathData="M20 6h-2.18c0.11-0.31 0.18 -0.65 0.18 -1 0-1.66-1.34-3-3-3-1.05 0-1.96 0.54 -2.5 1.35l-0.5 0.67 -0.5-0.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 0.35 0.07 0.69 0.18 1H4c-1.11 0-1.99 0.89 -1.99 2L2 19c0 1.11 0.89 2 2 2h16c1.11 0 2-0.89 2-2V8c0-1.11-0.89-2-2-2zm-5-2c0.55 0 1 0.45 1 1s-0.45 1-1 1-1-0.45-1-1 0.45-1 1-1zM9 4c0.55 0 1 0.45 1 1s-0.45 1-1 1-1-0.45-1-1 0.45-1 1-1zm11 15H4v-2h16v2zm0-5H4V9c0-0.55 0.45 -1 1-1h4.08L7.6 10.02c-0.33 0.45 -0.23 1.08 0.22 1.4 0.44 0.32 1.07 0.22 1.39-0.22L12 7.4l2.79 3.8c0.32 0.44 0.95 0.54 1.39 0.22 0.45-0.32 0.55 -0.95 0.22 -1.4L14.92 8H19c0.55 0 1 0.45 1 1v5z" />
android:pathData="M20 6h-2.18c0.11-0.31 0.18 -0.65 0.18 -1 0-1.66-1.34-3-3-3-1.05 0-1.96 0.54 -2.5 1.35l-0.5 0.67 -0.5-0.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 0.35 0.07 0.69 0.18 1H4c-1.11 0-1.99 0.89 -1.99 2L2 19c0 1.11 0.89 2 2 2h16c1.11 0 2-0.89 2-2V8c0-1.11-0.89-2-2-2zm-5-2c0.55 0 1 0.45 1 1s-0.45 1-1 1-1-0.45-1-1 0.45-1 1-1zM9 4c0.55 0 1 0.45 1 1s-0.45 1-1 1-1-0.45-1-1 0.45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 10.83 8.62 12 12 7.4l3.38 4.6L17 10.83 14.92 8H20v6z" />
</vector>

View File

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M5,13h14v-2L5,11v2zM3,17h14v-2L3,15v2zM7,7v2h14L21,7L7,7z"/>
</vector>
android:pathData="M5 13h14v-2H5v2zm-2 4h14v-2H3v2zM7 7v2h14V7H7z" />
</vector>

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M18.3,5.71L18.3,5.71c-0.39,-0.39 -1.02,-0.39 -1.41,0L12,10.59L7.11,5.7c-0.39,-0.39 -1.02,-0.39 -1.41,0l0,0c-0.39,0.39 -0.39,1.02 0,1.41L10.59,12L5.7,16.89c-0.39,0.39 -0.39,1.02 0,1.41h0c0.39,0.39 1.02,0.39 1.41,0L12,13.41l4.89,4.89c0.39,0.39 1.02,0.39 1.41,0l0,0c0.39,-0.39 0.39,-1.02 0,-1.41L13.41,12l4.89,-4.89C18.68,6.73 18.68,6.09 18.3,5.71z"/>
</vector>
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" />
</vector>

View File

@ -5,7 +5,8 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M6 19c0 1.1 0.9 2 2 2h8c1.1 0 2-0.9 2-2V9c0-1.1-0.9-2-2-2H8c-1.1 0-2 0.9-2 2v10zM18 4h-2.5l-0.71-0.71c-0.18-0.18-0.44-0.29-0.7-0.29H9.91c-0.26 0-0.52 0.11 -0.7 0.29 L8.5 4H6c-0.55 0-1 0.45-1 1s0.45 1 1 1h12c0.55 0 1-0.45 1-1s-0.45-1-1-1z" />
android:pathData="M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1 0.9 2 2 2h8c1.1 0 2-0.9 2-2V7z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20,16h2v-2h-2v2zM20,7v5h2L22,7h-2zM10,4c-4.42,0 -8,3.58 -8,8s3.58,8 8,8 8,-3.58 8,-8 -3.58,-8 -8,-8zM10,14c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
</vector>

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M3,17.46v3.04c0,0.28 0.22,0.5 0.5,0.5h3.04c0.13,0 0.26,-0.05 0.35,-0.15L17.81,9.94l-3.75,-3.75L3.15,17.1c-0.1,0.1 -0.15,0.22 -0.15,0.36zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z" />
</vector>
android:pathData="M14.06 9.02l0.92 0.92 L5.92 19H5v-0.92l9.06-9.06M17.66 3c-0.25 0-0.51 0.1 -0.7 0.29 l-1.83 1.83 3.75 3.75 1.83-1.83c0.39-0.39 0.39 -1.02 0-1.41l-2.34-2.34c-0.2-0.2-0.45-0.29-0.71-0.29zm-3.6 3.19L3 17.25V21h3.75L17.81 9.94l-3.75-3.75z" />
</vector>

View File

@ -1,9 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M10,20h4L14,4h-4v16zM4,20h4v-8L4,12v8zM16,9v11h4L20,9h-4z"/>
</vector>
android:pathData="M10 20h4V4h-4v16zm-6 0h4v-8H4v8zM16 9v11h4V9h-4z" />
</vector>

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M19.66,3.99c-2.64,-1.8 -5.9,-0.96 -7.66,1.1c-1.76,-2.06 -5.02,-2.91 -7.66,-1.1C2.94,4.95 2.06,6.57 2,8.28c-0.14,3.88 3.3,6.99 8.55,11.76l0.1,0.09c0.76,0.69 1.93,0.69 2.69,-0.01l0.11,-0.1c5.25,-4.76 8.68,-7.87 8.55,-11.75C21.94,6.57 21.06,4.95 19.66,3.99zM12.1,18.55l-0.1,0.1l-0.1,-0.1C7.14,14.24 4,11.39 4,8.5C4,6.5 5.5,5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5C20,11.39 16.86,14.24 12.1,18.55z"/>
</vector>
<path
android:fillColor="@color/md_white_1000"
android:pathData="M16.5 3c-1.74 0-3.41 0.81 -4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-0.1 0.1 -0.1-0.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04 0.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z" />
</vector>

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/md_white_1000"
android:pathData="M13.35,20.13c-0.76,0.69 -1.93,0.69 -2.69,-0.01l-0.11,-0.1C5.3,15.27 1.87,12.16 2,8.28c0.06,-1.7 0.93,-3.33 2.34,-4.29c2.64,-1.8 5.9,-0.96 7.66,1.1c1.76,-2.06 5.02,-2.91 7.66,-1.1c1.41,0.96 2.28,2.59 2.34,4.29c0.14,3.88 -3.3,6.99 -8.55,11.76L13.35,20.13z"/>
</vector>
<path
android:fillColor="@color/md_white_1000"
android:pathData="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41 0.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" />
</vector>

Some files were not shown because too many files have changed in this diff Show More