Removed butter knife

This commit is contained in:
h4h13 2018-12-06 14:22:57 +05:30
parent d5f63b91ac
commit 63e3276098
194 changed files with 5984 additions and 7491 deletions

View file

@ -6,7 +6,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import butterknife.ButterKnife
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.loaders.PlaylistLoader
@ -24,9 +23,8 @@ class AddToPlaylistDialog : RoundedBottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val layout = inflater.inflate(R.layout.dialog_add_to_playlist, container, false)
ButterKnife.bind(this, layout)
return layout
return inflater.inflate(R.layout.dialog_add_to_playlist, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View file

@ -6,7 +6,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import butterknife.ButterKnife
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.MaterialUtil
import code.name.monkey.retromusic.R
@ -23,9 +22,8 @@ class CreatePlaylistDialog : RoundedBottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val layout = inflater.inflate(R.layout.dialog_playlist, container, false)
ButterKnife.bind(this, layout)
return layout
return inflater.inflate(R.layout.dialog_playlist, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View file

@ -5,7 +5,6 @@ import android.text.Html
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import butterknife.ButterKnife
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.model.Playlist
@ -19,9 +18,7 @@ class DeletePlaylistDialog : RoundedBottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val layout = inflater.inflate(R.layout.dialog_remove_from_playlist, container, false)
ButterKnife.bind(this, layout)
return layout
return inflater.inflate(R.layout.dialog_remove_from_playlist, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View file

@ -1,100 +0,0 @@
package code.name.monkey.retromusic.dialogs;
import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.google.android.material.button.MaterialButton;
import java.util.ArrayList;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.MaterialUtil;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.views.RoundedBottomSheetDialogFragment;
public class DeleteSongsDialog extends RoundedBottomSheetDialogFragment {
@BindView(R.id.action_delete)
MaterialButton actionDelete;
@BindView(R.id.title)
TextView title;
@BindView(R.id.action_cancel)
MaterialButton actionCancel;
@NonNull
public static DeleteSongsDialog create(Song song) {
ArrayList<Song> list = new ArrayList<>();
list.add(song);
return create(list);
}
@NonNull
public static DeleteSongsDialog create(ArrayList<Song> songs) {
DeleteSongsDialog dialog = new DeleteSongsDialog();
Bundle args = new Bundle();
args.putParcelableArrayList("songs", songs);
dialog.setArguments(args);
return dialog;
}
@OnClick({R.id.action_cancel, R.id.action_delete})
void actions(View view) {
//noinspection ConstantConditions
final ArrayList<Song> songs = getArguments().getParcelableArrayList("songs");
switch (view.getId()) {
case R.id.action_delete:
if (getActivity() == null) {
return;
}
if (songs != null) {
MusicUtil.deleteTracks(getActivity(), songs);
}
break;
default:
}
dismiss();
}
@SuppressWarnings("ConstantConditions")
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
title.setTextColor(ThemeStore.textColorPrimary(getContext()));
MaterialUtil.setTint(actionDelete, true);
MaterialUtil.setTint(actionCancel, false);
//noinspection unchecked,ConstantConditions
final ArrayList<Song> songs = getArguments().getParcelableArrayList("songs");
CharSequence content;
if (songs != null) {
if (songs.size() > 1) {
content = Html.fromHtml(getString(R.string.delete_x_songs, songs.size()));
} else {
content = Html.fromHtml(getString(R.string.delete_song_x, songs.get(0).getTitle()));
}
this.title.setText(content);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.dialog_delete, container, false);
ButterKnife.bind(this, layout);
return layout;
}
}

View file

@ -0,0 +1,69 @@
package code.name.monkey.retromusic.dialogs
import android.os.Bundle
import android.text.Html
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.MaterialUtil
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.views.RoundedBottomSheetDialogFragment
import kotlinx.android.synthetic.main.dialog_delete.*
import java.util.*
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)
//noinspection unchecked,ConstantConditions
val songs = arguments!!.getParcelableArrayList<Song>("songs")
val content: CharSequence
if (songs != null) {
content = if (songs.size > 1) {
Html.fromHtml(getString(R.string.delete_x_songs, songs.size))
} else {
Html.fromHtml(getString(R.string.delete_song_x, songs[0].title))
}
this.title.text = content
}
actionDelete.setOnClickListener {
if (songs != null) {
MusicUtil.deleteTracks(activity!!, songs)
}
dismiss()
}
actionCancel.setOnClickListener { dismiss() }
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.dialog_delete, container, false)
}
companion object {
fun create(song: Song): DeleteSongsDialog {
val list = ArrayList<Song>()
list.add(song)
return create(list)
}
fun create(songs: ArrayList<Song>): DeleteSongsDialog {
val dialog = DeleteSongsDialog()
val args = Bundle()
args.putParcelableArrayList("songs", songs)
dialog.arguments = args
return dialog
}
}
}

View file

@ -6,7 +6,6 @@ import android.text.Html
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import butterknife.ButterKnife
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.model.PlaylistSong
@ -19,9 +18,8 @@ import java.util.*
class RemoveFromPlaylistDialog : RoundedBottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val layout = inflater.inflate(R.layout.dialog_remove_from_playlist, container, false)
ButterKnife.bind(this, layout)
return layout
return inflater.inflate(R.layout.dialog_remove_from_playlist, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View file

@ -5,7 +5,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import butterknife.ButterKnife
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.MaterialUtil
import code.name.monkey.retromusic.R
@ -17,9 +16,8 @@ class RenamePlaylistDialog : RoundedBottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val layout = inflater.inflate(R.layout.dialog_playlist, container, false)
ButterKnife.bind(this, layout)
return layout
return inflater.inflate(R.layout.dialog_playlist, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View file

@ -1,193 +0,0 @@
package code.name.monkey.retromusic.dialogs;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.PorterDuff;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.button.MaterialButton;
import java.util.Locale;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.MaterialUtil;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.views.RoundedBottomSheetDialogFragment;
import static code.name.monkey.retromusic.Constants.ACTION_QUIT;
public class SleepTimerDialog extends RoundedBottomSheetDialogFragment {
@BindView(R.id.seek_arc)
SeekBar seekArc;
@BindView(R.id.timer_display)
TextView timerDisplay;
@BindView(R.id.action_set)
MaterialButton setButton;
@BindView(R.id.action_cancel)
MaterialButton cancelButton;
@BindView(R.id.title)
TextView title;
private int seekArcProgress;
private TimerUpdater timerUpdater;
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
timerUpdater.cancel();
}
@Override
public void onResume() {
super.onResume();
if (makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE) != null) {
timerUpdater.start();
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.dialog_sleep_timer, container, false);
ButterKnife.bind(this, layout);
return layout;
}
private void setProgressBarColor(int dark) {
LayerDrawable ld = (LayerDrawable) seekArc.getProgressDrawable();
ClipDrawable clipDrawable = (ClipDrawable) ld.findDrawableByLayerId(android.R.id.progress);
clipDrawable.setColorFilter(dark, PorterDuff.Mode.SRC_IN);
}
@SuppressWarnings("ConstantConditions")
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
MaterialUtil.setTint(setButton, true);
MaterialUtil.setTint(cancelButton, false);
title.setTextColor(ThemeStore.textColorPrimary(getContext()));
timerDisplay.setTextColor(ThemeStore.textColorSecondary(getContext()));
timerUpdater = new TimerUpdater();
seekArcProgress = PreferenceUtil.getInstance().getLastSleepTimerValue();
updateTimeDisplayTime();
seekArc.setProgress(seekArcProgress);
setProgressBarColor(ThemeStore.accentColor(getContext()));
seekArc.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (i < 1) {
seekArc.setProgress(1);
return;
}
seekArcProgress = i;
updateTimeDisplayTime();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
PreferenceUtil.getInstance().setLastSleepTimerValue(seekArcProgress);
}
});
}
@OnClick({R.id.action_cancel, R.id.action_set})
void set(View view) {
switch (view.getId()) {
case R.id.action_cancel:
if (getActivity() == null) {
return;
}
final PendingIntent previous = makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE);
if (previous != null) {
AlarmManager am = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
if (am != null) {
am.cancel(previous);
}
previous.cancel();
Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.sleep_timer_canceled), Toast.LENGTH_SHORT).show();
}
break;
case R.id.action_set:
if (getActivity() == null) {
return;
}
final int minutes = seekArcProgress;
PendingIntent pi = makeTimerPendingIntent(PendingIntent.FLAG_CANCEL_CURRENT);
final long nextSleepTimerElapsedTime = SystemClock.elapsedRealtime() + minutes * 60 * 1000;
PreferenceUtil.getInstance().setNextSleepTimerElapsedRealtime(nextSleepTimerElapsedTime);
AlarmManager am = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
if (am != null) {
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextSleepTimerElapsedTime, pi);
}
Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.sleep_timer_set, minutes), Toast.LENGTH_SHORT).show();
break;
}
dismiss();
}
private void updateTimeDisplayTime() {
timerDisplay.setText(String.format(Locale.getDefault(), "%d min", seekArcProgress));
}
private PendingIntent makeTimerPendingIntent(int flag) {
return PendingIntent.getService(getActivity(), 0, makeTimerIntent(), flag);
}
private Intent makeTimerIntent() {
return new Intent(getActivity(), MusicService.class)
.setAction( ACTION_QUIT);
}
private class TimerUpdater extends CountDownTimer {
TimerUpdater() {
//noinspection ConstantConditions
super(PreferenceUtil.getInstance().getNextSleepTimerElapsedRealTime() - SystemClock.elapsedRealtime(), 1000);
}
@Override
public void onTick(long millisUntilFinished) {
cancelButton.setText(String.format("%s (%s)", getString(R.string.cancel_current_timer), MusicUtil.getReadableDurationString(millisUntilFinished)));
//materialDialog.setActionButton(DialogAction.NEUTRAL, materialDialog.getContext().getString(R.string.cancel_current_timer) + " (" + MusicUtil.getReadableDurationString(millisUntilFinished) + ")");
}
@Override
public void onFinish() {
cancelButton.setText(null);
cancelButton.setVisibility(View.GONE);
//materialDialog.setActionButton(DialogAction.NEUTRAL, null);
}
}
}

View file

@ -0,0 +1,138 @@
package code.name.monkey.retromusic.dialogs
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.graphics.PorterDuff
import android.graphics.drawable.ClipDrawable
import android.graphics.drawable.LayerDrawable
import android.os.Bundle
import android.os.CountDownTimer
import android.os.SystemClock
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.SeekBar
import android.widget.Toast
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.MaterialUtil
import code.name.monkey.retromusic.Constants.ACTION_QUIT
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.views.RoundedBottomSheetDialogFragment
import kotlinx.android.synthetic.main.dialog_sleep_timer.*
import java.util.*
class SleepTimerDialog : RoundedBottomSheetDialogFragment() {
private var seekArcProgress: Int = 0
private lateinit var timerUpdater: TimerUpdater
override fun onDismiss(dialog: DialogInterface?) {
super.onDismiss(dialog)
timerUpdater.cancel()
}
override fun onResume() {
super.onResume()
if (makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE) != null) {
timerUpdater.start()
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.dialog_sleep_timer, container, false)
}
private fun setProgressBarColor(dark: Int) {
val ld = seekBar.progressDrawable as LayerDrawable
val clipDrawable = ld.findDrawableByLayerId(android.R.id.progress) as ClipDrawable
clipDrawable.setColorFilter(dark, PorterDuff.Mode.SRC_IN)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
MaterialUtil.setTint(actionSet, true)
MaterialUtil.setTint(actionCancel, false)
title.setTextColor(ThemeStore.textColorPrimary(context!!))
timerDisplay!!.setTextColor(ThemeStore.textColorSecondary(context!!))
timerUpdater = TimerUpdater()
seekArcProgress = PreferenceUtil.getInstance().lastSleepTimerValue
updateTimeDisplayTime()
seekBar.progress = seekArcProgress
setProgressBarColor(ThemeStore.accentColor(context!!))
seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
if (i < 1) {
seekBar.progress = 1
return
}
seekArcProgress = i
updateTimeDisplayTime()
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
PreferenceUtil.getInstance().lastSleepTimerValue = seekArcProgress
}
})
actionCancel.setOnClickListener {
val previous = makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE)
if (previous != null) {
val am = activity!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager
am.cancel(previous)
previous.cancel()
Toast.makeText(activity, activity!!.resources.getString(R.string.sleep_timer_canceled), Toast.LENGTH_SHORT).show()
}
dismiss()
}
actionSet.setOnClickListener {
val minutes = seekArcProgress
val pi = makeTimerPendingIntent(PendingIntent.FLAG_CANCEL_CURRENT)
val nextSleepTimerElapsedTime = SystemClock.elapsedRealtime() + minutes * 60 * 1000
PreferenceUtil.getInstance().setNextSleepTimerElapsedRealtime(nextSleepTimerElapsedTime)
val am = activity!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextSleepTimerElapsedTime, pi)
Toast.makeText(activity, activity!!.resources.getString(R.string.sleep_timer_set, minutes), Toast.LENGTH_SHORT).show()
dismiss()
}
}
private fun updateTimeDisplayTime() {
timerDisplay!!.text = String.format(Locale.getDefault(), "%d min", seekArcProgress)
}
private fun makeTimerPendingIntent(flag: Int): PendingIntent? {
return PendingIntent.getService(activity, 0, makeTimerIntent(), flag)
}
private fun makeTimerIntent(): Intent {
return Intent(activity, MusicService::class.java)
.setAction(ACTION_QUIT)
}
private inner class TimerUpdater internal constructor() : CountDownTimer(PreferenceUtil.getInstance().nextSleepTimerElapsedRealTime - SystemClock.elapsedRealtime(), 1000) {
override fun onTick(millisUntilFinished: Long) {
actionCancel.text = String.format("%s (%s)", getString(R.string.cancel_current_timer), MusicUtil.getReadableDurationString(millisUntilFinished))
}
override fun onFinish() {
actionCancel.text = null
actionCancel.visibility = View.GONE
}
}
}

View file

