LyricsDialog displays lyrics without timestamps

Refactoring
This commit is contained in:
tkashkin 2017-07-08 16:29:50 +03:00
commit c047ea96a7
7 changed files with 142 additions and 112 deletions

View file

@ -2,22 +2,21 @@ package com.kabouzeid.gramophone.dialogs;
import android.app.Dialog; import android.app.Dialog;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
import com.kabouzeid.gramophone.model.lyrics.Lyrics;
/** /**
* @author Karim Abou Zeid (kabouzeid) * @author Karim Abou Zeid (kabouzeid)
*/ */
public class LyricsDialog extends DialogFragment { public class LyricsDialog extends DialogFragment {
public static LyricsDialog create(@NonNull Lyrics lyrics) {
public static LyricsDialog create(@NonNull LyricInfo lyricInfo) {
LyricsDialog dialog = new LyricsDialog(); LyricsDialog dialog = new LyricsDialog();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putParcelable("LyricInfo", lyricInfo); args.putString("title", lyrics.song.title);
args.putString("lyrics", lyrics.getText());
dialog.setArguments(args); dialog.setArguments(args);
return dialog; return dialog;
} }
@ -25,49 +24,10 @@ public class LyricsDialog extends DialogFragment {
@NonNull @NonNull
@Override @Override
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(Bundle savedInstanceState) {
LyricInfo lyricInfo = getArguments().getParcelable("LyricInfo");
//noinspection ConstantConditions //noinspection ConstantConditions
return new MaterialDialog.Builder(getActivity()) return new MaterialDialog.Builder(getActivity())
.title(lyricInfo.title) .title(getArguments().getString("title"))
.content(lyricInfo.lyrics) .content(getArguments().getString("lyrics"))
.build(); .build();
} }
public static class LyricInfo implements Parcelable {
public final String title;
public final String lyrics;
public LyricInfo(String title, String lyrics) {
this.title = title;
this.lyrics = lyrics;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.title);
dest.writeString(this.lyrics);
}
protected LyricInfo(Parcel in) {
this.title = in.readString();
this.lyrics = in.readString();
}
public static final Parcelable.Creator<LyricInfo> CREATOR = new Parcelable.Creator<LyricInfo>() {
@Override
public LyricInfo createFromParcel(Parcel source) {
return new LyricInfo(source);
}
@Override
public LyricInfo[] newArray(int size) {
return new LyricInfo[size];
}
};
}
} }

View file

@ -2,29 +2,16 @@ package com.kabouzeid.gramophone.model.lyrics;
import android.util.SparseArray; import android.util.SparseArray;
public abstract class AbsSynchronizedLyrics { import com.kabouzeid.gramophone.model.Song;
public abstract class AbsSynchronizedLyrics extends Lyrics {
private static final int TIME_OFFSET_MS = 500; // time adjustment to display line before it actually starts private static final int TIME_OFFSET_MS = 500; // time adjustment to display line before it actually starts
public final SparseArray<String> lines = new SparseArray<>(); public final SparseArray<String> lines = new SparseArray<>();
public boolean isValid = false;
public int offset = 0; public int offset = 0;
/** AbsSynchronizedLyrics(Song song, String data) {
* @param data Lyrics string super(song, data);
* @param justCheck Set isValid = true and stop parsing if lyrics appears to be valid
* and has at least 1 line
*/
public static AbsSynchronizedLyrics parse(String data, boolean justCheck) {
return new SynchronizedLyricsLRC(data, justCheck); // no another formats at the moment
}
public static AbsSynchronizedLyrics parse(String data) {
return parse(data, false);
}
public static boolean isSynchronized(String data) {
AbsSynchronizedLyrics lyrics = parse(data, true);
return lyrics.isValid;
} }
public String getLine(int time) { public String getLine(int time) {
@ -44,4 +31,31 @@ public abstract class AbsSynchronizedLyrics {
return lines.get(lastLineTime); return lines.get(lastLineTime);
} }
public boolean isSynchronized() {
return true;
}
public boolean isValid() {
this.parse(true);
return this.valid;
}
@Override
public String getText() {
if (isValid()) {
parse(false);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < lines.size(); i++) {
String line = lines.valueAt(i);
sb.append(line).append('\n');
}
return sb.toString();
}
return super.getText();
}
} }

View file

