Added a lyrics dialog. Updated the SlidingUpPanelLayout lib which fixes a few sliding issues. Fixed an issue where the sling panel would get stuck somewhere in the middle. Fixed a NPE in an asynctask onPostExecute().
This commit is contained in:
parent
c168dc1e25
commit
9b17931cd6
9 changed files with 197 additions and 8 deletions
|
|
@ -134,7 +134,7 @@ dependencies {
|
||||||
compile 'com.android.support:preference-v7:23.2.1'
|
compile 'com.android.support:preference-v7:23.2.1'
|
||||||
compile 'com.github.ksoichiro:android-observablescrollview:1.6.0'
|
compile 'com.github.ksoichiro:android-observablescrollview:1.6.0'
|
||||||
compile 'com.github.kabouzeid:SeekArc:1.2-kmod'
|
compile 'com.github.kabouzeid:SeekArc:1.2-kmod'
|
||||||
compile 'com.github.kabouzeid:AndroidSlidingUpPanel:3.3.1-kmod'
|
compile 'com.github.kabouzeid:AndroidSlidingUpPanel:3.3.0-kmod2'
|
||||||
compile 'com.squareup.retrofit2:retrofit:2.0.0'
|
compile 'com.squareup.retrofit2:retrofit:2.0.0'
|
||||||
compile 'com.squareup.retrofit2:converter-gson:2.0.0'
|
compile 'com.squareup.retrofit2:converter-gson:2.0.0'
|
||||||
compile 'com.jakewharton:butterknife:7.0.1'
|
compile 'com.jakewharton:butterknife:7.0.1'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.kabouzeid.gramophone.dialogs;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
|
||||||
|
import hugo.weaving.DebugLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
*/
|
||||||
|
public class LyricsDialog extends DialogFragment {
|
||||||
|
|
||||||
|
public static LyricsDialog create(@NonNull LyricInfo lyricInfo) {
|
||||||
|
LyricsDialog dialog = new LyricsDialog();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putParcelable("LyricInfo", lyricInfo);
|
||||||
|
dialog.setArguments(args);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@DebugLog
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
LyricInfo lyricInfo = getArguments().getParcelable("LyricInfo");
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return new MaterialDialog.Builder(getActivity())
|
||||||
|
.title(lyricInfo.title)
|
||||||
|
.content(lyricInfo.lyrics)
|
||||||
|
.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];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -107,6 +107,9 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi
|
||||||
case EXPANDED:
|
case EXPANDED:
|
||||||
onPanelExpanded(panel);
|
onPanelExpanded(panel);
|
||||||
break;
|
break;
|
||||||
|
case ANCHORED:
|
||||||
|
collapsePanel(); // this fixes a bug where the panel would get stuck for some reason
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.kabouzeid.gramophone.ui.fragments.player;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
|
import android.app.Activity;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
@ -15,7 +16,9 @@ import android.support.v7.widget.CardView;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewAnimationUtils;
|
import android.view.ViewAnimationUtils;
|
||||||
|
|
@ -36,6 +39,7 @@ import com.kabouzeid.appthemehelper.util.ToolbarContentTintHelper;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.adapter.base.MediaEntryViewHolder;
|
import com.kabouzeid.gramophone.adapter.base.MediaEntryViewHolder;
|
||||||
import com.kabouzeid.gramophone.adapter.song.PlayingQueueAdapter;
|
import com.kabouzeid.gramophone.adapter.song.PlayingQueueAdapter;
|
||||||
|
import com.kabouzeid.gramophone.dialogs.LyricsDialog;
|
||||||
import com.kabouzeid.gramophone.dialogs.SongShareDialog;
|
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;
|
||||||
|
|
@ -47,6 +51,16 @@ import com.kabouzeid.gramophone.util.ViewUtil;
|
||||||
import com.kabouzeid.gramophone.views.WidthFitSquareLayout;
|
import com.kabouzeid.gramophone.views.WidthFitSquareLayout;
|
||||||
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
|
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
|
||||||
|
|
||||||
|
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.FieldKey;
|
||||||
|
import org.jaudiotagger.tag.TagException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
|
|
@ -79,6 +93,9 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove
|
||||||
private RecyclerViewDragDropManager recyclerViewDragDropManager;
|
private RecyclerViewDragDropManager recyclerViewDragDropManager;
|
||||||
|
|
||||||
private AsyncTask updateIsFavoriteTask;
|
private AsyncTask updateIsFavoriteTask;
|
||||||
|
private AsyncTask updateLyricsAsyncTask;
|
||||||
|
|
||||||
|
private LyricsDialog.LyricInfo lyricsInfo;
|
||||||
|
|
||||||
private Impl impl;
|
private Impl impl;
|
||||||
|
|
||||||
|
|
@ -160,6 +177,7 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove
|
||||||
updateQueue();
|
updateQueue();
|
||||||
updateCurrentSong();
|
updateCurrentSong();
|
||||||
updateIsFavorite();
|
updateIsFavorite();
|
||||||
|
updateLyrics();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -167,6 +185,7 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove
|
||||||
updateCurrentSong();
|
updateCurrentSong();
|
||||||
updateIsFavorite();
|
updateIsFavorite();
|
||||||
updateQueuePosition();
|
updateQueuePosition();
|
||||||
|
updateLyrics();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -217,6 +236,17 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove
|
||||||
toolbar.setOnMenuItemClickListener(this);
|
toolbar.setOnMenuItemClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_show_lyrics:
|
||||||
|
if (lyricsInfo != null)
|
||||||
|
LyricsDialog.create(lyricsInfo).show(getFragmentManager(), "LYRICS");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onMenuItemClick(item);
|
||||||
|
}
|
||||||
|
|
||||||
private void setUpRecyclerView() {
|
private void setUpRecyclerView() {
|
||||||
recyclerViewDragDropManager = new RecyclerViewDragDropManager();
|
recyclerViewDragDropManager = new RecyclerViewDragDropManager();
|
||||||
final GeneralItemAnimator animator = new RefactoredDefaultItemAnimator();
|
final GeneralItemAnimator animator = new RefactoredDefaultItemAnimator();
|
||||||
|
|
@ -252,16 +282,65 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Boolean isFavorite) {
|
protected void onPostExecute(Boolean isFavorite) {
|
||||||
int res = isFavorite ? R.drawable.ic_favorite_white_24dp : R.drawable.ic_favorite_border_white_24dp;
|
Activity activity = getActivity();
|
||||||
int color = ToolbarContentTintHelper.toolbarContentColor(getActivity(), Color.TRANSPARENT);
|
if (activity != null) {
|
||||||
Drawable drawable = TintHelper.createTintedDrawable(ContextCompat.getDrawable(getActivity(), res), color);
|
int res = isFavorite ? R.drawable.ic_favorite_white_24dp : R.drawable.ic_favorite_border_white_24dp;
|
||||||
toolbar.getMenu().findItem(R.id.action_toggle_favorite)
|
int color = ToolbarContentTintHelper.toolbarContentColor(activity, Color.TRANSPARENT);
|
||||||
.setIcon(drawable)
|
Drawable drawable = TintHelper.createTintedDrawable(ContextCompat.getDrawable(activity, res), color);
|
||||||
.setTitle(isFavorite ? getString(R.string.action_remove_from_favorites) : getString(R.string.action_add_to_favorites));
|
toolbar.getMenu().findItem(R.id.action_toggle_favorite)
|
||||||
|
.setIcon(drawable)
|
||||||
|
.setTitle(isFavorite ? getString(R.string.action_remove_from_favorites) : getString(R.string.action_add_to_favorites));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.execute(MusicPlayerRemote.getCurrentSong());
|
}.execute(MusicPlayerRemote.getCurrentSong());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateLyrics() {
|
||||||
|
if (updateLyricsAsyncTask != null) updateLyricsAsyncTask.cancel(false);
|
||||||
|
final Song song = MusicPlayerRemote.getCurrentSong();
|
||||||
|
updateLyricsAsyncTask = new AsyncTask<Void, Void, String>() {
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
super.onPreExecute();
|
||||||
|
lyricsInfo = null;
|
||||||
|
toolbar.getMenu().removeItem(R.id.action_show_lyrics);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String doInBackground(Void... params) {
|
||||||
|
try {
|
||||||
|
return AudioFileIO.read(new File(song.data)).getTagOrCreateDefault().getFirst(FieldKey.LYRICS);
|
||||||
|
} catch (IOException | CannotReadException | TagException | InvalidAudioFrameException | ReadOnlyFileException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(String lyrics) {
|
||||||
|
super.onPostExecute(lyrics);
|
||||||
|
if (TextUtils.isEmpty(lyrics)) {
|
||||||
|
lyricsInfo = null;
|
||||||
|
if (toolbar != null) {
|
||||||
|
toolbar.getMenu().removeItem(R.id.action_show_lyrics);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lyricsInfo = new LyricsDialog.LyricInfo(song.title, lyrics);
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (toolbar != null && activity != null)
|
||||||
|
if (toolbar.getMenu().findItem(R.id.action_show_lyrics) == null) {
|
||||||
|
int color = ToolbarContentTintHelper.toolbarContentColor(activity, Color.TRANSPARENT);
|
||||||
|
Drawable drawable = TintHelper.createTintedDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_comment_text_outline_white_24dp), color);
|
||||||
|
toolbar.getMenu()
|
||||||
|
.add(Menu.NONE, R.id.action_show_lyrics, Menu.NONE, R.string.action_show_lyrics)
|
||||||
|
.setIcon(drawable)
|
||||||
|
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ColorInt
|
@ColorInt
|
||||||
public int getPaletteColor() {
|
public int getPaletteColor() {
|
||||||
|
|
@ -333,6 +412,9 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove
|
||||||
case COLLAPSED:
|
case COLLAPSED:
|
||||||
onPanelCollapsed(panel);
|
onPanelCollapsed(panel);
|
||||||
break;
|
break;
|
||||||
|
case ANCHORED:
|
||||||
|
slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); // this fixes a bug where the panel would get stuck for some reason
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -448,7 +530,7 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove
|
||||||
int topMargin = fragment.getResources().getDimensionPixelSize(R.dimen.status_bar_padding);
|
int topMargin = fragment.getResources().getDimensionPixelSize(R.dimen.status_bar_padding);
|
||||||
|
|
||||||
final int availablePanelHeight = fragment.slidingUpPanelLayout.getHeight() - fragment.getView().findViewById(R.id.player_content).getHeight() + topMargin;
|
final int availablePanelHeight = fragment.slidingUpPanelLayout.getHeight() - fragment.getView().findViewById(R.id.player_content).getHeight() + topMargin;
|
||||||
final int minPanelHeight = (int) fragment.getResources().getDisplayMetrics().density * (72 + 24) + topMargin;
|
final int minPanelHeight = (int) ViewUtil.convertDpToPixel(72 + 24, fragment.getResources()) + topMargin;
|
||||||
if (availablePanelHeight < minPanelHeight) {
|
if (availablePanelHeight < minPanelHeight) {
|
||||||
albumCoverContainer.getLayoutParams().height = albumCoverContainer.getHeight() - (minPanelHeight - availablePanelHeight);
|
albumCoverContainer.getLayoutParams().height = albumCoverContainer.getHeight() - (minPanelHeight - availablePanelHeight);
|
||||||
albumCoverContainer.forceSquare(false);
|
albumCoverContainer.forceSquare(false);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import android.animation.ArgbEvaluator;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
@ -13,6 +14,7 @@ import android.graphics.drawable.StateListDrawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.support.annotation.ColorInt;
|
import android.support.annotation.ColorInt;
|
||||||
import android.support.v4.view.ViewCompat;
|
import android.support.v4.view.ViewCompat;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.animation.PathInterpolator;
|
import android.view.animation.PathInterpolator;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
@ -84,4 +86,14 @@ public class ViewUtil {
|
||||||
recyclerView.setThumbColor(accentColor);
|
recyclerView.setThumbColor(accentColor);
|
||||||
recyclerView.setTrackColor(ColorUtil.withAlpha(ATHUtil.resolveColor(context, R.attr.colorControlNormal), 0.12f));
|
recyclerView.setTrackColor(ColorUtil.withAlpha(ATHUtil.resolveColor(context, R.attr.colorControlNormal), 0.12f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float convertDpToPixel(float dp, Resources resources) {
|
||||||
|
DisplayMetrics metrics = resources.getDisplayMetrics();
|
||||||
|
return dp * metrics.density;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float convertPixelsToDp(float px, Resources resources) {
|
||||||
|
DisplayMetrics metrics = resources.getDisplayMetrics();
|
||||||
|
return px / metrics.density;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!-- drawable/comment_text_outline.xml -->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M9,22A1,1 0 0,1 8,21V18H4A2,2 0 0,1 2,16V4C2,2.89 2.9,2 4,2H20A2,2 0 0,1 22,4V16A2,2 0 0,1 20,18H13.9L10.2,21.71C10,21.9 9.75,22 9.5,22V22H9M10,16V19.08L13.08,16H20V4H4V16H10M6,7H18V9H6V7M6,11H15V13H6V11Z" />
|
||||||
|
</vector>
|
||||||
|
|
@ -4,21 +4,25 @@
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_toggle_favorite"
|
android:id="@+id/action_toggle_favorite"
|
||||||
android:icon="@drawable/ic_favorite_border_white_24dp"
|
android:icon="@drawable/ic_favorite_border_white_24dp"
|
||||||
|
android:orderInCategory="1"
|
||||||
android:title="@string/action_add_to_favorites"
|
android:title="@string/action_add_to_favorites"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_shuffle_all"
|
android:id="@+id/action_shuffle_all"
|
||||||
|
android:orderInCategory="1"
|
||||||
android:title="@string/action_shuffle_all"
|
android:title="@string/action_shuffle_all"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_clear_playing_queue"
|
android:id="@+id/action_clear_playing_queue"
|
||||||
|
android:orderInCategory="1"
|
||||||
android:title="@string/action_clear_playing_queue"
|
android:title="@string/action_clear_playing_queue"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_sleep_timer"
|
android:id="@+id/action_sleep_timer"
|
||||||
|
android:orderInCategory="1"
|
||||||
android:title="@string/action_sleep_timer"
|
android:title="@string/action_sleep_timer"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<item name="action_new_playlist" type="id" />
|
<item name="action_new_playlist" type="id" />
|
||||||
|
<item name="action_show_lyrics" type="id" />
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -99,6 +99,7 @@
|
||||||
<string name="action_shuffle_playlist">Shuffle playlist</string>
|
<string name="action_shuffle_playlist">Shuffle playlist</string>
|
||||||
<string name="action_clear_playing_queue">Clear playing queue</string>
|
<string name="action_clear_playing_queue">Clear playing queue</string>
|
||||||
<string name="action_go_to_start_directory">Go to start directory</string>
|
<string name="action_go_to_start_directory">Go to start directory</string>
|
||||||
|
<string name="action_show_lyrics">Show lyrics</string>
|
||||||
<string name="last_opened">Last opened</string>
|
<string name="last_opened">Last opened</string>
|
||||||
<string name="light_theme_name">Light</string>
|
<string name="light_theme_name">Light</string>
|
||||||
<string name="dark_theme_name">Dark</string>
|
<string name="dark_theme_name">Dark</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue