Merge pull request #107 from poisdeux/master
Added playing or queueing artist/album/genre from music screen
This commit is contained in:
commit
2d4818689a
|
@ -41,6 +41,7 @@ import android.widget.AdapterView;
|
|||
import android.widget.CursorAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -49,10 +50,12 @@ import org.xbmc.kore.host.HostInfo;
|
|||
import org.xbmc.kore.host.HostManager;
|
||||
import org.xbmc.kore.jsonrpc.ApiException;
|
||||
import org.xbmc.kore.jsonrpc.event.MediaSyncEvent;
|
||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||
import org.xbmc.kore.provider.MediaContract;
|
||||
import org.xbmc.kore.provider.MediaDatabase;
|
||||
import org.xbmc.kore.service.LibrarySyncService;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaManager;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
|
@ -341,7 +344,7 @@ public class AlbumListFragment extends Fragment
|
|||
final int YEAR = 6;
|
||||
}
|
||||
|
||||
private static class AlbumsAdapter extends CursorAdapter {
|
||||
private class AlbumsAdapter extends CursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
|
@ -396,6 +399,11 @@ public class AlbumListFragment extends Fragment
|
|||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
thumbnail, viewHolder.albumTitle,
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
// For the popupmenu
|
||||
ImageView contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(viewHolder);
|
||||
contextMenu.setOnClickListener(albumlistItemMenuClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,4 +419,32 @@ public class AlbumListFragment extends Fragment
|
|||
int albumId;
|
||||
String albumTitle;
|
||||
}
|
||||
|
||||
private View.OnClickListener albumlistItemMenuClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||
|
||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||
playListItem.albumid = viewHolder.albumId;
|
||||
|
||||
final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
|
||||
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MediaManager.play(AlbumListFragment.this, playListItem);
|
||||
return true;
|
||||
case R.id.action_queue:
|
||||
MediaManager.queueAudio(AlbumListFragment.this, playListItem);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popupMenu.show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import android.widget.AdapterView;
|
|||
import android.widget.CursorAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -49,10 +50,12 @@ import org.xbmc.kore.host.HostInfo;
|
|||
import org.xbmc.kore.host.HostManager;
|
||||
import org.xbmc.kore.jsonrpc.ApiException;
|
||||
import org.xbmc.kore.jsonrpc.event.MediaSyncEvent;
|
||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||
import org.xbmc.kore.provider.MediaContract;
|
||||
import org.xbmc.kore.provider.MediaDatabase;
|
||||
import org.xbmc.kore.service.LibrarySyncService;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaManager;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
|
@ -84,7 +87,6 @@ public class ArtistListFragment extends Fragment
|
|||
// Activity listener
|
||||
private OnArtistSelectedListener listenerActivity;
|
||||
|
||||
private HostManager hostManager;
|
||||
private HostInfo hostInfo;
|
||||
private EventBus bus;
|
||||
|
||||
|
@ -103,8 +105,7 @@ public class ArtistListFragment extends Fragment
|
|||
ButterKnife.inject(this, root);
|
||||
|
||||
bus = EventBus.getDefault();
|
||||
hostManager = HostManager.getInstance(getActivity());
|
||||
hostInfo = hostManager.getHostInfo();
|
||||
hostInfo = HostManager.getInstance(getActivity()).getHostInfo();
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener(this);
|
||||
//UIUtils.setSwipeRefreshLayoutColorScheme(swipeRefreshLayout);
|
||||
|
@ -305,7 +306,7 @@ public class ArtistListFragment extends Fragment
|
|||
final int THUMBNAIL = 4;
|
||||
}
|
||||
|
||||
private static class ArtistsAdapter extends CursorAdapter {
|
||||
private class ArtistsAdapter extends CursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
|
@ -354,6 +355,11 @@ public class ArtistListFragment extends Fragment
|
|||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
thumbnail, viewHolder.artistName,
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
// For the popupmenu
|
||||
ImageView contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(viewHolder);
|
||||
contextMenu.setOnClickListener(artistlistItemMenuClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,4 +374,32 @@ public class ArtistListFragment extends Fragment
|
|||
int artistId;
|
||||
String artistName;
|
||||
}
|
||||
|
||||
private View.OnClickListener artistlistItemMenuClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||
|
||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||
playListItem.artistid = viewHolder.artistId;
|
||||
|
||||
final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
|
||||
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MediaManager.play(ArtistListFragment.this, playListItem);
|
||||
return true;
|
||||
case R.id.action_queue:
|
||||
MediaManager.queueAudio(ArtistListFragment.this, playListItem);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popupMenu.show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import android.widget.AdapterView;
|
|||
import android.widget.CursorAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -49,9 +50,11 @@ import org.xbmc.kore.host.HostInfo;
|
|||
import org.xbmc.kore.host.HostManager;
|
||||
import org.xbmc.kore.jsonrpc.ApiException;
|
||||
import org.xbmc.kore.jsonrpc.event.MediaSyncEvent;
|
||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||
import org.xbmc.kore.provider.MediaContract;
|
||||
import org.xbmc.kore.service.LibrarySyncService;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaManager;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
|
@ -291,7 +294,7 @@ public class AudioGenresListFragment extends Fragment
|
|||
final int THUMBNAIL = 3;
|
||||
}
|
||||
|
||||
private static class AudioGenresAdapter extends CursorAdapter {
|
||||
private class AudioGenresAdapter extends CursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
|
@ -337,6 +340,11 @@ public class AudioGenresListFragment extends Fragment
|
|||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
thumbnail, viewHolder.genreTitle,
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
// For the popupmenu
|
||||
ImageView contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(viewHolder);
|
||||
contextMenu.setOnClickListener(genrelistItemMenuClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,4 +358,32 @@ public class AudioGenresListFragment extends Fragment
|
|||
int genreId;
|
||||
String genreTitle;
|
||||
}
|
||||
|
||||
private View.OnClickListener genrelistItemMenuClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||
|
||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||
playListItem.genreid = viewHolder.genreId;
|
||||
|
||||
final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
|
||||
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MediaManager.play(AudioGenresListFragment.this, playListItem);
|
||||
return true;
|
||||
case R.id.action_queue:
|
||||
MediaManager.queueAudio(AudioGenresListFragment.this, playListItem);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popupMenu.show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright 2015 Synced Synapse. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.xbmc.kore.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.xbmc.kore.R;
|
||||
import org.xbmc.kore.Settings;
|
||||
import org.xbmc.kore.host.HostManager;
|
||||
import org.xbmc.kore.jsonrpc.ApiCallback;
|
||||
import org.xbmc.kore.jsonrpc.method.Player;
|
||||
import org.xbmc.kore.jsonrpc.method.Playlist;
|
||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||
import org.xbmc.kore.ui.RemoteActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class MediaManager {
|
||||
|
||||
/**
|
||||
* Clears current playlist and starts playing item
|
||||
* @param fragment Fragment instance from which this method is called
|
||||
* @param item PlaylistType.Item that needs to be played
|
||||
*/
|
||||
public static void play(final Fragment fragment, final PlaylistType.Item item) {
|
||||
HostManager hostManager = HostManager.getInstance(fragment.getActivity());
|
||||
|
||||
final Handler callbackHandler = new Handler();
|
||||
|
||||
final Context context = fragment.getActivity();
|
||||
|
||||
Player.Open action = new Player.Open(item);
|
||||
action.execute(hostManager.getConnection(), new ApiCallback<String>() {
|
||||
@Override
|
||||
public void onSuccess(String result) {
|
||||
if (!fragment.isAdded()) return;
|
||||
boolean switchToRemote = PreferenceManager
|
||||
.getDefaultSharedPreferences(context)
|
||||
.getBoolean(Settings.KEY_PREF_SWITCH_TO_REMOTE_AFTER_MEDIA_START,
|
||||
Settings.DEFAULT_PREF_SWITCH_TO_REMOTE_AFTER_MEDIA_START);
|
||||
if (switchToRemote) {
|
||||
Intent launchIntent = new Intent(context, RemoteActivity.class);
|
||||
context.startActivity(launchIntent);
|
||||
} else {
|
||||
Toast.makeText(context, R.string.now_playing, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorCode, String description) {
|
||||
if (!fragment.isAdded()) return;
|
||||
// Got an error, show toast
|
||||
String errorMessage = context.getString(R.string.error_play_media_file, description);
|
||||
Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}, callbackHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears current playlist and starts playing item
|
||||
* @param fragment Fragment instance from which this method is called
|
||||
* @param item PlaylistType.Item that needs to be added to the current audio playlist
|
||||
*/
|
||||
public static void queueAudio(final Fragment fragment, final PlaylistType.Item item) {
|
||||
Playlist.GetPlaylists getPlaylists = new Playlist.GetPlaylists();
|
||||
|
||||
final Handler callbackHandler = new Handler();
|
||||
|
||||
final Context context = fragment.getActivity();
|
||||
|
||||
final HostManager hostManager = HostManager.getInstance(fragment.getActivity());
|
||||
|
||||
getPlaylists.execute(hostManager.getConnection(), new ApiCallback<ArrayList<PlaylistType.GetPlaylistsReturnType>>() {
|
||||
@Override
|
||||
public void onSuccess(ArrayList<PlaylistType.GetPlaylistsReturnType> result) {
|
||||
if (!fragment.isAdded()) return;
|
||||
// Ok, loop through the playlists, looking for the audio one
|
||||
int audioPlaylistId = -1;
|
||||
for (PlaylistType.GetPlaylistsReturnType playlist : result) {
|
||||
if (playlist.type.equals(PlaylistType.GetPlaylistsReturnType.AUDIO)) {
|
||||
audioPlaylistId = playlist.playlistid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If found, add to playlist
|
||||
if (audioPlaylistId != -1) {
|
||||
Playlist.Add action = new Playlist.Add(audioPlaylistId, item);
|
||||
action.execute(hostManager.getConnection(), new ApiCallback<String>() {
|
||||
@Override
|
||||
public void onSuccess(String result) {
|
||||
if (!fragment.isAdded()) return;
|
||||
Toast.makeText(context, R.string.item_added_to_playlist, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorCode, String description) {
|
||||
if (!fragment.isAdded()) return;
|
||||
// Got an error, show toast
|
||||
String errorMessage = context.getString(R.string.error_queue_media_file, description);
|
||||
Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}, callbackHandler);
|
||||
} else {
|
||||
Toast.makeText(context, R.string.no_suitable_playlist, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorCode, String description) {
|
||||
if (!fragment.isAdded()) return;
|
||||
// Got an error, show toast
|
||||
Toast.makeText(context, R.string.error_getting_playlist, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}, callbackHandler);
|
||||
}
|
||||
}
|
|
@ -35,28 +35,43 @@
|
|||
android:layout_alignParentLeft="true"
|
||||
android:contentDescription="@string/poster"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@id/art"
|
||||
<ImageView
|
||||
android:id="@+id/list_context_menu"
|
||||
android:layout_width="@dimen/default_icon_size"
|
||||
android:layout_height="@dimen/default_icon_size"
|
||||
android:padding="@dimen/default_icon_padding"
|
||||
android:layout_alignTop="@id/art"
|
||||
style="@style/TextAppearance.Medialist.Title"/>
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_below="@id/title"
|
||||
style="@style/TextAppearance.Medialist.Details"/>
|
||||
android:layout_alignParentRight="true"
|
||||
style="@style/Widget.Button.Borderless"
|
||||
android:src="?attr/iconOverflow"
|
||||
android:contentDescription="@string/action_options"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/genres"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/name"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_alignParentBottom="true"
|
||||
style="@style/TextAppearance.Medialist.OtherInfo"/>
|
||||
android:orientation="vertical"
|
||||
android:layout_toLeftOf="@+id/list_context_menu"
|
||||
android:layout_toRightOf="@id/art"
|
||||
android:layout_alignTop="@id/art">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance.Medialist.Title"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance.Medialist.Details"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/genres"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance.Medialist.OtherInfo"/>
|
||||
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</android.support.v7.widget.CardView>
|
|
@ -35,9 +35,10 @@
|
|||
android:contentDescription="@string/poster"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical">
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
|
@ -53,5 +54,14 @@
|
|||
android:paddingBottom="0dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/list_context_menu"
|
||||
android:layout_width="@dimen/default_icon_size"
|
||||
android:layout_height="@dimen/default_icon_size"
|
||||
android:padding="@dimen/default_icon_padding"
|
||||
style="@style/Widget.Button.Borderless"
|
||||
android:src="?attr/iconOverflow"
|
||||
android:contentDescription="@string/action_options"/>
|
||||
</LinearLayout>
|
||||
</android.support.v7.widget.CardView>
|
|
@ -34,11 +34,21 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
style="@style/TextAppearance.Medialist.Title"
|
||||
android:paddingTop="0dp"
|
||||
android:paddingBottom="0dp"
|
||||
android:gravity="center_vertical"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/list_context_menu"
|
||||
android:layout_width="@dimen/default_icon_size"
|
||||
android:layout_height="@dimen/default_icon_size"
|
||||
android:padding="@dimen/default_icon_padding"
|
||||
style="@style/Widget.Button.Borderless"
|
||||
android:src="?attr/iconOverflow"
|
||||
android:contentDescription="@string/action_options"/>
|
||||
</LinearLayout>
|
||||
</android.support.v7.widget.CardView>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015 Synced Synapse. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item android:id="@+id/action_play"
|
||||
android:title="@string/play"
|
||||
android:orderInCategory="1"
|
||||
app:showAsAction="never" />
|
||||
<item android:id="@+id/action_queue"
|
||||
android:title="@string/add_to_playlist"
|
||||
android:orderInCategory="2"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
Loading…
Reference in New Issue