@ -0,0 +1,49 @@
package com.kabouzeid.gramophone.model.lyrics;
import com.kabouzeid.gramophone.model.Song;
public class Lyrics {
public Song song;
public String data;
boolean parsed = false;
boolean valid = false;
public Lyrics(Song song, String data) {
this.song = song;
this.data = data;
}
public static Lyrics parse(Song song, String data) {
Lyrics lyrics = new SynchronizedLyricsLRC(song, data);
if (lyrics.isValid()) {
return lyrics.parse(false);
} else {
return new Lyrics(song, data).parse(false);
}
}
public static boolean isSynchronized(String data) {
Lyrics lyrics = new SynchronizedLyricsLRC(null, data);
return lyrics.isValid();
}
public Lyrics parse(boolean check) {
this.valid = true;
this.parsed = true;
return this;
}
public boolean isSynchronized() {
return false;
}
public boolean isValid() {
this.parse(true);
return this.valid;
}
public String getText() {
return this.data;
}
}

View file

@ -1,9 +1,11 @@
package com.kabouzeid.gramophone.model.lyrics; package com.kabouzeid.gramophone.model.lyrics;
import com.kabouzeid.gramophone.model.Song;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class SynchronizedLyricsLRC extends AbsSynchronizedLyrics { class SynchronizedLyricsLRC extends AbsSynchronizedLyrics {
private static final Pattern LRC_LINE_PATTERN = Pattern.compile("((?:\\[.*?\\])+)(.*)"); private static final Pattern LRC_LINE_PATTERN = Pattern.compile("((?:\\[.*?\\])+)(.*)");
private static final Pattern LRC_TIME_PATTERN = Pattern.compile("\\[(\\d+):(\\d{2}(?:\\.\\d+)?)\\]"); private static final Pattern LRC_TIME_PATTERN = Pattern.compile("\\[(\\d+):(\\d{2}(?:\\.\\d+)?)\\]");
private static final Pattern LRC_ATTRIBUTE_PATTERN = Pattern.compile("\\[(\\D+):(.+)\\]"); private static final Pattern LRC_ATTRIBUTE_PATTERN = Pattern.compile("\\[(\\D+):(.+)\\]");
@ -11,17 +13,17 @@ public class SynchronizedLyricsLRC extends AbsSynchronizedLyrics {
private static final float LRC_SECONDS_TO_MS_MULTIPLIER = 1000f; private static final float LRC_SECONDS_TO_MS_MULTIPLIER = 1000f;
private static final int LRC_MINUTES_TO_MS_MULTIPLIER = 60000; private static final int LRC_MINUTES_TO_MS_MULTIPLIER = 60000;
/** SynchronizedLyricsLRC(Song song, String data) {
* @param data Lyrics string super(song, data);
* @param justCheck Set isValid = true and stop parsing if lyrics appears to be valid
* and has at least 1 line
*/
public SynchronizedLyricsLRC(String data, boolean justCheck) {
if (data == null || data.isEmpty()) {
return;
} }
String[] lines = data.split("\r?\n"); @Override
public SynchronizedLyricsLRC parse(boolean check) {
if (this.parsed || this.data == null || this.data.isEmpty()) {
return this;
}
String[] lines = this.data.split("\r?\n");
for (String line : lines) { for (String line : lines) {
line = line.trim(); line = line.trim();
@ -60,14 +62,17 @@ public class SynchronizedLyricsLRC extends AbsSynchronizedLyrics {
} }
int ms = (int) (s * LRC_SECONDS_TO_MS_MULTIPLIER) + m * LRC_MINUTES_TO_MS_MULTIPLIER; int ms = (int) (s * LRC_SECONDS_TO_MS_MULTIPLIER) + m * LRC_MINUTES_TO_MS_MULTIPLIER;
this.isValid = true; this.valid = true;
if (justCheck) return; if (check) return this;
this.lines.append(ms, text); this.lines.append(ms, text);
} }
} }
} }
} }
}
this.parsed = true;
return this;
}
} }

View file