@ -1,124 +0,0 @@
package code.name.monkey.retromusic.dialogs;
import android.content.Context;
import android.os.Bundle;
import android.text.Html;
import android.text.Spanned;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.AudioHeader;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.tag.TagException;
import java.io.File;
import java.io.IOException;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import butterknife.BindViews;
import butterknife.ButterKnife;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.views.RoundedBottomSheetDialogFragment;
/**
* @author Karim Abou Zeid (kabouzeid), Aidan Follestad (afollestad)
*/
public class SongDetailDialog extends RoundedBottomSheetDialogFragment {
public static final String TAG = SongDetailDialog.class.getSimpleName();
@BindViews({R.id.title,
R.id.file_name,
R.id.file_path,
R.id.file_size,
R.id.file_format,
R.id.track_length,
R.id.bitrate,
R.id.sampling_rate})
List<TextView> textViews;
@NonNull
public static SongDetailDialog create(Song song) {
SongDetailDialog dialog = new SongDetailDialog();
Bundle args = new Bundle();
args.putParcelable("song", song);
dialog.setArguments(args);
return dialog;
}
private static Spanned makeTextWithTitle(@NonNull Context context, int titleResId, String text) {
return Html.fromHtml("<b>" + context.getResources().getString(titleResId) + ": " + "</b>" + text);
}
private static String getFileSizeString(long sizeInBytes) {
long fileSizeInKB = sizeInBytes / 1024;
long fileSizeInMB = fileSizeInKB / 1024;
return fileSizeInMB + " MB";
}
private void setTextColor(List<TextView> textColor) {
for (TextView textView : textColor) {
//noinspection ConstantConditions
textView.setTextColor(ThemeStore.textColorPrimary(getContext()));
}
}
@SuppressWarnings("ConstantConditions")
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View dialogView = inflater.inflate(R.layout.dialog_file_details, container, false);
ButterKnife.bind(this, dialogView);
Context context = getContext();
setTextColor(textViews);
textViews.get(1).setText(makeTextWithTitle(context, R.string.label_file_name, "-"));
textViews.get(2).setText(makeTextWithTitle(context, R.string.label_file_path, "-"));
textViews.get(3).setText(makeTextWithTitle(context, R.string.label_file_size, "-"));
textViews.get(4).setText(makeTextWithTitle(context, R.string.label_file_format, "-"));
textViews.get(5).setText(makeTextWithTitle(context, R.string.label_track_length, "-"));
textViews.get(6).setText(makeTextWithTitle(context, R.string.label_bit_rate, "-"));
textViews.get(7).setText(makeTextWithTitle(context, R.string.label_sampling_rate, "-"));
final Song song = getArguments().getParcelable("song");
if (song != null) {
final File songFile = new File(song.getData());
if (songFile.exists()) {
textViews.get(1).setText(makeTextWithTitle(context, R.string.label_file_name, songFile.getName()));
textViews.get(2).setText(makeTextWithTitle(context, R.string.label_file_path, songFile.getAbsolutePath()));
textViews.get(3).setText(makeTextWithTitle(context, R.string.label_file_size, getFileSizeString(songFile.length())));
try {
AudioFile audioFile = AudioFileIO.read(songFile);
AudioHeader audioHeader = audioFile.getAudioHeader();
textViews.get(4).setText(makeTextWithTitle(context, R.string.label_file_format, audioHeader.getFormat()));
textViews.get(5).setText(makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(audioHeader.getTrackLength() * 1000)));
textViews.get(6).setText(makeTextWithTitle(context, R.string.label_bit_rate, audioHeader.getBitRate() + " kb/s"));
textViews.get(7).setText(makeTextWithTitle(context, R.string.label_sampling_rate, audioHeader.getSampleRate() + " Hz"));
} catch (@NonNull CannotReadException | IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
Log.e(TAG, "error while reading the song file", e);
// fallback
textViews.get(5).setText(makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(song.getDuration())));
}
} else {
// fallback
textViews.get(1).setText(makeTextWithTitle(context, R.string.label_file_name, song.getTitle()));
textViews.get(5).setText(makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(song.getDuration())));
}
}
return dialogView;
}
}

View file

@ -0,0 +1,113 @@
package code.name.monkey.retromusic.dialogs
import android.content.Context
import android.os.Bundle
import android.text.Html
import android.text.Spanned
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.views.RoundedBottomSheetDialogFragment
import kotlinx.android.synthetic.main.dialog_file_details.*
import org.jaudiotagger.audio.AudioFileIO
import org.jaudiotagger.audio.exceptions.CannotReadException
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException
import org.jaudiotagger.tag.TagException
import java.io.File
import java.io.IOException
class SongDetailDialog : RoundedBottomSheetDialogFragment() {
private fun setTextColor(textColor: List<TextView>) {
for (textView in textColor) {
textView.setTextColor(ThemeStore.textColorPrimary(context!!))
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val dialogView = inflater.inflate(R.layout.dialog_file_details, container, false)
val context = context
fileName.text = makeTextWithTitle(context!!, R.string.label_file_name, "-")
filePath.text = makeTextWithTitle(context, R.string.label_file_path, "-")
fileSize.text = makeTextWithTitle(context, R.string.label_file_size, "-")
fileFormat.text = makeTextWithTitle(context, R.string.label_file_format, "-")
trackLength.text = makeTextWithTitle(context, R.string.label_track_length, "-")
bitrate.text = makeTextWithTitle(context, R.string.label_bit_rate, "-")
samplingRate.text = makeTextWithTitle(context, R.string.label_sampling_rate, "-")
val song = arguments!!.getParcelable<Song>("song")
if (song != null) {
val songFile = File(song.data)
if (songFile.exists()) {
fileName.text = makeTextWithTitle(context, R.string.label_file_name, songFile.name)
filePath.text = makeTextWithTitle(context, R.string.label_file_path, songFile.absolutePath)
fileSize.text = makeTextWithTitle(context, R.string.label_file_size, getFileSizeString(songFile.length()))
try {
val audioFile = AudioFileIO.read(songFile)
val audioHeader = audioFile.audioHeader
fileFormat.text = makeTextWithTitle(context, R.string.label_file_format, audioHeader.format)
trackLength.text = makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString((audioHeader.trackLength * 1000).toLong()))
bitrate.text = makeTextWithTitle(context, R.string.label_bit_rate, audioHeader.bitRate + " kb/s")
samplingRate.text = makeTextWithTitle(context, R.string.label_sampling_rate, audioHeader.sampleRate + " Hz")
} catch (e: CannotReadException) {
Log.e(TAG, "error while reading the song file", e)
// fallback
trackLength.text = makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(song.duration))
} catch (e: IOException) {
Log.e(TAG, "error while reading the song file", e)
trackLength.text = makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(song.duration))
} catch (e: TagException) {
Log.e(TAG, "error while reading the song file", e)
trackLength.text = makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(song.duration))
} catch (e: ReadOnlyFileException) {
Log.e(TAG, "error while reading the song file", e)
trackLength.text = makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(song.duration))
} catch (e: InvalidAudioFrameException) {
Log.e(TAG, "error while reading the song file", e)
trackLength.text = makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(song.duration))
}
} else {
// fallback
fileName.text = makeTextWithTitle(context, R.string.label_file_name, song.title)
trackLength.text = makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(song.duration))
}
}
return dialogView
}
companion object {
val TAG = SongDetailDialog::class.java.simpleName
fun create(song: Song): SongDetailDialog {
val dialog = SongDetailDialog()
val args = Bundle()
args.putParcelable("song", song)
dialog.arguments = args
return dialog
}
private fun makeTextWithTitle(context: Context, titleResId: Int, text: String?): Spanned {
return Html.fromHtml("<b>" + context.resources.getString(titleResId) + ": " + "</b>" + text)
}
private fun getFileSizeString(sizeInBytes: Long): String {
val fileSizeInKB = sizeInBytes / 1024
val fileSizeInMB = fileSizeInKB / 1024
return fileSizeInMB.toString() + " MB"
}
}
}

View file

@ -1,77 +0,0 @@
package code.name.monkey.retromusic.dialogs;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.views.RoundedBottomSheetDialogFragment;
public class SongShareDialog extends RoundedBottomSheetDialogFragment {
@BindView(R.id.option_1)
TextView audioFile;
@BindView(R.id.option_2)
TextView audioText;
@BindView(R.id.title)
TextView title;
@NonNull
public static SongShareDialog create(final Song song) {
final SongShareDialog dialog = new SongShareDialog();
final Bundle args = new Bundle();
args.putParcelable("song", song);
dialog.setArguments(args);
return dialog;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.dialog_file_share, container, false);
ButterKnife.bind(this, layout);
return layout;
}
@SuppressLint("StringFormatInvalid")
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final Song song = getArguments().getParcelable("song");
audioFile.setText(getString(R.string.currently_listening_to_x_by_x, song.getTitle(), song.getArtistName()));
audioFile.setTextColor(ThemeStore.textColorSecondary(getContext()));
audioText.setTextColor(ThemeStore.textColorSecondary(getContext()));
title.setTextColor(ThemeStore.textColorPrimary(getContext()));
}
@OnClick({R.id.option_2, R.id.option_1})
void onClick(View view) {
final Song song = getArguments().getParcelable("song");
final String currentlyListening = getString(R.string.currently_listening_to_x_by_x, song.getTitle(), song.getArtistName());
switch (view.getId()) {
case R.id.option_1:
startActivity(Intent.createChooser(
MusicUtil.createShareSongFileIntent(song, getContext()), null));
break;
case R.id.option_2:
getActivity().startActivity(Intent.createChooser(new Intent().setAction(Intent.ACTION_SEND)
.putExtra(Intent.EXTRA_TEXT, currentlyListening)
.setType("text/plain"), null));
break;
}
dismiss();
}
}

View file

@ -0,0 +1,56 @@
package code.name.monkey.retromusic.dialogs
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.views.RoundedBottomSheetDialogFragment
import kotlinx.android.synthetic.main.dialog_file_share.*
class SongShareDialog : RoundedBottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.dialog_file_share, container, false)
}
@SuppressLint("StringFormatInvalid")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val song = arguments!!.getParcelable<Song>("song")!!
audioFile.text = getString(R.string.currently_listening_to_x_by_x, song.title, song.artistName)
audioFile.setTextColor(ThemeStore.textColorSecondary(context!!))
audioText.setTextColor(ThemeStore.textColorSecondary(context!!))
title.setTextColor(ThemeStore.textColorPrimary(context!!))
audioFile.setOnClickListener {
MusicUtil.createShareSongFileIntent(song, context)
dismiss()
}
audioText.setOnClickListener {
val currentlyListening = getString(R.string.currently_listening_to_x_by_x, song.title, song.artistName)
activity!!.startActivity(Intent.createChooser(Intent().setAction(Intent.ACTION_SEND)
.putExtra(Intent.EXTRA_TEXT, currentlyListening)
.setType("text/plain"), null))
dismiss()
}
}
companion object {
fun create(song: Song): SongShareDialog {
val dialog = SongShareDialog()
val args = Bundle()
args.putParcelable("song", song)
dialog.arguments = args
return dialog
}
}
}

View file

@ -1,141 +0,0 @@
package code.name.monkey.retromusic.glide;
import android.content.Context;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import com.bumptech.glide.BitmapRequestBuilder;
import com.bumptech.glide.DrawableRequestBuilder;
import com.bumptech.glide.DrawableTypeRequest;
import com.bumptech.glide.Priority;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.target.Target;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.App;
import code.name.monkey.retromusic.glide.artistimage.ArtistImage;
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder;
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.util.ArtistSignatureUtil;
import code.name.monkey.retromusic.util.CustomArtistImageUtil;
public class ArtistGlideRequest {
private static final int DEFAULT_ANIMATION = android.R.anim.fade_in;
private static final DiskCacheStrategy DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.ALL;
private static final int DEFAULT_ERROR_IMAGE = R.drawable.default_artist_art;
private static DrawableTypeRequest createBaseRequest(RequestManager requestManager, Artist artist,
boolean noCustomImage, boolean forceDownload) {
boolean hasCustomImage = CustomArtistImageUtil.getInstance(App.Companion.getInstance())
.hasCustomArtistImage(artist);
if (noCustomImage || !hasCustomImage) {
return requestManager.load(new ArtistImage(artist.getName(), forceDownload));
} else {
return requestManager.load(CustomArtistImageUtil.getFile(artist));
}
}
private static Key createSignature(Artist artist) {
return ArtistSignatureUtil.getInstance(App.Companion.getInstance())
.getArtistSignature(artist.getName());
}
public static class Builder {
final RequestManager requestManager;
final Artist artist;
boolean noCustomImage;
boolean forceDownload;
private Builder(@NonNull RequestManager requestManager, Artist artist) {
this.requestManager = requestManager;
this.artist = artist;
}
public static Builder from(@NonNull RequestManager requestManager, Artist artist) {
return new Builder(requestManager, artist);
}
public PaletteBuilder generatePalette(Context context) {
return new PaletteBuilder(this, context);
}
public BitmapBuilder asBitmap() {
return new BitmapBuilder(this);
}
public Builder noCustomImage(boolean noCustomImage) {
this.noCustomImage = noCustomImage;
return this;
}
public Builder forceDownload(boolean forceDownload) {
this.forceDownload = forceDownload;
return this;
}
public DrawableRequestBuilder<GlideDrawable> build() {
//noinspection unchecked
return createBaseRequest(requestManager, artist, noCustomImage, forceDownload)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.priority(Priority.LOW)
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.signature(createSignature(artist));
}
}
public static class BitmapBuilder {
private final Builder builder;
BitmapBuilder(Builder builder) {
this.builder = builder;
}
public BitmapRequestBuilder<?, Bitmap> build() {
//noinspection unchecked
return createBaseRequest(builder.requestManager, builder.artist, builder.noCustomImage,
builder.forceDownload)
.asBitmap()
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.priority(Priority.LOW)
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.signature(createSignature(builder.artist));
}
}
public static class PaletteBuilder {
final Context context;
private final Builder builder;
PaletteBuilder(Builder builder, Context context) {
this.builder = builder;
this.context = context;
}
public BitmapRequestBuilder<?, BitmapPaletteWrapper> build() {
//noinspection unchecked
return createBaseRequest(builder.requestManager, builder.artist, builder.noCustomImage,
builder.forceDownload)
.asBitmap()
.transcode(new BitmapPaletteTranscoder(context), BitmapPaletteWrapper.class)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.priority(Priority.LOW)
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.signature(createSignature(builder.artist));
}
}
}

View file