@ -20,6 +20,7 @@ import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.helper.MusicProgressViewUpdateHelper; import com.kabouzeid.gramophone.helper.MusicProgressViewUpdateHelper;
import com.kabouzeid.gramophone.misc.SimpleAnimatorListener; import com.kabouzeid.gramophone.misc.SimpleAnimatorListener;
import com.kabouzeid.gramophone.model.lyrics.AbsSynchronizedLyrics; import com.kabouzeid.gramophone.model.lyrics.AbsSynchronizedLyrics;
import com.kabouzeid.gramophone.model.lyrics.Lyrics;
import com.kabouzeid.gramophone.ui.fragments.AbsMusicServiceFragment; import com.kabouzeid.gramophone.ui.fragments.AbsMusicServiceFragment;
import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.PreferenceUtil;
import com.kabouzeid.gramophone.util.ViewUtil; import com.kabouzeid.gramophone.util.ViewUtil;
@ -42,7 +43,7 @@ public class PlayerAlbumCoverFragment extends AbsMusicServiceFragment implements
ImageView favoriteIcon; ImageView favoriteIcon;
@BindView(R.id.player_lyrics) @BindView(R.id.player_lyrics)
FrameLayout lyrics; FrameLayout lyricsLayout;
@BindView(R.id.player_lyrics_line1) @BindView(R.id.player_lyrics_line1)
TextView lyricsLine1; TextView lyricsLine1;
@BindView(R.id.player_lyrics_line2) @BindView(R.id.player_lyrics_line2)
@ -51,7 +52,7 @@ public class PlayerAlbumCoverFragment extends AbsMusicServiceFragment implements
private Callbacks callbacks; private Callbacks callbacks;
private int currentPosition; private int currentPosition;
private AbsSynchronizedLyrics synchronizedLyrics; private Lyrics lyrics;
private MusicProgressViewUpdateHelper progressViewUpdateHelper; private MusicProgressViewUpdateHelper progressViewUpdateHelper;
@Override @Override
@ -181,18 +182,18 @@ public class PlayerAlbumCoverFragment extends AbsMusicServiceFragment implements
.start(); .start();
} }
public void setSynchronizedLyrics(AbsSynchronizedLyrics sLyrics) { public void setLyrics(Lyrics l) {
if (sLyrics == null || sLyrics.lines.size() == 0) { if (l == null || !l.isSynchronized() || !l.isValid()) {
synchronizedLyrics = null; lyrics = null;
lyrics.setVisibility(View.GONE); lyricsLayout.setVisibility(View.GONE);
lyricsLine1.setText(null); lyricsLine1.setText(null);
lyricsLine2.setText(null); lyricsLine2.setText(null);
return; return;
} }
synchronizedLyrics = sLyrics; lyrics = l;
lyrics.setVisibility(View.VISIBLE); lyricsLayout.setVisibility(View.VISIBLE);
} }
private void notifyColorChange(int color) { private void notifyColorChange(int color) {
@ -205,14 +206,17 @@ public class PlayerAlbumCoverFragment extends AbsMusicServiceFragment implements
@Override @Override
public void onUpdateProgressViews(int progress, int total) { public void onUpdateProgressViews(int progress, int total) {
if (synchronizedLyrics == null || synchronizedLyrics.lines.size() == 0 || !PreferenceUtil.getInstance(getActivity()).synchronizedLyricsShow()) { if (lyrics == null || !lyrics.isSynchronized() || !lyrics.isValid() || !PreferenceUtil.getInstance(getActivity()).synchronizedLyricsShow()) {
lyrics.setVisibility(View.GONE); lyricsLayout.setVisibility(View.GONE);
lyricsLine1.setText(null); lyricsLine1.setText(null);
lyricsLine2.setText(null); lyricsLine2.setText(null);
return; return;
} }
lyrics.setVisibility(View.VISIBLE); if (!(lyrics instanceof AbsSynchronizedLyrics)) return;
AbsSynchronizedLyrics synchronizedLyrics = (AbsSynchronizedLyrics) lyrics;
lyricsLayout.setVisibility(View.VISIBLE);
String oldLine = lyricsLine2.getText().toString(); String oldLine = lyricsLine2.getText().toString();
String line = synchronizedLyrics.getLine(progress); String line = synchronizedLyrics.getLine(progress);

View file

@ -42,7 +42,7 @@ import com.kabouzeid.gramophone.dialogs.SongShareDialog;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.helper.menu.SongMenuHelper; import com.kabouzeid.gramophone.helper.menu.SongMenuHelper;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.model.lyrics.AbsSynchronizedLyrics; import com.kabouzeid.gramophone.model.lyrics.Lyrics;
import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity; import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity;
import com.kabouzeid.gramophone.ui.fragments.player.AbsPlayerFragment; import com.kabouzeid.gramophone.ui.fragments.player.AbsPlayerFragment;
import com.kabouzeid.gramophone.ui.fragments.player.PlayerAlbumCoverFragment; import com.kabouzeid.gramophone.ui.fragments.player.PlayerAlbumCoverFragment;
@ -89,7 +89,7 @@ public class CardPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
private AsyncTask updateIsFavoriteTask; private AsyncTask updateIsFavoriteTask;
private AsyncTask updateLyricsAsyncTask; private AsyncTask updateLyricsAsyncTask;
private LyricsDialog.LyricInfo lyricsInfo; private Lyrics lyrics;
private Impl impl; private Impl impl;
@ -236,8 +236,8 @@ public class CardPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_show_lyrics: case R.id.action_show_lyrics:
if (lyricsInfo != null) if (lyrics != null)
LyricsDialog.create(lyricsInfo).show(getFragmentManager(), "LYRICS"); LyricsDialog.create(lyrics).show(getFragmentManager(), "LYRICS");
return true; return true;
} }
return super.onMenuItemClick(item); return super.onMenuItemClick(item);
@ -304,8 +304,8 @@ public class CardPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
@Override @Override
protected void onPreExecute() { protected void onPreExecute() {
super.onPreExecute(); super.onPreExecute();
lyricsInfo = null; lyrics = null;
playerAlbumCoverFragment.setSynchronizedLyrics(null); playerAlbumCoverFragment.setLyrics(null);
toolbar.getMenu().removeItem(R.id.action_show_lyrics); toolbar.getMenu().removeItem(R.id.action_show_lyrics);
} }
@ -315,16 +315,15 @@ public class CardPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
} }
@Override @Override
protected void onPostExecute(String lyrics) { protected void onPostExecute(String data) {
super.onPostExecute(lyrics); if (TextUtils.isEmpty(data)) {
if (TextUtils.isEmpty(lyrics)) { lyrics = null;
lyricsInfo = null;
if (toolbar != null) { if (toolbar != null) {
toolbar.getMenu().removeItem(R.id.action_show_lyrics); toolbar.getMenu().removeItem(R.id.action_show_lyrics);
} }
} else { } else {
lyricsInfo = new LyricsDialog.LyricInfo(song.title, lyrics); lyrics = Lyrics.parse(song, data);
playerAlbumCoverFragment.setSynchronizedLyrics(AbsSynchronizedLyrics.parse(lyrics)); playerAlbumCoverFragment.setLyrics(lyrics);
Activity activity = getActivity(); Activity activity = getActivity();
if (toolbar != null && activity != null) if (toolbar != null && activity != null)
if (toolbar.getMenu().findItem(R.id.action_show_lyrics) == null) { if (toolbar.getMenu().findItem(R.id.action_show_lyrics) == null) {

View file

@ -40,7 +40,7 @@ import com.kabouzeid.gramophone.dialogs.SongShareDialog;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.helper.menu.SongMenuHelper; import com.kabouzeid.gramophone.helper.menu.SongMenuHelper;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.model.lyrics.AbsSynchronizedLyrics; import com.kabouzeid.gramophone.model.lyrics.Lyrics;
import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity; import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity;
import com.kabouzeid.gramophone.ui.fragments.player.AbsPlayerFragment; import com.kabouzeid.gramophone.ui.fragments.player.AbsPlayerFragment;
import com.kabouzeid.gramophone.ui.fragments.player.PlayerAlbumCoverFragment; import com.kabouzeid.gramophone.ui.fragments.player.PlayerAlbumCoverFragment;
@ -86,7 +86,7 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
private AsyncTask updateIsFavoriteTask; private AsyncTask updateIsFavoriteTask;
private AsyncTask updateLyricsAsyncTask; private AsyncTask updateLyricsAsyncTask;
private LyricsDialog.LyricInfo lyricsInfo; private Lyrics lyrics;
private Impl impl; private Impl impl;
@ -232,8 +232,8 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_show_lyrics: case R.id.action_show_lyrics:
if (lyricsInfo != null) if (lyrics != null)
LyricsDialog.create(lyricsInfo).show(getFragmentManager(), "LYRICS"); LyricsDialog.create(lyrics).show(getFragmentManager(), "LYRICS");
return true; return true;
} }
return super.onMenuItemClick(item); return super.onMenuItemClick(item);
@ -300,8 +300,8 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
@Override @Override
protected void onPreExecute() { protected void onPreExecute() {
super.onPreExecute(); super.onPreExecute();
lyricsInfo = null; lyrics = null;
playerAlbumCoverFragment.setSynchronizedLyrics(null); playerAlbumCoverFragment.setLyrics(null);
toolbar.getMenu().removeItem(R.id.action_show_lyrics); toolbar.getMenu().removeItem(R.id.action_show_lyrics);
} }
@ -311,16 +311,15 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
} }
@Override @Override
protected void onPostExecute(String lyrics) { protected void onPostExecute(String data) {
super.onPostExecute(lyrics); if (TextUtils.isEmpty(data)) {
if (TextUtils.isEmpty(lyrics)) { lyrics = null;
lyricsInfo = null;
if (toolbar != null) { if (toolbar != null) {
toolbar.getMenu().removeItem(R.id.action_show_lyrics); toolbar.getMenu().removeItem(R.id.action_show_lyrics);
} }
} else { } else {
lyricsInfo = new LyricsDialog.LyricInfo(song.title, lyrics); lyrics = Lyrics.parse(song, data);
playerAlbumCoverFragment.setSynchronizedLyrics(AbsSynchronizedLyrics.parse(lyrics)); playerAlbumCoverFragment.setLyrics(lyrics);
Activity activity = getActivity(); Activity activity = getActivity();
if (toolbar != null && activity != null) if (toolbar != null && activity != null)
if (toolbar.getMenu().findItem(R.id.action_show_lyrics) == null) { if (toolbar.getMenu().findItem(R.id.action_show_lyrics) == null) {