@ -0,0 +1,112 @@
package code.name.monkey.retromusic.glide
import android.content.Context
import android.graphics.Bitmap
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.artistimage.ArtistImage
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.util.ArtistSignatureUtil
import code.name.monkey.retromusic.util.CustomArtistImageUtil
import com.bumptech.glide.*
import com.bumptech.glide.load.Key
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.target.Target
object ArtistGlideRequest {
private const val DEFAULT_ANIMATION = android.R.anim.fade_in
private val DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.ALL
private const val DEFAULT_ERROR_IMAGE = R.drawable.default_artist_art
private fun createBaseRequest(requestManager: RequestManager, artist: Artist, noCustomImage: Boolean, forceDownload: Boolean): DrawableTypeRequest<*> {
val hasCustomImage = CustomArtistImageUtil.getInstance(App.instance)
.hasCustomArtistImage(artist)
return if (noCustomImage || !hasCustomImage) {
requestManager.load(ArtistImage(artist.name, forceDownload))
} else {
requestManager.load(CustomArtistImageUtil.getFile(artist))
}
}
private fun createSignature(artist: Artist): Key {
return ArtistSignatureUtil.getInstance(App.instance)
.getArtistSignature(artist.name)
}
class Builder private constructor(internal val requestManager: RequestManager, internal val artist: Artist) {
internal var noCustomImage: Boolean = false
internal var forceDownload: Boolean = false
fun generatePalette(context: Context): PaletteBuilder {
return PaletteBuilder(this, context)
}
fun asBitmap(): BitmapBuilder {
return BitmapBuilder(this)
}
fun noCustomImage(noCustomImage: Boolean): Builder {
this.noCustomImage = noCustomImage
return this
}
fun forceDownload(forceDownload: Boolean): Builder {
this.forceDownload = forceDownload
return this
}
fun build(): DrawableRequestBuilder<out Any> {
return createBaseRequest(requestManager, artist, noCustomImage, forceDownload)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.priority(Priority.LOW)
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.signature(createSignature(artist))
}
companion object {
fun from(requestManager: RequestManager, artist: Artist): Builder {
return Builder(requestManager, artist)
}
}
}
class BitmapBuilder internal constructor(private val builder: Builder) {
fun build(): BitmapRequestBuilder<*, Bitmap> {
return createBaseRequest(builder.requestManager, builder.artist, builder.noCustomImage,
builder.forceDownload)
.asBitmap()
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.priority(Priority.LOW)
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.signature(createSignature(builder.artist))
}
}
class PaletteBuilder internal constructor(private val builder: Builder, internal val context: Context) {
fun build(): BitmapRequestBuilder<*, BitmapPaletteWrapper> {
return createBaseRequest(builder.requestManager, builder.artist, builder.noCustomImage,
builder.forceDownload)
.asBitmap()
.transcode(BitmapPaletteTranscoder(context), BitmapPaletteWrapper::class.java)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.priority(Priority.LOW)
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.signature(createSignature(builder.artist))
}
}
}

View file

@ -1,147 +0,0 @@
package code.name.monkey.retromusic.glide;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Build;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RSRuntimeException;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import androidx.annotation.FloatRange;
import androidx.annotation.NonNull;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import code.name.monkey.retromusic.helper.StackBlur;
import code.name.monkey.retromusic.BuildConfig;
import code.name.monkey.retromusic.util.ImageUtil;
public class BlurTransformation extends BitmapTransformation {
static final float DEFAULT_BLUR_RADIUS = 5f;
private Context context;
private float blurRadius;
private int sampling;
private BlurTransformation(Builder builder) {
super(builder.context);
init(builder);
}
private BlurTransformation(Builder builder, BitmapPool bitmapPool) {
super(bitmapPool);
init(builder);
}
private void init(Builder builder) {
this.context = builder.context;
this.blurRadius = builder.blurRadius;
this.sampling = builder.sampling;
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
int sampling;
if (this.sampling == 0) {
sampling = ImageUtil.calculateInSampleSize(toTransform.getWidth(), toTransform.getHeight(), 100);
} else {
sampling = this.sampling;
}
int width = toTransform.getWidth();
int height = toTransform.getHeight();
int scaledWidth = width / sampling;
int scaledHeight = height / sampling;
Bitmap out = pool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888);
if (out == null) {
out = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(out);
canvas.scale(1 / (float) sampling, 1 / (float) sampling);
Paint paint = new Paint();
paint.setFlags(Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(toTransform, 0, 0, paint);
if (Build.VERSION.SDK_INT >= 17) {
try {
final RenderScript rs = RenderScript.create(context.getApplicationContext());
final Allocation input = Allocation.createFromBitmap(rs, out, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
final Allocation output = Allocation.createTyped(rs, input.getType());
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setRadius(blurRadius);
script.setInput(input);
script.forEach(output);
output.copyTo(out);
rs.destroy();
return out;
} catch (RSRuntimeException e) {
// on some devices RenderScript.create() throws: android.support.v8.renderscript.RSRuntimeException: Error loading libRSSupport library
if (BuildConfig.DEBUG) e.printStackTrace();
}
}
return StackBlur.blur(out, blurRadius);
}
@Override
public String getId() {
return "BlurTransformation(radius=" + blurRadius + ", sampling=" + sampling + ")";
}
public static class Builder {
private Context context;
private BitmapPool bitmapPool;
private float blurRadius = DEFAULT_BLUR_RADIUS;
private int sampling;
public Builder(@NonNull Context context) {
this.context = context;
}
/**
* @param blurRadius The radius to use. Must be between 0 and 25. Default is 5.
* @return the same Builder
*/
public Builder blurRadius(@FloatRange(from = 0.0f, to = 25.0f) float blurRadius) {
this.blurRadius = blurRadius;
return this;
}
/**
* @param sampling The inSampleSize to use. Must be a power of 2, or 1 for no down sampling or 0 for auto detect sampling. Default is 0.
* @return the same Builder
*/
public Builder sampling(int sampling) {
this.sampling = sampling;
return this;
}
/**
* @param bitmapPool The BitmapPool to use.
* @return the same Builder
*/
public Builder bitmapPool(BitmapPool bitmapPool) {
this.bitmapPool = bitmapPool;
return this;
}
public BlurTransformation build() {
if (bitmapPool != null) {
return new BlurTransformation(this, bitmapPool);
}
return new BlurTransformation(this);
}
}
}

View file

@ -0,0 +1,142 @@
package code.name.monkey.retromusic.glide
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Paint
import android.os.Build
import android.renderscript.Allocation
import android.renderscript.Element
import android.renderscript.RSRuntimeException
import android.renderscript.RenderScript
import android.renderscript.ScriptIntrinsicBlur
import androidx.annotation.FloatRange
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import code.name.monkey.retromusic.helper.StackBlur
import code.name.monkey.retromusic.BuildConfig
import code.name.monkey.retromusic.util.ImageUtil
class BlurTransformation : BitmapTransformation {
private var context: Context? = null
private var blurRadius: Float = 0.toFloat()
private var sampling: Int = 0
private constructor(builder: Builder) : super(builder.context) {
init(builder)
}
private constructor(builder: Builder, bitmapPool: BitmapPool) : super(bitmapPool) {
init(builder)
}
private fun init(builder: Builder) {
this.context = builder.context
this.blurRadius = builder.blurRadius
this.sampling = builder.sampling
}
override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap? {
val sampling: Int
if (this.sampling == 0) {
sampling = ImageUtil.calculateInSampleSize(toTransform.width, toTransform.height, 100)
} else {
sampling = this.sampling
}
val width = toTransform.width
val height = toTransform.height
val scaledWidth = width / sampling
val scaledHeight = height / sampling
var out: Bitmap? = pool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888)
if (out == null) {
out = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888)
}
val canvas = Canvas(out!!)
canvas.scale(1 / sampling.toFloat(), 1 / sampling.toFloat())
val paint = Paint()
paint.flags = Paint.FILTER_BITMAP_FLAG
canvas.drawBitmap(toTransform, 0f, 0f, paint)
if (Build.VERSION.SDK_INT >= 17) {
try {
val rs = RenderScript.create(context!!.applicationContext)
val input = Allocation.createFromBitmap(rs, out, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT)
val output = Allocation.createTyped(rs, input.type)
val script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs))
script.setRadius(blurRadius)
script.setInput(input)
script.forEach(output)
output.copyTo(out)
rs.destroy()
return out
} catch (e: RSRuntimeException) {
// on some devices RenderScript.create() throws: android.support.v8.renderscript.RSRuntimeException: Error loading libRSSupport library
if (BuildConfig.DEBUG) e.printStackTrace()
}
}
return StackBlur.blur(out, blurRadius)
}
override fun getId(): String {
return "BlurTransformation(radius=$blurRadius, sampling=$sampling)"
}
class Builder(internal val context: Context) {
private var bitmapPool: BitmapPool? = null
internal var blurRadius = DEFAULT_BLUR_RADIUS
internal var sampling: Int = 0
/**
* @param blurRadius The radius to use. Must be between 0 and 25. Default is 5.
* @return the same Builder
*/
fun blurRadius(@FloatRange(from = 0.0, to = 25.0) blurRadius: Float): Builder {
this.blurRadius = blurRadius
return this
}
/**
* @param sampling The inSampleSize to use. Must be a power of 2, or 1 for no down sampling or 0 for auto detect sampling. Default is 0.
* @return the same Builder
*/
fun sampling(sampling: Int): Builder {
this.sampling = sampling
return this
}
/**
* @param bitmapPool The BitmapPool to use.
* @return the same Builder
*/
fun bitmapPool(bitmapPool: BitmapPool): Builder {
this.bitmapPool = bitmapPool
return this
}
fun build(): BlurTransformation {
return if (bitmapPool != null) {
BlurTransformation(this, bitmapPool!!)
} else BlurTransformation(this)
}
}
companion object {
internal const val DEFAULT_BLUR_RADIUS = 5f
}
}

View file

@ -1,27 +0,0 @@
package code.name.monkey.retromusic.glide;
import android.content.Context;
import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.module.GlideModule;
import code.name.monkey.retromusic.glide.artistimage.ArtistImage;
import code.name.monkey.retromusic.glide.artistimage.ArtistImageLoader;
import code.name.monkey.retromusic.glide.audiocover.AudioFileCover;
import code.name.monkey.retromusic.glide.audiocover.AudioFileCoverLoader;
import java.io.InputStream;
public class RetroMusicGlideModule implements GlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
}
@Override
public void registerComponents(Context context, Glide glide) {
glide.register(AudioFileCover.class, InputStream.class, new AudioFileCoverLoader.Factory());
glide.register(ArtistImage.class, InputStream.class, new ArtistImageLoader.Factory(context));
}
}

View file

@ -0,0 +1,25 @@
package code.name.monkey.retromusic.glide
import android.content.Context
import com.bumptech.glide.Glide
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.module.GlideModule
import code.name.monkey.retromusic.glide.artistimage.ArtistImage
import code.name.monkey.retromusic.glide.artistimage.ArtistImageLoader
import code.name.monkey.retromusic.glide.audiocover.AudioFileCover
import code.name.monkey.retromusic.glide.audiocover.AudioFileCoverLoader
import java.io.InputStream
class RetroMusicGlideModule : GlideModule {
override fun applyOptions(context: Context, builder: GlideBuilder) {
}
override fun registerComponents(context: Context, glide: Glide) {
glide.register(AudioFileCover::class.java, InputStream::class.java, AudioFileCoverLoader.Factory())
glide.register(ArtistImage::class.java, InputStream::class.java, ArtistImageLoader.Factory(context))
}
}

View file

@ -1,124 +0,0 @@
package code.name.monkey.retromusic.glide;
import android.content.Context;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.audiocover.AudioFileCover;
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder;
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import com.bumptech.glide.BitmapRequestBuilder;
import com.bumptech.glide.DrawableRequestBuilder;
import com.bumptech.glide.DrawableTypeRequest;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.signature.MediaStoreSignature;
public class SongGlideRequest {
static final DiskCacheStrategy DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.NONE;
static final int DEFAULT_ANIMATION = android.R.anim.fade_in;
static final int DEFAULT_ERROR_IMAGE = R.drawable.default_album_art;
static DrawableTypeRequest createBaseRequest(RequestManager requestManager, Song song,
boolean ignoreMediaStore) {
if (ignoreMediaStore) {
return requestManager.load(new AudioFileCover(song.getData()));
} else {
return requestManager.loadFromMediaStore(MusicUtil.getMediaStoreAlbumCoverUri(song.getAlbumId()));
}
}
static Key createSignature(Song song) {
return new MediaStoreSignature("", song.getDateModified(), 0);
}
public static class Builder {
final RequestManager requestManager;
final Song song;
boolean ignoreMediaStore;
private Builder(@NonNull RequestManager requestManager, Song song) {
this.requestManager = requestManager;
this.song = song;
}
public static Builder from(@NonNull RequestManager requestManager, Song song) {
return new Builder(requestManager, song);
}
public PaletteBuilder generatePalette(Context context) {
return new PaletteBuilder(this, context);
}
public BitmapBuilder asBitmap() {
return new BitmapBuilder(this);
}
public Builder checkIgnoreMediaStore(Context context) {
return ignoreMediaStore(PreferenceUtil.getInstance().ignoreMediaStoreArtwork());
}
Builder ignoreMediaStore(boolean ignoreMediaStore) {
this.ignoreMediaStore = ignoreMediaStore;
return this;
}
public DrawableRequestBuilder<GlideDrawable> build() {
//noinspection unchecked
return createBaseRequest(requestManager, song, ignoreMediaStore)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.signature(createSignature(song));
}
}
public static class BitmapBuilder {
private final Builder builder;
BitmapBuilder(Builder builder) {
this.builder = builder;
}
public BitmapRequestBuilder<?, Bitmap> build() {
//noinspection unchecked
return createBaseRequest(builder.requestManager, builder.song, builder.ignoreMediaStore)
.asBitmap()
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.signature(createSignature(builder.song));
}
}
public static class PaletteBuilder {
final Context context;
private final Builder builder;
PaletteBuilder(Builder builder, Context context) {
this.builder = builder;
this.context = context;
}
public BitmapRequestBuilder<?, BitmapPaletteWrapper> build() {
//noinspection unchecked
return createBaseRequest(builder.requestManager, builder.song, builder.ignoreMediaStore)
.asBitmap()
.transcode(new BitmapPaletteTranscoder(context), BitmapPaletteWrapper.class)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.signature(createSignature(builder.song));
}
}
}

View file

@ -0,0 +1,102 @@
package code.name.monkey.retromusic.glide
import android.content.Context
import android.graphics.Bitmap
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.audiocover.AudioFileCover
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import com.bumptech.glide.BitmapRequestBuilder
import com.bumptech.glide.DrawableRequestBuilder
import com.bumptech.glide.DrawableTypeRequest
import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.Key
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.signature.MediaStoreSignature
object SongGlideRequest {
internal val DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.NONE
internal const val DEFAULT_ANIMATION = android.R.anim.fade_in
internal const val DEFAULT_ERROR_IMAGE = R.drawable.default_album_art
internal fun createBaseRequest(requestManager: RequestManager, song: Song,
ignoreMediaStore: Boolean): DrawableTypeRequest<*> {
return if (ignoreMediaStore) {
requestManager.load(AudioFileCover(song.data!!))
} else {
requestManager.loadFromMediaStore(MusicUtil.getMediaStoreAlbumCoverUri(song.albumId))
}
}
internal fun createSignature(song: Song): Key {
return MediaStoreSignature("", song.dateModified, 0)
}
class Builder private constructor(internal val requestManager: RequestManager, internal val song: Song) {
internal var ignoreMediaStore: Boolean = false
fun generatePalette(context: Context): PaletteBuilder {
return PaletteBuilder(this, context)
}
fun asBitmap(): BitmapBuilder {
return BitmapBuilder(this)
}
fun checkIgnoreMediaStore(context: Context): Builder {
return ignoreMediaStore(PreferenceUtil.getInstance().ignoreMediaStoreArtwork())
}
fun ignoreMediaStore(ignoreMediaStore: Boolean): Builder {
this.ignoreMediaStore = ignoreMediaStore
return this
}
fun build(): DrawableRequestBuilder<out Any> {
return createBaseRequest(requestManager, song, ignoreMediaStore)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.signature(createSignature(song))
}
companion object {
fun from(requestManager: RequestManager, song: Song): Builder {
return Builder(requestManager, song)
}
}
}
class BitmapBuilder internal constructor(private val builder: Builder) {
fun build(): BitmapRequestBuilder<*, Bitmap> {
return createBaseRequest(builder.requestManager, builder.song, builder.ignoreMediaStore)
.asBitmap()
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.signature(createSignature(builder.song))
}
}
class PaletteBuilder internal constructor(private val builder: Builder, internal val context: Context) {
fun build(): BitmapRequestBuilder<*, BitmapPaletteWrapper> {
return createBaseRequest(builder.requestManager, builder.song, builder.ignoreMediaStore)
.asBitmap()
.transcode(BitmapPaletteTranscoder(context), BitmapPaletteWrapper::class.java)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.signature(createSignature(builder.song))
}
}
}

View file

@ -1,12 +0,0 @@
package code.name.monkey.retromusic.glide.artistimage;
public class ArtistImage {
public final String artistName;
public final boolean skipOkHttpCache;
public ArtistImage(String artistName, boolean skipOkHttpCache) {
this.artistName = artistName;
this.skipOkHttpCache = skipOkHttpCache;
}
}

View file

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

View file

@ -1,83 +0,0 @@
package code.name.monkey.retromusic.glide.artistimage;
import android.content.Context;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.load.model.ModelLoader;
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 java.io.IOException;
import java.io.InputStream;
import retrofit2.Response;
public class ArtistImageFetcher implements DataFetcher<InputStream> {
public static final String TAG = ArtistImageFetcher.class.getSimpleName();
private final LastFMRestClient lastFMRestClient;
private final ArtistImage model;
private final int width;
private final int height;
private Context context;
private ModelLoader<GlideUrl, InputStream> urlLoader;
private volatile boolean isCancelled;
private DataFetcher<InputStream> urlFetcher;
public ArtistImageFetcher(Context context, LastFMRestClient lastFMRestClient, ArtistImage model, ModelLoader<GlideUrl, InputStream> urlLoader, int width, int height) {
this.context = context;
this.lastFMRestClient = lastFMRestClient;
this.model = model;
this.urlLoader = urlLoader;
this.width = width;
this.height = height;
}
@Override
public String getId() {
// makes sure we never ever return null here
return String.valueOf(model.artistName);
}
@Override
public InputStream loadData(Priority priority) throws Exception {
if (!MusicUtil.isArtistNameUnknown(model.artistName) && RetroUtil.isAllowedToDownloadMetadata(context)) {
Response<LastFmArtist> response = lastFMRestClient.getApiService().getArtistInfo(model.artistName, null, model.skipOkHttpCache ? "no-cache" : null).execute();
if (!response.isSuccessful()) {
throw new IOException("Request failed with code: " + response.code());
}
LastFmArtist lastFmArtist = response.body();
if (isCancelled) return null;
GlideUrl url = new GlideUrl(LastFMUtil.getLargestArtistImageUrl(lastFmArtist.getArtist().getImage()));
urlFetcher = urlLoader.getResourceFetcher(url, width, height);
return urlFetcher.loadData(priority);
}
return null;
}
@Override
public void cleanup() {
if (urlFetcher != null) {
urlFetcher.cleanup();
}
}
@Override
public void cancel() {
isCancelled = true;
if (urlFetcher != null) {
urlFetcher.cancel();
}
}
}

View file

@ -0,0 +1,69 @@
package code.name.monkey.retromusic.glide.artistimage
import android.content.Context
import com.bumptech.glide.Priority
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.load.model.ModelLoader
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 java.io.IOException
import java.io.InputStream
import retrofit2.Response
class ArtistImageFetcher(private val context: Context, private val lastFMRestClient: LastFMRestClient, private val model: ArtistImage, private val urlLoader: ModelLoader<GlideUrl, InputStream>, private val width: Int, private val height: Int) : DataFetcher<InputStream> {
@Volatile
private var isCancelled: Boolean = false
private var urlFetcher: DataFetcher<InputStream>? = null
override fun getId(): String {
// makes sure we never ever return null here
return model.artistName
}
@Throws(Exception::class)
override fun loadData(priority: Priority): InputStream? {
if (!MusicUtil.isArtistNameUnknown(model.artistName) && RetroUtil.isAllowedToDownloadMetadata(context)) {
val response = lastFMRestClient.apiService.getArtistInfo(model.artistName, null, if (model.skipOkHttpCache) "no-cache" else null).execute()
if (!response.isSuccessful) {
throw IOException("Request failed with code: " + response.code())
}
val lastFmArtist = response.body()
if (isCancelled) return null
val url = GlideUrl(LastFMUtil.getLargestArtistImageUrl(lastFmArtist!!.artist.image))
urlFetcher = urlLoader.getResourceFetcher(url, width, height)
return urlFetcher!!.loadData(priority)
}
return null
}
override fun cleanup() {
if (urlFetcher != null) {
urlFetcher!!.cleanup()
}
}
override fun cancel() {
isCancelled = true
if (urlFetcher != null) {
urlFetcher!!.cancel()
}
}
companion object {
val TAG = ArtistImageFetcher::class.java.simpleName
}
}

View file

@ -1,68 +0,0 @@
package code.name.monkey.retromusic.glide.artistimage;
import android.content.Context;
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.GenericLoaderFactory;
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.stream.StreamModelLoader;
import code.name.monkey.retromusic.rest.LastFMRestClient;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
public class ArtistImageLoader implements StreamModelLoader<ArtistImage> {
// we need these very low values to make sure our artist image loading calls doesn't block the image loading queue
private static final int TIMEOUT = 500;
private Context context;
private LastFMRestClient lastFMClient;
private ModelLoader<GlideUrl, InputStream> urlLoader;
public ArtistImageLoader(Context context, LastFMRestClient lastFMRestClient, ModelLoader<GlideUrl, InputStream> urlLoader) {
this.context = context;
this.lastFMClient = lastFMRestClient;
this.urlLoader = urlLoader;
}
@Override
public DataFetcher<InputStream> getResourceFetcher(ArtistImage model, int width, int height) {
return new ArtistImageFetcher(context, lastFMClient, model, urlLoader, width, height);
}
public static class Factory implements ModelLoaderFactory<ArtistImage, InputStream> {
private LastFMRestClient lastFMClient;
private OkHttpUrlLoader.Factory okHttpFactory;
public Factory(Context context) {
okHttpFactory = new OkHttpUrlLoader.Factory(new OkHttpClient.Builder()
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.build());
lastFMClient = new LastFMRestClient(LastFMRestClient.createDefaultOkHttpClientBuilder(context)
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.build());
}
@Override
public ModelLoader<ArtistImage, InputStream> build(Context context, GenericLoaderFactory factories) {
return new ArtistImageLoader(context, lastFMClient, okHttpFactory.build(context, factories));
}
@Override
public void teardown() {
okHttpFactory.teardown();
}
}
}

View file

@ -0,0 +1,52 @@
package code.name.monkey.retromusic.glide.artistimage
import android.content.Context
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.GenericLoaderFactory
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.stream.StreamModelLoader
import code.name.monkey.retromusic.rest.LastFMRestClient
import java.io.InputStream
import java.util.concurrent.TimeUnit
import okhttp3.OkHttpClient
class ArtistImageLoader(private val context: Context, private val lastFMClient: LastFMRestClient, private val urlLoader: ModelLoader<GlideUrl, InputStream>) : StreamModelLoader<ArtistImage> {
override fun getResourceFetcher(model: ArtistImage, width: Int, height: Int): DataFetcher<InputStream> {
return ArtistImageFetcher(context, lastFMClient, model, urlLoader, width, height)
}
class Factory(context: Context) : ModelLoaderFactory<ArtistImage, InputStream> {
private val lastFMClient: LastFMRestClient = LastFMRestClient(LastFMRestClient.createDefaultOkHttpClientBuilder(context)
.connectTimeout(TIMEOUT.toLong(), TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT.toLong(), TimeUnit.MILLISECONDS)
.writeTimeout(TIMEOUT.toLong(), TimeUnit.MILLISECONDS)
.build())
private val okHttpFactory: OkHttpUrlLoader.Factory = OkHttpUrlLoader.Factory(OkHttpClient.Builder()
.connectTimeout(TIMEOUT.toLong(), TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT.toLong(), TimeUnit.MILLISECONDS)
.writeTimeout(TIMEOUT.toLong(), TimeUnit.MILLISECONDS)
.build())
override fun build(context: Context, factories: GenericLoaderFactory): ModelLoader<ArtistImage, InputStream> {
return ArtistImageLoader(context, lastFMClient, okHttpFactory.build(context, factories))
}
override fun teardown() {
okHttpFactory.teardown()
}
}
companion object {
// we need these very low values to make sure our artist image loading calls doesn't block the image loading queue
private const val TIMEOUT = 500
}
}

View file

@ -1,10 +0,0 @@
package code.name.monkey.retromusic.glide.audiocover;
public class AudioFileCover {
public final String filePath;
public AudioFileCover(String filePath) {
this.filePath = filePath;
}
}

View file

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

View file

@ -1,95 +0,0 @@
package code.name.monkey.retromusic.glide.audiocover;
import android.media.MediaMetadataRetriever;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.data.DataFetcher;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.audio.mp3.MP3File;
import org.jaudiotagger.tag.TagException;
import org.jaudiotagger.tag.images.Artwork;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class AudioFileCoverFetcher implements DataFetcher<InputStream> {
private static final String[] FALLBACKS = {"cover.jpg", "album.jpg", "folder.jpg", "cover.png", "album.png", "folder.png"};
private final AudioFileCover model;
private FileInputStream stream;
public AudioFileCoverFetcher(AudioFileCover model) {
this.model = model;
}
@Override
public String getId() {
// makes sure we never ever return null here
return String.valueOf(model.filePath);
}
@Override
public InputStream loadData(Priority priority) throws Exception {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(model.filePath);
byte[] picture = retriever.getEmbeddedPicture();
if (picture != null) {
return new ByteArrayInputStream(picture);
} else {
return fallback(model.filePath);
}
} finally {
retriever.release();
}
}
private InputStream fallback(String path) throws FileNotFoundException {
// Method 1: use embedded high resolution album art if there is any
try {
MP3File mp3File = new MP3File(path);
if (mp3File.hasID3v2Tag()) {
Artwork art = mp3File.getTag().getFirstArtwork();
if (art != null) {
byte[] imageData = art.getBinaryData();
return new ByteArrayInputStream(imageData);
}
}
// If there are any exceptions, we ignore them and continue to the other fallback method
} catch (ReadOnlyFileException | InvalidAudioFrameException | TagException | IOException ignored) {
}
// Method 2: look for album art in external files
File parent = new File(path).getParentFile();
for (String fallback : FALLBACKS) {
File cover = new File(parent, fallback);
if (cover.exists()) {
return stream = new FileInputStream(cover);
}
}
return null;
}
@Override
public void cleanup() {
// already cleaned up in loadData and ByteArrayInputStream will be GC'd
if (stream != null) {
try {
stream.close();
} catch (IOException ignore) {
// can't do much about it
}
}
}
@Override
public void cancel() {
// cannot cancel
}
}

View file

@ -0,0 +1,87 @@
package code.name.monkey.retromusic.glide.audiocover
import android.media.MediaMetadataRetriever
import com.bumptech.glide.Priority
import com.bumptech.glide.load.data.DataFetcher
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException
import org.jaudiotagger.audio.mp3.MP3File
import org.jaudiotagger.tag.TagException
import java.io.*
class AudioFileCoverFetcher(private val model: AudioFileCover) : DataFetcher<InputStream> {
private var stream: FileInputStream? = null
override fun getId(): String {
// makes sure we never ever return null here
return model.filePath
}
@Throws(Exception::class)
override fun loadData(priority: Priority): InputStream? {
val retriever = MediaMetadataRetriever()
try {
retriever.setDataSource(model.filePath)
val picture = retriever.embeddedPicture
return if (picture != null) {
ByteArrayInputStream(picture)
} else {
fallback(model.filePath)
}
} finally {
retriever.release()
}
}
@Throws(FileNotFoundException::class)
private fun fallback(path: String): InputStream? {
// Method 1: use embedded high resolution album art if there is any
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: ReadOnlyFileException) {
} catch (ignored: InvalidAudioFrameException) {
} catch (ignored: TagException) {
} catch (ignored: IOException) {
}
// 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,32 +0,0 @@
package code.name.monkey.retromusic.glide.audiocover;
import android.content.Context;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.GenericLoaderFactory;
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.model.ModelLoaderFactory;
import com.bumptech.glide.load.model.stream.StreamModelLoader;
import java.io.InputStream;
public class AudioFileCoverLoader implements StreamModelLoader<AudioFileCover> {
@Override
public DataFetcher<InputStream> getResourceFetcher(AudioFileCover model, int width, int height) {
return new AudioFileCoverFetcher(model);
}
public static class Factory implements ModelLoaderFactory<AudioFileCover, InputStream> {
@Override
public ModelLoader<AudioFileCover, InputStream> build(Context context, GenericLoaderFactory factories) {
return new AudioFileCoverLoader();
}
@Override
public void teardown() {
}
}
}

View file

@ -0,0 +1,28 @@
package code.name.monkey.retromusic.glide.audiocover
import android.content.Context
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.GenericLoaderFactory
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.stream.StreamModelLoader
import java.io.InputStream
class AudioFileCoverLoader : StreamModelLoader<AudioFileCover> {
override fun getResourceFetcher(model: AudioFileCover, width: Int, height: Int): DataFetcher<InputStream> {
return AudioFileCoverFetcher(model)
}
class Factory : ModelLoaderFactory<AudioFileCover, InputStream> {
override fun build(context: Context, factories: GenericLoaderFactory): ModelLoader<AudioFileCover, InputStream> {
return AudioFileCoverLoader()
}
override fun teardown() {}
}
}

View file

@ -1,34 +0,0 @@
package code.name.monkey.retromusic.glide.palette;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.util.Util;
public class BitmapPaletteResource implements Resource<BitmapPaletteWrapper> {
private final BitmapPaletteWrapper bitmapPaletteWrapper;
private final BitmapPool bitmapPool;
public BitmapPaletteResource(BitmapPaletteWrapper bitmapPaletteWrapper, BitmapPool bitmapPool) {
this.bitmapPaletteWrapper = bitmapPaletteWrapper;
this.bitmapPool = bitmapPool;
}
@Override
public BitmapPaletteWrapper get() {
return bitmapPaletteWrapper;
}
@Override
public int getSize() {
return Util.getBitmapByteSize(bitmapPaletteWrapper.getBitmap());
}
@Override
public void recycle() {
if (!bitmapPool.put(bitmapPaletteWrapper.getBitmap())) {
bitmapPaletteWrapper.getBitmap().recycle();
}
}
}

View file

@ -0,0 +1,23 @@
package code.name.monkey.retromusic.glide.palette
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
import com.bumptech.glide.util.Util
class BitmapPaletteResource(private val bitmapPaletteWrapper: BitmapPaletteWrapper, private val bitmapPool: BitmapPool) : Resource<BitmapPaletteWrapper> {
override fun get(): BitmapPaletteWrapper {
return bitmapPaletteWrapper
}
override fun getSize(): Int {
return Util.getBitmapByteSize(bitmapPaletteWrapper.bitmap)
}
override fun recycle() {
if (!bitmapPool.put(bitmapPaletteWrapper.bitmap)) {
bitmapPaletteWrapper.bitmap.recycle()
}
}
}

View file

@ -1,34 +0,0 @@
package code.name.monkey.retromusic.glide.palette;
import android.content.Context;
import android.graphics.Bitmap;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
import code.name.monkey.retromusic.util.RetroColorUtil;
public class BitmapPaletteTranscoder implements ResourceTranscoder<Bitmap, BitmapPaletteWrapper> {
private final BitmapPool bitmapPool;
public BitmapPaletteTranscoder(Context context) {
this(Glide.get(context).getBitmapPool());
}
public BitmapPaletteTranscoder(BitmapPool bitmapPool) {
this.bitmapPool = bitmapPool;
}
@Override
public Resource<BitmapPaletteWrapper> transcode(Resource<Bitmap> bitmapResource) {
Bitmap bitmap = bitmapResource.get();
BitmapPaletteWrapper bitmapPaletteWrapper = new BitmapPaletteWrapper(bitmap, RetroColorUtil.generatePalette(bitmap));
return new BitmapPaletteResource(bitmapPaletteWrapper, bitmapPool);
}
@Override
public String getId() {
return "BitmapPaletteTranscoder.code.name.monkey.retromusic.glide.palette";
}
}

View file

@ -0,0 +1,25 @@
package code.name.monkey.retromusic.glide.palette
import android.content.Context
import android.graphics.Bitmap
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder
import code.name.monkey.retromusic.util.RetroColorUtil
class BitmapPaletteTranscoder(private val bitmapPool: BitmapPool) : ResourceTranscoder<Bitmap, BitmapPaletteWrapper> {
constructor(context: Context) : this(Glide.get(context).bitmapPool) {}
override fun transcode(bitmapResource: Resource<Bitmap>): Resource<BitmapPaletteWrapper> {
val bitmap = bitmapResource.get()
val bitmapPaletteWrapper = BitmapPaletteWrapper(bitmap, RetroColorUtil.generatePalette(bitmap)!!)
return BitmapPaletteResource(bitmapPaletteWrapper, bitmapPool)
}
override fun getId(): String {
return "BitmapPaletteTranscoder.code.name.monkey.retromusic.glide.palette"
}
}

View file

@ -1,22 +0,0 @@
package code.name.monkey.retromusic.glide.palette;
import android.graphics.Bitmap;
import androidx.palette.graphics.Palette;
public class BitmapPaletteWrapper {
private final Bitmap mBitmap;
private final Palette mPalette;
public BitmapPaletteWrapper(Bitmap bitmap, Palette palette) {
mBitmap = bitmap;
mPalette = palette;
}
public Bitmap getBitmap() {
return mBitmap;
}
public Palette getPalette() {
return mPalette;
}
}

View file

@ -0,0 +1,6 @@
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

@ -1,12 +0,0 @@
package code.name.monkey.retromusic.mvp;
/**
* Created by hemanths on 09/08/17.
*/
public interface BasePresenter<T> {
void subscribe();
void unsubscribe();
}

View file

@ -0,0 +1,12 @@
package code.name.monkey.retromusic.mvp
/**
* Created by hemanths on 09/08/17.
*/
interface BasePresenter<T> {
fun subscribe()
fun unsubscribe()
}

View file

@ -1,15 +0,0 @@
package code.name.monkey.retromusic.mvp;
/**
* Created by hemanths on 09/08/17.
*/
public interface BaseView<T> {
void loading();
void showData(T list);
void showEmptyView();
void completed();
}

View file

@ -0,0 +1,15 @@
package code.name.monkey.retromusic.mvp
/**
* Created by hemanths on 09/08/17.
*/
interface BaseView<T> {
fun loading()
fun showData(list: T)
fun showEmptyView()
fun completed()
}

View file

@ -1,27 +0,0 @@
package code.name.monkey.retromusic.mvp;
import androidx.annotation.NonNull;
import code.name.monkey.retromusic.Injection;
import code.name.monkey.retromusic.providers.interfaces.Repository;
import code.name.monkey.retromusic.util.schedulers.BaseSchedulerProvider;
import io.reactivex.disposables.CompositeDisposable;
/**
* Created by hemanths on 16/08/17.
*/
public class Presenter {
@NonNull
protected Repository repository;
@NonNull
protected CompositeDisposable disposable;
@NonNull
protected BaseSchedulerProvider schedulerProvider;
public Presenter() {
this.repository = Injection.INSTANCE.provideRepository();
this.schedulerProvider = Injection.INSTANCE.provideSchedulerProvider();
this.disposable = new CompositeDisposable();
}
}

View file

@ -0,0 +1,16 @@
package code.name.monkey.retromusic.mvp
import code.name.monkey.retromusic.Injection
import code.name.monkey.retromusic.providers.interfaces.Repository
import code.name.monkey.retromusic.util.schedulers.BaseSchedulerProvider
import io.reactivex.disposables.CompositeDisposable
/**
* Created by hemanths on 16/08/17.
*/
open class Presenter {
protected var repository: Repository = Injection.provideRepository()
protected var disposable: CompositeDisposable = CompositeDisposable()
protected var schedulerProvider: BaseSchedulerProvider = Injection.provideSchedulerProvider()
}

View file

@ -1,19 +0,0 @@
package code.name.monkey.retromusic.mvp.contract;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.mvp.BasePresenter;
import code.name.monkey.retromusic.mvp.BaseView;
import java.util.ArrayList;
public interface AlbumContract {
interface AlbumView extends BaseView<ArrayList<Album>> {
}
interface Presenter extends BasePresenter<AlbumView> {
void loadAlbums();
}
}

View file

@ -0,0 +1,17 @@
package code.name.monkey.retromusic.mvp.contract
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
import java.util.ArrayList
interface AlbumContract {
interface AlbumView : BaseView<ArrayList<Album>>
interface Presenter : BasePresenter<AlbumView> {
fun loadAlbums()
}
}

View file

@ -1,18 +0,0 @@
package code.name.monkey.retromusic.mvp.contract;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.mvp.BasePresenter;
import code.name.monkey.retromusic.mvp.BaseView;
public interface AlbumDetailsContract {
interface AlbumDetailsView extends BaseView<Album> {
}
interface Presenter extends BasePresenter<AlbumDetailsView> {
void loadAlbumSongs(int albumId);
}
}

View file

@ -0,0 +1,16 @@
package code.name.monkey.retromusic.mvp.contract
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
interface AlbumDetailsContract {
interface AlbumDetailsView : BaseView<Album>
interface Presenter : BasePresenter<AlbumDetailsView> {
fun loadAlbumSongs(albumId: Int)
}
}

View file

@ -1,23 +0,0 @@
package code.name.monkey.retromusic.mvp.contract;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.mvp.BasePresenter;
import code.name.monkey.retromusic.mvp.BaseView;
import java.util.ArrayList;
/**
* Created by hemanths on 16/08/17.
*/
public interface ArtistContract {
interface ArtistView extends BaseView<ArrayList<Artist>> {
}
interface Presenter extends BasePresenter<ArtistView> {
void loadArtists();
}
}

View file

@ -0,0 +1,21 @@
package code.name.monkey.retromusic.mvp.contract
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
import java.util.ArrayList
/**
* Created by hemanths on 16/08/17.
*/
interface ArtistContract {
interface ArtistView : BaseView<ArrayList<Artist>>
interface Presenter : BasePresenter<ArtistView> {
fun loadArtists()
}
}

View file

@ -1,21 +0,0 @@
package code.name.monkey.retromusic.mvp.contract;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.mvp.BasePresenter;
import code.name.monkey.retromusic.mvp.BaseView;
/**
* Created by hemanths on 20/08/17.
*/
public interface ArtistDetailContract {
interface ArtistsDetailsView extends BaseView<Artist> {
}
interface Presenter extends BasePresenter<ArtistsDetailsView> {
void loadArtistById();
}
}

View file

@ -0,0 +1,19 @@
package code.name.monkey.retromusic.mvp.contract
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
/**
* Created by hemanths on 20/08/17.
*/
interface ArtistDetailContract {
interface ArtistsDetailsView : BaseView<Artist>
interface Presenter : BasePresenter<ArtistsDetailsView> {
fun loadArtistById()
}
}

View file

@ -1,21 +0,0 @@
package code.name.monkey.retromusic.mvp.contract;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.mvp.BasePresenter;
import code.name.monkey.retromusic.mvp.BaseView;
import java.util.ArrayList;
/**
* @author Hemanth S (h4h13).
*/
public interface GenreContract {
interface GenreView extends BaseView<ArrayList<Genre>> {
}
interface Presenter extends BasePresenter<GenreView> {
void loadGenre();
}
}

View file

@ -0,0 +1,19 @@
package code.name.monkey.retromusic.mvp.contract
import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
import java.util.ArrayList
/**
* @author Hemanth S (h4h13).
*/
interface GenreContract {
interface GenreView : BaseView<ArrayList<Genre>>
interface Presenter : BasePresenter<GenreView> {
fun loadGenre()
}
}

View file

@ -1,20 +0,0 @@
package code.name.monkey.retromusic.mvp.contract;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.mvp.BasePresenter;
import code.name.monkey.retromusic.mvp.BaseView;
import java.util.ArrayList;
/**
* @author Hemanth S (h4h13).
*/
public interface GenreDetailsContract {
interface GenreDetailsView extends BaseView<ArrayList<Song>> {
}
interface Presenter extends BasePresenter<GenreDetailsView> {
void loadGenre(int genreId);
}
}

View file

@ -0,0 +1,19 @@
package code.name.monkey.retromusic.mvp.contract
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
import java.util.ArrayList
/**
* @author Hemanth S (h4h13).
*/
interface GenreDetailsContract {
interface GenreDetailsView : BaseView<ArrayList<Song>>
interface Presenter : BasePresenter<GenreDetailsView> {
fun loadGenre(genreId: Int)
}
}

View file

@ -1,47 +0,0 @@
package code.name.monkey.retromusic.mvp.contract;
import java.util.ArrayList;
import code.name.monkey.retromusic.model.AbsCustomPlaylist;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.mvp.BasePresenter;
import code.name.monkey.retromusic.mvp.BaseView;
public interface HomeContract {
interface HomeView extends BaseView<ArrayList<Object>> {
void recentArtist(ArrayList<Artist> artists);
void recentAlbum(ArrayList<Album> albums);
void topArtists(ArrayList<Artist> artists);
void topAlbums(ArrayList<Album> albums);
void suggestions(ArrayList<Song> songs);
void playlists(ArrayList<Playlist> playlists);
void geners(ArrayList<Genre> songs);
}
interface HomePresenter extends BasePresenter<HomeView> {
void loadRecentAlbums();
void loadTopAlbums();
void loadRecentArtists();
void loadTopArtists();
void loadSuggestions();
void loadGenres();
}
}

View file

@ -0,0 +1,47 @@
package code.name.monkey.retromusic.mvp.contract
import java.util.ArrayList
import code.name.monkey.retromusic.model.AbsCustomPlaylist
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
interface HomeContract {
interface HomeView : BaseView<ArrayList<Any>> {
fun recentArtist(artists: ArrayList<Artist>)
fun recentAlbum(albums: ArrayList<Album>)
fun topArtists(artists: ArrayList<Artist>)
fun topAlbums(albums: ArrayList<Album>)
fun suggestions(songs: ArrayList<Song>)
fun playlists(playlists: ArrayList<Playlist>)
fun geners(songs: ArrayList<Genre>)
}
interface HomePresenter : BasePresenter<HomeView> {
fun loadRecentAlbums()
fun loadTopAlbums()
fun loadRecentArtists()
fun loadTopArtists()
fun loadSuggestions()
fun loadGenres()
}
}

View file

@ -1,21 +0,0 @@
package code.name.monkey.retromusic.mvp.contract;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.mvp.BasePresenter;
import code.name.monkey.retromusic.mvp.BaseView;
import java.util.ArrayList;
/**
* Created by hemanths on 19/08/17.
*/
public interface PlaylistContract {
interface PlaylistView extends BaseView<ArrayList<Playlist> > {
}
interface Presenter extends BasePresenter<PlaylistView> {
void loadPlaylists();
}
}

View file

@ -0,0 +1,19 @@
package code.name.monkey.retromusic.mvp.contract
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
import java.util.ArrayList
/**
* Created by hemanths on 19/08/17.
*/
interface PlaylistContract {
interface PlaylistView : BaseView<ArrayList<Playlist>>
interface Presenter : BasePresenter<PlaylistView> {
fun loadPlaylists()
}
}

View file

@ -1,23 +0,0 @@
package code.name.monkey.retromusic.mvp.contract;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.mvp.BasePresenter;
import code.name.monkey.retromusic.mvp.BaseView;
import java.util.ArrayList;
/**
* Created by hemanths on 20/08/17.
*/
public interface PlaylistSongsContract {
interface PlaylistSongsView extends BaseView<ArrayList<Song>> {
}
interface Presenter extends BasePresenter<PlaylistSongsView> {
void loadSongs(Playlist playlist);
}
}

View file

@ -0,0 +1,21 @@
package code.name.monkey.retromusic.mvp.contract
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
import java.util.ArrayList
/**
* Created by hemanths on 20/08/17.
*/
interface PlaylistSongsContract {
interface PlaylistSongsView : BaseView<ArrayList<Song>>
interface Presenter : BasePresenter<PlaylistSongsView> {
fun loadSongs(playlist: Playlist)
}
}

View file

@ -1,21 +0,0 @@
package code.name.monkey.retromusic.mvp.contract;
import code.name.monkey.retromusic.mvp.BasePresenter;
import code.name.monkey.retromusic.mvp.BaseView;
import java.util.ArrayList;
/**
* Created by hemanths on 20/08/17.
*/
public interface SearchContract {
interface SearchView extends BaseView<ArrayList<Object>> {
}
interface SearchPresenter extends BasePresenter<SearchView> {
void search(String query);
}
}

View file

@ -0,0 +1,19 @@
package code.name.monkey.retromusic.mvp.contract
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
import java.util.ArrayList
/**
* Created by hemanths on 20/08/17.
*/
interface SearchContract {
interface SearchView : BaseView<ArrayList<Any>>
interface SearchPresenter : BasePresenter<SearchView> {
fun search(query: String)
}
}

View file

@ -1,24 +0,0 @@
package code.name.monkey.retromusic.mvp.contract;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.mvp.BasePresenter;
import code.name.monkey.retromusic.mvp.BaseView;
import java.util.ArrayList;
/**
* Created by hemanths on 10/08/17.
*/
public interface SongContract {
interface SongView extends BaseView<ArrayList<Song>> {
}
interface Presenter extends BasePresenter<SongView> {
void loadSongs();
}
}

View file

@ -0,0 +1,22 @@
package code.name.monkey.retromusic.mvp.contract
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.BasePresenter
import code.name.monkey.retromusic.mvp.BaseView
import java.util.ArrayList
/**
* Created by hemanths on 10/08/17.
*/
interface SongContract {
interface SongView : BaseView<ArrayList<Song>>
interface Presenter : BasePresenter<SongView> {
fun loadSongs()
}
}

View file

@ -1,54 +0,0 @@
package code.name.monkey.retromusic.mvp.presenter;
import androidx.annotation.NonNull;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.mvp.Presenter;
import code.name.monkey.retromusic.mvp.contract.AlbumDetailsContract;
/**
* Created by hemanths on 20/08/17.
*/
public class AlbumDetailsPresenter extends Presenter implements AlbumDetailsContract.Presenter {
@NonNull
private final int albumId;
@NonNull
private AlbumDetailsContract.AlbumDetailsView view;
public AlbumDetailsPresenter(@NonNull AlbumDetailsContract.AlbumDetailsView view, int albumId) {
this.view = view;
this.albumId = albumId;
}
@Override
public void subscribe() {
loadAlbumSongs(albumId);
}
@Override
public void unsubscribe() {
disposable.clear();
}
@Override
public void loadAlbumSongs(int albumId) {
disposable.add(repository.getAlbum(albumId)
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(this::showAlbum,
throwable -> view.showEmptyView(),
() -> view.completed()));
}
private void showAlbum(Album album) {
if (album != null) {
view.showData(album);
} else {
view.showEmptyView();
}
}
}

View file

@ -0,0 +1,39 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.contract.AlbumDetailsContract
/**
* Created by hemanths on 20/08/17.
*/
class AlbumDetailsPresenter(private val view: AlbumDetailsContract.AlbumDetailsView, private val albumId: Int) : Presenter(), AlbumDetailsContract.Presenter {
override fun subscribe() {
loadAlbumSongs(albumId)
}
override fun unsubscribe() {
disposable.clear()
}
override fun loadAlbumSongs(albumId: Int) {
disposable.add(repository.getAlbum(albumId)
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe { view.loading() }
.subscribe({ this.showAlbum(it) },
{ view.showEmptyView() },
{ view.completed() }))
}
private fun showAlbum(album: Album?) {
if (album != null) {
view.showData(album)
} else {
view.showEmptyView()
}
}
}

View file

@ -1,49 +0,0 @@
package code.name.monkey.retromusic.mvp.presenter;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.mvp.Presenter;
import code.name.monkey.retromusic.mvp.contract.AlbumContract;
/**
* Created by hemanths on 12/08/17.
*/
public class AlbumPresenter extends Presenter implements AlbumContract.Presenter {
@NonNull
private AlbumContract.AlbumView view;
public AlbumPresenter(@NonNull AlbumContract.AlbumView view) {
this.view = view;
}
@Override
public void subscribe() {
loadAlbums();
}
@Override
public void unsubscribe() {
disposable.clear();
}
private void showList(@NonNull ArrayList<Album> albums) {
view.showData(albums);
}
@Override
public void loadAlbums() {
disposable.add(repository.getAllAlbums()
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(this::showList,
throwable -> view.showEmptyView(),
() -> view.completed()));
}
}

View file

@ -0,0 +1,36 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.contract.AlbumContract
import java.util.*
/**
* Created by hemanths on 12/08/17.
*/
class AlbumPresenter(private val view: AlbumContract.AlbumView) : Presenter(), AlbumContract.Presenter {
override fun subscribe() {
loadAlbums()
}
override fun unsubscribe() {
disposable.clear()
}
private fun showList(albums: ArrayList<Album>) {
view.showData(albums)
}
override fun loadAlbums() {
disposable.add(repository.allAlbums
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe { view.loading() }
.subscribe({ this.showList(it) },
{ view.showEmptyView() },
{ view.completed() }))
}
}

View file

@ -1,56 +0,0 @@
package code.name.monkey.retromusic.mvp.presenter;
import android.os.Bundle;
import androidx.annotation.NonNull;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.mvp.Presenter;
import code.name.monkey.retromusic.mvp.contract.ArtistDetailContract;
import code.name.monkey.retromusic.ui.activities.ArtistDetailActivity;
/**
* Created by hemanths on 20/08/17.
*/
public class ArtistDetailsPresenter extends Presenter implements ArtistDetailContract.Presenter {
@NonNull
private final ArtistDetailContract.ArtistsDetailsView view;
private Bundle bundle;
public ArtistDetailsPresenter(@NonNull ArtistDetailContract.ArtistsDetailsView view,
Bundle artistId) {
this.view = view;
this.bundle = artistId;
}
@Override
public void subscribe() {
loadArtistById();
}
@Override
public void unsubscribe() {
disposable.clear();
}
@Override
public void loadArtistById() {
disposable.add(repository.getArtistById(bundle.getInt(ArtistDetailActivity.EXTRA_ARTIST_ID))
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(this::showArtist,
throwable -> view.showEmptyView(),
view::completed));
}
private void showArtist(Artist album) {
if (album != null) {
view.showData(album);
} else {
view.showEmptyView();
}
}
}

View file

@ -0,0 +1,42 @@
package code.name.monkey.retromusic.mvp.presenter
import android.os.Bundle
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.contract.ArtistDetailContract
import code.name.monkey.retromusic.ui.activities.ArtistDetailActivity
/**
* Created by hemanths on 20/08/17.
*/
class ArtistDetailsPresenter(private val view: ArtistDetailContract.ArtistsDetailsView,
private val bundle: Bundle) : Presenter(), ArtistDetailContract.Presenter {
override fun subscribe() {
loadArtistById()
}
override fun unsubscribe() {
disposable.clear()
}
override fun loadArtistById() {
disposable.add(repository.getArtistById(bundle.getInt(ArtistDetailActivity.EXTRA_ARTIST_ID).toLong())
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe { view.loading() }
.subscribe({ this.showArtist(it) },
{ view.showEmptyView() },
{ view.completed() }))
}
private fun showArtist(album: Artist?) {
if (album != null) {
view.showData(album)
} else {
view.showEmptyView()
}
}
}

View file

@ -1,47 +0,0 @@
package code.name.monkey.retromusic.mvp.presenter;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.mvp.Presenter;
import code.name.monkey.retromusic.mvp.contract.ArtistContract;
public class ArtistPresenter extends Presenter implements ArtistContract.Presenter {
@NonNull
private ArtistContract.ArtistView mView;
public ArtistPresenter(@NonNull ArtistContract.ArtistView view) {
mView = view;
}
@Override
public void subscribe() {
loadArtists();
}
@Override
public void unsubscribe() {
disposable.clear();
}
private void showList(@NonNull ArrayList<Artist> songs) {
if (songs.isEmpty()) {
mView.showEmptyView();
} else {
mView.showData(songs);
}
}
@Override
public void loadArtists() {
disposable.add(repository.getAllArtists()
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe(disposable1 -> mView.loading())
.subscribe(this::showList,
throwable -> mView.showEmptyView(),
() -> mView.completed()));
}
}

View file

@ -0,0 +1,35 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.contract.ArtistContract
import java.util.*
class ArtistPresenter(private val mView: ArtistContract.ArtistView) : Presenter(), ArtistContract.Presenter {
override fun subscribe() {
loadArtists()
}
override fun unsubscribe() {
disposable.clear()
}
private fun showList(songs: ArrayList<Artist>) {
if (songs.isEmpty()) {
mView.showEmptyView()
} else {
mView.showData(songs)
}
}
override fun loadArtists() {
disposable.add(repository.allArtists
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe { mView.loading() }
.subscribe({ this.showList(it) },
{ mView.showEmptyView() },
{ mView.completed() }))
}
}

View file

@ -1,56 +0,0 @@
package code.name.monkey.retromusic.mvp.presenter;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.mvp.Presenter;
import code.name.monkey.retromusic.mvp.contract.GenreDetailsContract;
/**
* Created by hemanths on 20/08/17.
*/
public class GenreDetailsPresenter extends Presenter
implements GenreDetailsContract.Presenter {
private final int genreId;
@NonNull
private GenreDetailsContract.GenreDetailsView view;
public GenreDetailsPresenter(@NonNull GenreDetailsContract.GenreDetailsView view,
int genreId) {
this.view = view;
this.genreId = genreId;
}
@Override
public void subscribe() {
loadGenre(genreId);
}
@Override
public void unsubscribe() {
disposable.clear();
}
@Override
public void loadGenre(int genreId) {
disposable.add(repository.getGenre(genreId)
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(this::showGenre,
throwable -> view.showEmptyView(),
() -> view.completed()));
}
private void showGenre(ArrayList<Song> songs) {
if (songs != null) {
view.showData(songs);
} else {
view.showEmptyView();
}
}
}

View file

@ -0,0 +1,41 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.contract.GenreDetailsContract
import java.util.*
/**
* Created by hemanths on 20/08/17.
*/
class GenreDetailsPresenter(private val view: GenreDetailsContract.GenreDetailsView,
private val genreId: Int) : Presenter(), GenreDetailsContract.Presenter {
override fun subscribe() {
loadGenre(genreId)
}
override fun unsubscribe() {
disposable.clear()
}
override fun loadGenre(genreId: Int) {
disposable.add(repository.getGenre(genreId)
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe { view.loading() }
.subscribe({ this.showGenre(it) },
{ view.showEmptyView() },
{ view.completed() }))
}
private fun showGenre(songs: ArrayList<Song>?) {
if (songs != null) {
view.showData(songs)
} else {
view.showEmptyView()
}
}
}

View file

@ -1,53 +0,0 @@
package code.name.monkey.retromusic.mvp.presenter;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.mvp.Presenter;
import code.name.monkey.retromusic.mvp.contract.GenreContract;
/**
* @author Hemanth S (h4h13).
*/
public class GenrePresenter extends Presenter
implements GenreContract.Presenter {
@NonNull
private GenreContract.GenreView view;
public GenrePresenter(
@NonNull GenreContract.GenreView view) {
this.view = view;
}
@Override
public void subscribe() {
loadGenre();
}
@Override
public void unsubscribe() {
disposable.clear();
}
@Override
public void loadGenre() {
disposable.add(repository.getAllGenres()
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(this::showList,
throwable -> view.showEmptyView(),
() -> view.completed()));
}
private void showList(@NonNull ArrayList<Genre> genres) {
if (genres.isEmpty()) {
view.showEmptyView();
} else {
view.showData(genres);
}
}
}

View file

@ -0,0 +1,40 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.contract.GenreContract
import java.util.*
/**
* @author Hemanth S (h4h13).
*/
class GenrePresenter(
private val view: GenreContract.GenreView) : Presenter(), GenreContract.Presenter {
override fun subscribe() {
loadGenre()
}
override fun unsubscribe() {
disposable.clear()
}
override fun loadGenre() {
disposable.add(repository.allGenres
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe { view.loading() }
.subscribe({ this.showList(it) },
{ view.showEmptyView() },
{ view.completed() }))
}
private fun showList(genres: ArrayList<Genre>) {
if (genres.isEmpty()) {
view.showEmptyView()
} else {
view.showData(genres)
}
}
}

View file

@ -1,126 +0,0 @@
package code.name.monkey.retromusic.mvp.presenter;
import androidx.annotation.NonNull;
import code.name.monkey.retromusic.mvp.Presenter;
import code.name.monkey.retromusic.mvp.contract.HomeContract;
import code.name.monkey.retromusic.util.PreferenceUtil;
public class HomePresenter extends Presenter implements HomeContract.HomePresenter {
@NonNull
private HomeContract.HomeView view;
public HomePresenter(@NonNull HomeContract.HomeView view) {
this.view = view;
}
@Override
public void subscribe() {
loadRecentAlbums();
loadRecentArtists();
loadTopAlbums();
loadTopArtists();
loadSuggestions();
if (PreferenceUtil.getInstance().isGenreShown()) loadGenres();
}
@Override
public void unsubscribe() {
disposable.clear();
}
public void loadPlaylists() {
disposable.add(repository.getAllPlaylists()
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.subscribe(playlist -> {
if (!playlist.isEmpty()) {
view.playlists(playlist);
}
},
throwable -> view.showEmptyView(), () -> view.completed()));
}
@Override
public void loadRecentAlbums() {
disposable.add(repository.getRecentAlbums()
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(artists -> {
if (!artists.isEmpty()) {
view.recentAlbum(artists);
}
},
throwable -> view.showEmptyView(), () -> view.completed()));
}
@Override
public void loadTopAlbums() {
disposable.add(repository.getTopAlbums()
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(artists -> {
if (!artists.isEmpty()) {
view.topAlbums(artists);
}
},
throwable -> view.showEmptyView(), () -> view.completed()));
}
@Override
public void loadRecentArtists() {
disposable.add(repository.getRecentArtists()
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(artists -> {
if (!artists.isEmpty()) {
view.recentArtist(artists);
}
},
throwable -> view.showEmptyView(), () -> view.completed()));
}
@Override
public void loadTopArtists() {
disposable.add(repository.getTopArtists()
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(artists -> {
if (!artists.isEmpty()) {
view.topArtists(artists);
}
},
throwable -> view.showEmptyView(), () -> view.completed()));
}
@Override
public void loadSuggestions() {
disposable.add(repository.getSuggestionSongs()
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(songs -> view.suggestions(songs), throwable -> view.showEmptyView(), () -> view.completed()));
}
@Override
public void loadGenres() {
disposable.add(repository.getAllGenres()
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(genres -> {
if (!genres.isEmpty()) {
view.geners(genres);
}
},
throwable -> view.showEmptyView(), () -> view.completed()));
}
}

View file

@ -0,0 +1,105 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.contract.HomeContract
import code.name.monkey.retromusic.util.PreferenceUtil
class HomePresenter(private val view: HomeContract.HomeView) : Presenter(), HomeContract.HomePresenter {
override fun subscribe() {
loadRecentAlbums()
loadRecentArtists()
loadTopAlbums()
loadTopArtists()
loadSuggestions()
if (PreferenceUtil.getInstance().isGenreShown) loadGenres()
}
override fun unsubscribe() {
disposable.clear()
}
fun loadPlaylists() {
disposable.add(repository.allPlaylists
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.subscribe({ playlist ->
if (!playlist.isEmpty()) {
view.playlists(playlist)
}
}, { view.showEmptyView() }, { view.completed() }))
}
override fun loadRecentAlbums() {
disposable.add(repository.recentAlbums
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe { view.loading() }
.subscribe({ artists ->
if (!artists.isEmpty()) {
view.recentAlbum(artists)
}
}, { view.showEmptyView() }, { view.completed() }))
}
override fun loadTopAlbums() {
disposable.add(repository.topAlbums
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe { view.loading() }
.subscribe({ artists ->
if (!artists.isEmpty()) {
view.topAlbums(artists)
}
}, { view.showEmptyView() }, { view.completed() }))
}
override fun loadRecentArtists() {
disposable.add(repository.recentArtists
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe { view.loading() }
.subscribe({ artists ->
if (!artists.isEmpty()) {
view.recentArtist(artists)
}
}, { view.showEmptyView() }, { view.completed() }))
}
override fun loadTopArtists() {
disposable.add(repository.topArtists
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe { view.loading() }
.subscribe({ artists ->
if (!artists.isEmpty()) {
view.topArtists(artists)
}
}, { view.showEmptyView() }, { view.completed() }))
}
override fun loadSuggestions() {
disposable.add(repository.suggestionSongs
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe { view.loading() }
.subscribe({ songs -> view.suggestions(songs) }, { view.showEmptyView() }, { view.completed() }))
}
override fun loadGenres() {
disposable.add(repository.allGenres
.observeOn(schedulerProvider.ui())
.subscribeOn(schedulerProvider.io())
.doOnSubscribe { view.loading() }
.subscribe({ genres ->
if (!genres.isEmpty()) {
view.geners(genres)
}
},
{ view.showEmptyView() }, { view.completed() }))
}
}

View file

@ -1,54 +0,0 @@
package code.name.monkey.retromusic.mvp.presenter;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.mvp.Presenter;
import code.name.monkey.retromusic.mvp.contract.PlaylistContract;
/**
* Created by hemanths on 19/08/17.
*/
public class PlaylistPresenter extends Presenter
implements PlaylistContract.Presenter {
@NonNull
private PlaylistContract.PlaylistView mView;
public PlaylistPresenter(@NonNull PlaylistContract.PlaylistView view) {
mView = view;
}
@Override
public void subscribe() {
loadPlaylists();
}
@Override
public void unsubscribe() {
disposable.clear();
}
@Override
public void loadPlaylists() {
disposable.add(repository.getAllPlaylists()
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe(disposable1 -> mView.loading())
.subscribe(this::showList,
throwable -> mView.showEmptyView(),
() -> mView.completed()));
}
private void showList(@NonNull ArrayList<Playlist> songs) {
if (songs.isEmpty()) {
mView.showEmptyView();
} else {
mView.showData(songs);
}
}
}

View file

@ -0,0 +1,40 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.contract.PlaylistContract
import java.util.*
/**
* Created by hemanths on 19/08/17.
*/
class PlaylistPresenter(private val view: PlaylistContract.PlaylistView) : Presenter(), PlaylistContract.Presenter {
override fun subscribe() {
loadPlaylists()
}
override fun unsubscribe() {
disposable.clear()
}
override fun loadPlaylists() {
disposable.add(repository.allPlaylists
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe { view.loading() }
.subscribe({ this.showList(it) },
{ view.showEmptyView() },
{ view.completed() }))
}
private fun showList(songs: ArrayList<Playlist>) {
if (songs.isEmpty()) {
view.showEmptyView()
} else {
view.showData(songs)
}
}
}

View file

@ -1,48 +0,0 @@
package code.name.monkey.retromusic.mvp.presenter;
import androidx.annotation.NonNull;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.mvp.Presenter;
import code.name.monkey.retromusic.mvp.contract.PlaylistSongsContract;
/**
* Created by hemanths on 20/08/17.
*/
public class PlaylistSongsPresenter extends Presenter
implements PlaylistSongsContract.Presenter {
@NonNull
private PlaylistSongsContract.PlaylistSongsView mView;
@NonNull
private Playlist mPlaylist;
public PlaylistSongsPresenter(@NonNull PlaylistSongsContract.PlaylistSongsView view,
@NonNull Playlist playlist) {
mView = view;
mPlaylist = playlist;
}
@Override
public void subscribe() {
loadSongs(mPlaylist);
}
@Override
public void unsubscribe() {
disposable.clear();
}
@Override
public void loadSongs(Playlist playlist) {
disposable.add(repository.getPlaylistSongs(playlist)
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
.doOnSubscribe(disposable1 -> mView.loading())
.subscribe(songs -> mView.showData(songs),
throwable -> mView.showEmptyView(),
() -> mView.completed()));
}
}

View file

@ -0,0 +1,32 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.contract.PlaylistSongsContract
/**
* Created by hemanths on 20/08/17.
*/
class PlaylistSongsPresenter(private val view: PlaylistSongsContract.PlaylistSongsView,
private val mPlaylist: Playlist) : Presenter(), PlaylistSongsContract.Presenter {
override fun subscribe() {
loadSongs(mPlaylist)
}
override fun unsubscribe() {
disposable.clear()
}
override fun loadSongs(playlist: Playlist) {
disposable.add(repository.getPlaylistSongs(playlist)
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
.doOnSubscribe { view.loading() }
.subscribe({ songs -> view.showData(songs) },
{ view.showEmptyView() },
{ view.completed() }))
}
}

View file

@ -1,52 +0,0 @@
package code.name.monkey.retromusic.mvp.presenter;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import code.name.monkey.retromusic.mvp.Presenter;
import code.name.monkey.retromusic.mvp.contract.SearchContract;
/**
* Created by hemanths on 20/08/17.
*/
public class SearchPresenter extends Presenter implements SearchContract.SearchPresenter {
@NonNull
private SearchContract.SearchView mView;
public SearchPresenter(@NonNull SearchContract.SearchView view) {
mView = view;
}
@Override
public void subscribe() {
search("");
}
@Override
public void unsubscribe() {
disposable.clear();
}
private void showList(@NonNull ArrayList<Object> albums) {
if (albums.isEmpty()) {
mView.showEmptyView();
} else {
mView.showData(albums);
}
}
@Override
public void search(String query) {
disposable.add(repository.search(query)
.debounce(500, TimeUnit.MILLISECONDS)
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe(disposable1 -> mView.loading())
.subscribe(this::showList,
throwable -> mView.showEmptyView(),
() -> mView.completed()));
}
}

View file

@ -0,0 +1,40 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.contract.SearchContract
import java.util.*
import java.util.concurrent.TimeUnit
/**
* Created by hemanths on 20/08/17.
*/
class SearchPresenter(private val view: SearchContract.SearchView) : Presenter(), SearchContract.SearchPresenter {
override fun subscribe() {
search("")
}
override fun unsubscribe() {
disposable.clear()
}
private fun showList(albums: ArrayList<Any>) {
if (albums.isEmpty()) {
view.showEmptyView()
} else {
view.showData(albums)
}
}
override fun search(query: String) {
disposable.add(repository.search(query)
.debounce(500, TimeUnit.MILLISECONDS)
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe { view.loading() }
.subscribe({ this.showList(it) },
{ view.showEmptyView() },
{ view.completed() }))
}
}

View file

@ -1,53 +0,0 @@
package code.name.monkey.retromusic.mvp.presenter;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.mvp.Presenter;
import code.name.monkey.retromusic.mvp.contract.SongContract;
/**
* Created by hemanths on 10/08/17.
*/
public class SongPresenter extends Presenter implements SongContract.Presenter {
@NonNull
private SongContract.SongView view;
public SongPresenter(@NonNull SongContract.SongView view) {
this.view = view;
}
@Override
public void loadSongs() {
disposable.add(repository.getAllSongs()
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe(disposable1 -> view.loading())
.subscribe(this::showList,
throwable -> view.showEmptyView(),
() -> view.completed()));
}
@Override
public void subscribe() {
loadSongs();
}
private void showList(@NonNull ArrayList<Song> songs) {
if (songs.isEmpty()) {
view.showEmptyView();
} else {
view.showData(songs);
}
}
@Override
public void unsubscribe() {
disposable.clear();
}
}

View file

@ -0,0 +1,39 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.contract.SongContract
import java.util.*
/**
* Created by hemanths on 10/08/17.
*/
class SongPresenter(private val view: SongContract.SongView) : Presenter(), SongContract.Presenter {
override fun loadSongs() {
disposable.add(repository.allSongs
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
.doOnSubscribe { view.loading() }
.subscribe({ this.showList(it) },
{ view.showEmptyView() },
{ view.completed() }))
}
override fun subscribe() {
loadSongs()
}
private fun showList(songs: ArrayList<Song>) {
if (songs.isEmpty()) {
view.showEmptyView()
} else {
view.showData(songs)
}
}
override fun unsubscribe() {
disposable.clear()
}
}

View file

@ -1,25 +0,0 @@
package code.name.monkey.retromusic.preferences;
import android.content.Context;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference;
public class AlbumCoverStylePreference extends ATEDialogPreference {
public AlbumCoverStylePreference(Context context) {
super(context);
}
public AlbumCoverStylePreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AlbumCoverStylePreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public AlbumCoverStylePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
}

View file

@ -0,0 +1,17 @@
package code.name.monkey.retromusic.preferences
import android.content.Context
import android.util.AttributeSet
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
class AlbumCoverStylePreference : ATEDialogPreference {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
}

View file

@ -1,137 +0,0 @@
package code.name.monkey.retromusic.preferences;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.bumptech.glide.Glide;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.ui.fragments.AlbumCoverStyle;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.ViewUtil;
public class AlbumCoverStylePreferenceDialog extends DialogFragment implements
ViewPager.OnPageChangeListener, MaterialDialog.SingleButtonCallback {
public static final String TAG = AlbumCoverStylePreferenceDialog.class.getSimpleName();
private DialogAction whichButtonClicked;
private int viewPagerPosition;
public static AlbumCoverStylePreferenceDialog newInstance() {
return new AlbumCoverStylePreferenceDialog();
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
@SuppressLint("InflateParams") View view = LayoutInflater.from(getActivity()).inflate(R.layout.preference_dialog_now_playing_screen, null);
ViewPager viewPager = view.findViewById(R.id.now_playing_screen_view_pager);
viewPager.setAdapter(new AlbumCoverStyleAdapter(getActivity()));
viewPager.addOnPageChangeListener(this);
viewPager.setPageMargin((int) ViewUtil.convertDpToPixel(32, getResources()));
viewPager.setCurrentItem(PreferenceUtil.getInstance().getAlbumCoverStyle().ordinal());
return new MaterialDialog.Builder(getActivity())
.title(R.string.pref_title_album_cover_style)
.positiveText(android.R.string.ok)
.negativeText(android.R.string.cancel)
.onAny(this)
.customView(view, false)
.build();
}
@Override
public void onClick(@NonNull MaterialDialog dialog,
@NonNull DialogAction which) {
whichButtonClicked = which;
}
@SuppressWarnings("ConstantConditions")
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (whichButtonClicked == DialogAction.POSITIVE) {
AlbumCoverStyle nowPlayingScreen = AlbumCoverStyle.values()[viewPagerPosition];
PreferenceUtil.getInstance().setAlbumCoverStyle(nowPlayingScreen);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
this.viewPagerPosition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
private static class AlbumCoverStyleAdapter extends PagerAdapter {
private Context context;
AlbumCoverStyleAdapter(Context context) {
this.context = context;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup collection, int position) {
AlbumCoverStyle albumCoverStyle = AlbumCoverStyle.values()[position];
LayoutInflater inflater = LayoutInflater.from(context);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.preference_now_playing_screen_item, collection, false);
collection.addView(layout);
ImageView image = layout.findViewById(R.id.image);
TextView title = layout.findViewById(R.id.title);
Glide.with(context).load(albumCoverStyle.drawableResId).into(image);
title.setText(albumCoverStyle.titleRes);
return layout;
}
@Override
public void destroyItem(@NonNull ViewGroup collection,
int position,
@NonNull Object view) {
collection.removeView((View) view);
}
@Override
public int getCount() {
return AlbumCoverStyle.values().length;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@Override
public CharSequence getPageTitle(int position) {
return context.getString(AlbumCoverStyle.values()[position].titleRes);
}
}
}

View file

@ -0,0 +1,116 @@
package code.name.monkey.retromusic.preferences
import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.DialogFragment
import androidx.viewpager.widget.PagerAdapter
import androidx.viewpager.widget.ViewPager
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.ui.fragments.AlbumCoverStyle
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
import com.afollestad.materialdialogs.DialogAction
import com.afollestad.materialdialogs.MaterialDialog
import com.bumptech.glide.Glide
class AlbumCoverStylePreferenceDialog : DialogFragment(), ViewPager.OnPageChangeListener, MaterialDialog.SingleButtonCallback {
private var whichButtonClicked: DialogAction? = null
private var viewPagerPosition: Int = 0
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
@SuppressLint("InflateParams") val view = LayoutInflater.from(activity).inflate(R.layout.preference_dialog_now_playing_screen, null)
val viewPager = view.findViewById<ViewPager>(R.id.now_playing_screen_view_pager)
viewPager.adapter = AlbumCoverStyleAdapter(activity!!)
viewPager.addOnPageChangeListener(this)
viewPager.pageMargin = ViewUtil.convertDpToPixel(32f, resources).toInt()
viewPager.currentItem = PreferenceUtil.getInstance().albumCoverStyle.ordinal
return MaterialDialog.Builder(activity!!)
.title(R.string.pref_title_album_cover_style)
.positiveText(android.R.string.ok)
.negativeText(android.R.string.cancel)
.onAny(this)
.customView(view, false)
.build()
}
override fun onClick(dialog: MaterialDialog,
which: DialogAction) {
whichButtonClicked = which
}
override fun onDismiss(dialog: DialogInterface?) {
super.onDismiss(dialog)
if (whichButtonClicked == DialogAction.POSITIVE) {
val nowPlayingScreen = AlbumCoverStyle.values()[viewPagerPosition]
PreferenceUtil.getInstance().albumCoverStyle = nowPlayingScreen
}
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
this.viewPagerPosition = position
}
override fun onPageScrollStateChanged(state: Int) {
}
private class AlbumCoverStyleAdapter internal constructor(private val context: Context) : PagerAdapter() {
override fun instantiateItem(collection: ViewGroup, position: Int): Any {
val albumCoverStyle = AlbumCoverStyle.values()[position]
val inflater = LayoutInflater.from(context)
val layout = inflater.inflate(R.layout.preference_now_playing_screen_item, collection, false) as ViewGroup
collection.addView(layout)
val image = layout.findViewById<ImageView>(R.id.image)
val title = layout.findViewById<TextView>(R.id.title)
Glide.with(context).load(albumCoverStyle.drawableResId).into(image)
title.setText(albumCoverStyle.titleRes)
return layout
}
override fun destroyItem(collection: ViewGroup,
position: Int,
view: Any) {
collection.removeView(view as View)
}
override fun getCount(): Int {
return AlbumCoverStyle.values().size
}
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view === `object`
}
override fun getPageTitle(position: Int): CharSequence? {
return context.getString(AlbumCoverStyle.values()[position].titleRes)
}
}
companion object {
val TAG: String = AlbumCoverStylePreferenceDialog::class.java.simpleName
fun newInstance(): AlbumCoverStylePreferenceDialog {
return AlbumCoverStylePreferenceDialog()
}
}
}

View file

@ -1,25 +0,0 @@
package code.name.monkey.retromusic.preferences;
import android.content.Context;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference;
public class BlacklistPreference extends ATEDialogPreference {
public BlacklistPreference(Context context) {
super(context);
}
public BlacklistPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BlacklistPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public BlacklistPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
}

View file

@ -0,0 +1,17 @@
package code.name.monkey.retromusic.preferences
import android.content.Context
import android.util.AttributeSet
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
class BlacklistPreference : ATEDialogPreference {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
}

View file

@ -1,25 +0,0 @@
package code.name.monkey.retromusic.preferences;
import android.content.Context;
import android.util.AttributeSet;
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference;
public class NowPlayingScreenPreference extends ATEDialogPreference {
public NowPlayingScreenPreference(Context context) {
super(context);
}
public NowPlayingScreenPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NowPlayingScreenPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public NowPlayingScreenPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
}

View file

@ -0,0 +1,17 @@
package code.name.monkey.retromusic.preferences
import android.content.Context
import android.util.AttributeSet
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
class NowPlayingScreenPreference : ATEDialogPreference {
constructor(context: Context) : super(context) {}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {}
}

View file

@ -1,166 +0,0 @@
package code.name.monkey.retromusic.preferences;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.bumptech.glide.Glide;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.App;
import code.name.monkey.retromusic.ui.fragments.NowPlayingScreen;
import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.ViewUtil;
public class NowPlayingScreenPreferenceDialog extends DialogFragment implements
ViewPager.OnPageChangeListener, MaterialDialog.SingleButtonCallback {
public static final String TAG = NowPlayingScreenPreferenceDialog.class.getSimpleName();
private DialogAction whichButtonClicked;
private int viewPagerPosition;
public static NowPlayingScreenPreferenceDialog newInstance() {
return new NowPlayingScreenPreferenceDialog();
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
@SuppressLint("InflateParams") View view = LayoutInflater.from(getActivity())
.inflate(R.layout.preference_dialog_now_playing_screen, null);
ViewPager viewPager = view.findViewById(R.id.now_playing_screen_view_pager);
viewPager.setAdapter(new NowPlayingScreenAdapter(getActivity()));
viewPager.addOnPageChangeListener(this);
viewPager.setPageMargin((int) ViewUtil.convertDpToPixel(32, getResources()));
viewPager.setCurrentItem(PreferenceUtil.getInstance().getNowPlayingScreen().ordinal());
return new MaterialDialog.Builder(getActivity())
.title(R.string.pref_title_now_playing_screen_appearance)
.positiveText(android.R.string.ok)
.negativeText(android.R.string.cancel)
.onAny(this)
.customView(view, false)
.build();
}
@Override
public void onClick(@NonNull MaterialDialog dialog,
@NonNull DialogAction which) {
whichButtonClicked = which;
}
@SuppressWarnings("ConstantConditions")
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (whichButtonClicked == DialogAction.POSITIVE) {
NowPlayingScreen nowPlayingScreen = NowPlayingScreen.values()[viewPagerPosition];
if (isNowPlayingThemes(nowPlayingScreen)) {
String result = getString(nowPlayingScreen.titleRes) + " theme is Pro version feature.";
Toast.makeText(getContext(), result, Toast.LENGTH_SHORT).show();
NavigationUtil.goToProVersion(getActivity());
} else {
PreferenceUtil.getInstance().setNowPlayingScreen(nowPlayingScreen);
}
}
}
private boolean isNowPlayingThemes(NowPlayingScreen nowPlayingScreen) {
/*if (nowPlayingScreen.equals(NowPlayingScreen.BLUR_CARD)) {
PreferenceUtil.getInstance().resetCarouselEffect();
PreferenceUtil.getInstance().resetCircularAlbumArt();
}*/
/* return (nowPlayingScreen.equals(NowPlayingScreen.FULL) ||
nowPlayingScreen.equals(NowPlayingScreen.CARD) ||
nowPlayingScreen.equals(NowPlayingScreen.PLAIN) ||
nowPlayingScreen.equals(NowPlayingScreen.BLUR) ||
nowPlayingScreen.equals(NowPlayingScreen.COLOR) ||
nowPlayingScreen.equals(NowPlayingScreen.SIMPLE) ||
nowPlayingScreen.equals(NowPlayingScreen.TINY) ||
nowPlayingScreen.equals(NowPlayingScreen.BLUR_CARD)||
nowPlayingScreen.equals(NowPlayingScreen.ADAPTIVE))
&& !App.Companion.isProVersion();*/
return !App.Companion.isProVersion();
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
this.viewPagerPosition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
private static class NowPlayingScreenAdapter extends PagerAdapter {
private Context context;
NowPlayingScreenAdapter(Context context) {
this.context = context;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup collection, int position) {
NowPlayingScreen nowPlayingScreen = NowPlayingScreen.values()[position];
LayoutInflater inflater = LayoutInflater.from(context);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.preference_now_playing_screen_item, collection, false);
collection.addView(layout);
ImageView image = layout.findViewById(R.id.image);
TextView title = layout.findViewById(R.id.title);
Glide.with(context).load(nowPlayingScreen.drawableResId).into(image);
title.setText(nowPlayingScreen.titleRes);
return layout;
}
@Override
public void destroyItem(@NonNull ViewGroup collection,
int position,
@NonNull Object view) {
collection.removeView((View) view);
}
@Override
public int getCount() {
return NowPlayingScreen.values().length;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@Override
public CharSequence getPageTitle(int position) {
return context.getString(NowPlayingScreen.values()[position].titleRes);
}
}
}

View file

@ -0,0 +1,144 @@
package code.name.monkey.retromusic.preferences
import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.DialogFragment
import androidx.viewpager.widget.PagerAdapter
import androidx.viewpager.widget.ViewPager
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.ui.fragments.NowPlayingScreen
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
import com.afollestad.materialdialogs.DialogAction
import com.afollestad.materialdialogs.MaterialDialog
import com.bumptech.glide.Glide
class NowPlayingScreenPreferenceDialog : DialogFragment(), ViewPager.OnPageChangeListener, MaterialDialog.SingleButtonCallback {
private var whichButtonClicked: DialogAction? = null
private var viewPagerPosition: Int = 0
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
@SuppressLint("InflateParams") val view = LayoutInflater.from(activity)
.inflate(R.layout.preference_dialog_now_playing_screen, null)
val viewPager = view.findViewById<ViewPager>(R.id.now_playing_screen_view_pager)
viewPager.adapter = NowPlayingScreenAdapter(activity!!)
viewPager.addOnPageChangeListener(this)
viewPager.pageMargin = ViewUtil.convertDpToPixel(32f, resources).toInt()
viewPager.currentItem = PreferenceUtil.getInstance().nowPlayingScreen.ordinal
return MaterialDialog.Builder(activity!!)
.title(R.string.pref_title_now_playing_screen_appearance)
.positiveText(android.R.string.ok)
.negativeText(android.R.string.cancel)
.onAny(this)
.customView(view, false)
.build()
}
override fun onClick(dialog: MaterialDialog,
which: DialogAction) {
whichButtonClicked = which
}
override fun onDismiss(dialog: DialogInterface?) {
super.onDismiss(dialog)
if (whichButtonClicked == DialogAction.POSITIVE) {
val nowPlayingScreen = NowPlayingScreen.values()[viewPagerPosition]
if (isNowPlayingThemes(nowPlayingScreen)) {
val result = getString(nowPlayingScreen.titleRes) + " theme is Pro version feature."
Toast.makeText(context, result, Toast.LENGTH_SHORT).show()
NavigationUtil.goToProVersion(activity!!)
} else {
PreferenceUtil.getInstance().nowPlayingScreen = nowPlayingScreen
}
}
}
private fun isNowPlayingThemes(nowPlayingScreen: NowPlayingScreen): Boolean {
if (nowPlayingScreen == NowPlayingScreen.BLUR_CARD) {
PreferenceUtil.getInstance().resetCarouselEffect()
PreferenceUtil.getInstance().resetCircularAlbumArt()
}
return (nowPlayingScreen == NowPlayingScreen.FULL ||
nowPlayingScreen == NowPlayingScreen.CARD ||
nowPlayingScreen == NowPlayingScreen.PLAIN ||
nowPlayingScreen == NowPlayingScreen.BLUR ||
nowPlayingScreen == NowPlayingScreen.COLOR ||
nowPlayingScreen == NowPlayingScreen.SIMPLE ||
nowPlayingScreen == NowPlayingScreen.BLUR_CARD ||
nowPlayingScreen == NowPlayingScreen.ADAPTIVE)
&& !App.isProVersion
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
this.viewPagerPosition = position
}
override fun onPageScrollStateChanged(state: Int) {
}
private class NowPlayingScreenAdapter internal constructor(private val context: Context) : PagerAdapter() {
override fun instantiateItem(collection: ViewGroup, position: Int): Any {
val nowPlayingScreen = NowPlayingScreen.values()[position]
val inflater = LayoutInflater.from(context)
val layout = inflater.inflate(R.layout.preference_now_playing_screen_item, collection, false) as ViewGroup
collection.addView(layout)
val image = layout.findViewById<ImageView>(R.id.image)
val title = layout.findViewById<TextView>(R.id.title)
Glide.with(context).load(nowPlayingScreen.drawableResId).into(image)
title.setText(nowPlayingScreen.titleRes)
return layout
}
override fun destroyItem(collection: ViewGroup,
position: Int,
view: Any) {
collection.removeView(view as View)
}
override fun getCount(): Int {
return NowPlayingScreen.values().size
}
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view === `object`
}
override fun getPageTitle(position: Int): CharSequence? {
return context.getString(NowPlayingScreen.values()[position].titleRes)
}
}
companion object {
val TAG: String = NowPlayingScreenPreferenceDialog::class.java.simpleName
fun newInstance(): NowPlayingScreenPreferenceDialog {
return NowPlayingScreenPreferenceDialog()
}
}
}

View file

@ -1,60 +0,0 @@
package code.name.monkey.retromusic.providers.interfaces;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist;
import io.reactivex.Observable;
import java.io.File;
import java.util.ArrayList;
/**
* Created by hemanths on 11/08/17.
*/
public interface Repository {
Observable<ArrayList<Song>> getAllSongs();
Observable<ArrayList<Song>> getSuggestionSongs();
Observable<Song> getSong(int id);
Observable<ArrayList<Album>> getAllAlbums();
Observable<ArrayList<Album>> getRecentAlbums();
Observable<ArrayList<Album>> getTopAlbums();
Observable<Album> getAlbum(int albumId);
Observable<ArrayList<Artist>> getAllArtists();
Observable<ArrayList<Artist>> getRecentArtists();
Observable<ArrayList<Artist>> getTopArtists();
Observable<Artist> getArtistById(long artistId);
Observable<ArrayList<Playlist>> getAllPlaylists();
Observable<ArrayList<Song>> getFavoriteSongs();
Observable<ArrayList<Object>> search(String query);
Observable<ArrayList<Song>> getPlaylistSongs(Playlist playlist);
Observable<ArrayList<Playlist>> getHomeList();
Observable<ArrayList<AbsSmartPlaylist>> getAllThings();
Observable<ArrayList<Genre>> getAllGenres();
Observable<ArrayList<Song>> getGenre(int genreId);
Observable<File> downloadLrcFile(final String title, final String artist, final long duration);
}

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