Commit b8151c37 authored by Geoffrey Métais's avatar Geoffrey Métais

Save favorite network directories

parent ada524bc
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/separator_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:layout_marginLeft="20dp"
android:fontFamily="sans-serif"/>
</LinearLayout>
\ No newline at end of file
......@@ -2,6 +2,13 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:vlc="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/ml_menu_save"
android:icon="@drawable/abc_btn_check_to_on_mtrl_000"
android:title="@string/clear_history"
android:nextFocusDown="@+id/ml_menu_search"
android:visible="false"
vlc:showAsAction="ifRoom" />
<item
android:id="@+id/ml_menu_clean"
android:icon="@drawable/ic_trash_normal_w"
......
......@@ -40,6 +40,7 @@ import android.database.sqlite.SQLiteFullException;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Log;
public class MediaDatabase {
......@@ -49,7 +50,7 @@ public class MediaDatabase {
private SQLiteDatabase mDb;
private final String DB_NAME = "vlc_database";
private final int DB_VERSION = 12;
private final int DB_VERSION = 13;
private final int CHUNK_SIZE = 50;
private final String DIR_TABLE_NAME = "directories_table";
......@@ -91,6 +92,9 @@ public class MediaDatabase {
private final String MRL_URI = "uri";
private final String MRL_TABLE_SIZE = "100";
private final String NETWORK_FAV_TABLE_NAME = "fav_table";
private final String NETWORK_FAV_URI = "uri";
public enum mediaColumn {
MEDIA_TABLE_NAME, MEDIA_PATH, MEDIA_TIME, MEDIA_LENGTH,
MEDIA_TYPE, MEDIA_PICTURE, MEDIA_TITLE, MEDIA_ARTIST, MEDIA_GENRE, MEDIA_ALBUM,
......@@ -217,6 +221,18 @@ public class MediaDatabase {
db.execSQL(query);
}
private void createNetworkFavTableQuery(SQLiteDatabase db) {
String createMrlTableQuery = "CREATE TABLE IF NOT EXISTS " +
NETWORK_FAV_TABLE_NAME + " (" +
MRL_URI + " TEXT PRIMARY KEY NOT NULL);";
db.execSQL(createMrlTableQuery);
}
public void dropNetworkFavTableQuery(SQLiteDatabase db) {
String query = "DROP TABLE " + NETWORK_FAV_TABLE_NAME + ";";
db.execSQL(query);
}
@Override
public void onCreate(SQLiteDatabase db) {
......@@ -244,6 +260,8 @@ public class MediaDatabase {
db.execSQL(createSearchhistoryTabelQuery);
createMRLTableQuery(db);
createNetworkFavTableQuery(db);
}
@Override
......@@ -264,6 +282,9 @@ public class MediaDatabase {
case 11:
createMRLTableQuery(db);
break;
case 13:
createNetworkFavTableQuery(db);
break;
default:
break;
}
......@@ -937,6 +958,49 @@ public class MediaDatabase {
mDb.delete(MRL_TABLE_NAME, null, null);
}
public synchronized void addNetworkFavItem(String mrl) {
ContentValues values = new ContentValues();
values.put(NETWORK_FAV_URI, Uri.encode(mrl));
mDb.replace(NETWORK_FAV_TABLE_NAME, null, values);
}
public synchronized boolean networkFavExists(String mrl) {
Cursor cursor = mDb.query(NETWORK_FAV_TABLE_NAME,
new String[] { NETWORK_FAV_URI },
NETWORK_FAV_URI + "=?",
new String[] { Uri.encode(mrl) },
null, null, null);
boolean exists = cursor.moveToFirst();
cursor.close();
return exists;
}
public synchronized ArrayList<String> getAllNetworkFav() {
ArrayList<String> favs = new ArrayList<String>();
Cursor cursor = mDb.query(NETWORK_FAV_TABLE_NAME,
new String[] { NETWORK_FAV_URI },
null, null, null, null, null);
while (cursor.moveToNext()) {
favs.add(Uri.decode(cursor.getString(0)));
}
cursor.close();
return favs;
}
public synchronized void deleteNetworkFav(String uri) {
ArrayList<String> history = new ArrayList<String>();
mDb.delete(NETWORK_FAV_TABLE_NAME, NETWORK_FAV_URI + "=?", new String[] { Uri.encode(uri) });
}
public synchronized void clearNetworkFavTable() {
mDb.delete(NETWORK_FAV_TABLE_NAME, null, null);
}
/**
* Empty the database for debugging purposes
*/
......
......@@ -32,4 +32,9 @@ public class BrowserFragment extends Fragment {
protected void setReadyToDisplay(boolean ready){}
protected void display(){}
public void onStart(){
super.onStart();
getActivity().supportInvalidateOptionsMenu();
}
}
......@@ -70,6 +70,11 @@ public class MRLPanelFragment extends Fragment implements View.OnKeyListener, Te
return v;
}
public void onStart(){
super.onStart();
getActivity().supportInvalidateOptionsMenu();
}
private void updateHistory() {
mHistory = MediaDatabase.getInstance().getMrlhistory();
mAdapter.setList(mHistory);
......
......@@ -560,6 +560,18 @@ public class MainActivity extends ActionBarActivity implements OnItemClickListen
if (mCurrentFragment != null && mCurrentFragment.equals("search"))
menu.findItem(R.id.search_clear_history).setVisible(true);
boolean networkSave = current instanceof NetworkFragment && !((NetworkFragment)current).isRootDirectory();
if (networkSave) {
MenuItem item = menu.findItem(R.id.ml_menu_save);
item.setVisible(true);
String mrl = ((NetworkFragment)current).mMrl;
item.setIcon(MediaDatabase.getInstance().networkFavExists(mrl) ?
R.drawable.abc_btn_check_to_on_mtrl_015 :
R.drawable.abc_btn_check_to_on_mtrl_000);
}
else
menu.findItem(R.id.ml_menu_save).setVisible(false);
menu.findItem(R.id.ml_menu_clean).setVisible(SidebarEntry.ID_MRL.equals(mCurrentFragment));
menu.findItem(R.id.ml_menu_last_playlist).setVisible(SidebarEntry.ID_AUDIO.equals(mCurrentFragment));
......@@ -640,6 +652,10 @@ public class MainActivity extends ActionBarActivity implements OnItemClickListen
case R.id.search_clear_history:
MediaDatabase.getInstance().clearSearchHistory();
break;
case R.id.ml_menu_save:
((NetworkFragment)current).toggleFavorite();
item.setIcon(R.drawable.abc_btn_check_to_on_mtrl_015);
break;
}
mRootContainer.closeDrawer(mSideMenu);
return super.onOptionsItemSelected(item);
......@@ -1021,7 +1037,6 @@ public class MainActivity extends ActionBarActivity implements OnItemClickListen
ft.replace(R.id.fragment_placeholder, fragment, entry.id);
ft.addToBackStack(mCurrentFragment);
ft.commit();
supportInvalidateOptionsMenu();
mCurrentFragment = entry.id;
mSidebarAdapter.setCurrentFragment(mCurrentFragment);
......
......@@ -38,10 +38,13 @@ import org.videolan.vlc.util.Util;
import java.util.ArrayList;
import java.util.Collections;
public class NetworkAdapter extends RecyclerView.Adapter<NetworkAdapter.ViewHolder> {
public class NetworkAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "VLC/NetworkAdapter";
ArrayList<MediaWrapper> mMediaList = new ArrayList<MediaWrapper>();
private static final int TYPE_MEDIA = 0;
private static final int TYPE_SEPARATOR = 1;
ArrayList<Object> mMediaList = new ArrayList<Object>();
NetworkFragment fragment;
public NetworkAdapter(NetworkFragment fragment){
......@@ -49,29 +52,43 @@ public class NetworkAdapter extends RecyclerView.Adapter<NetworkAdapter.ViewHol
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.directory_view_item, parent, false);
ViewHolder vh = new ViewHolder(v);
vh.more.setVisibility(View.GONE);
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder vh;
View v;
if (viewType == TYPE_MEDIA) {
v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.directory_view_item, parent, false);
vh = new MediaViewHolder(v);
} else {
v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.browser_item_separator, parent, false);
vh = new SeparatorViewHolder(v);
}
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
final MediaWrapper media = getItem(position);
holder.title.setText(media.getTitle());
holder.text.setVisibility(View.GONE);
holder.icon.setImageResource(getIconResId(media));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (media.getType() == MediaWrapper.TYPE_DIR)
fragment.browse(media);
else
Util.openMedia(v.getContext(), media);
}
});
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof MediaViewHolder) {
MediaViewHolder vh = (MediaViewHolder) holder;
final MediaWrapper media = (MediaWrapper) getItem(position);
vh.title.setText(media.getTitle());
vh.text.setVisibility(View.GONE);
vh.icon.setImageResource(getIconResId(media));
vh.more.setVisibility(View.GONE);
vh.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (media.getType() == MediaWrapper.TYPE_DIR)
fragment.browse(media);
else
Util.openMedia(v.getContext(), media);
}
});
} else {
SeparatorViewHolder vh = (SeparatorViewHolder) holder;
vh.title.setText(getItem(position).toString());
}
}
@Override
......@@ -79,13 +96,13 @@ public class NetworkAdapter extends RecyclerView.Adapter<NetworkAdapter.ViewHol
return mMediaList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public static class MediaViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public TextView text;
public ImageView icon;
public ImageView more;
public ViewHolder(View v) {
public MediaViewHolder(View v) {
super(v);
title = (TextView) v.findViewById(R.id.title);
text = (TextView) v.findViewById(R.id.text);
......@@ -94,6 +111,15 @@ public class NetworkAdapter extends RecyclerView.Adapter<NetworkAdapter.ViewHol
}
}
public static class SeparatorViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public SeparatorViewHolder(View v) {
super(v);
title = (TextView) v.findViewById(R.id.separator_title);
}
}
public void clear(){
mMediaList.clear();
notifyDataSetChanged();
......@@ -103,27 +129,49 @@ public class NetworkAdapter extends RecyclerView.Adapter<NetworkAdapter.ViewHol
return mMediaList.isEmpty();
}
public void addItem(Media media, boolean update){
public void addItem(Media media, boolean root, boolean first){
MediaWrapper mediaWrapper = new MediaWrapper(media);
if (mediaWrapper.getTitle().startsWith("."))
addItem(mediaWrapper, root, first);
}
public void addItem(Object item, boolean root, boolean first){
int position = first ? 0 : mMediaList.size();
if (item instanceof MediaWrapper && ((MediaWrapper)item).getTitle().startsWith("."))
return;
mMediaList.add(mediaWrapper);
if (update)
notifyItemInserted(mMediaList.size()-1);
else if (item instanceof Media)
item = new MediaWrapper((Media) item);
mMediaList.add(position, item);
if (root)
notifyItemInserted(position);
}
public MediaWrapper getItem(int position){
public void removeItem(int position){
mMediaList.remove(position);
}
public Object getItem(int position){
return mMediaList.get(position);
}
public int getItemViewType(int position){
if (getItem(position) instanceof MediaWrapper)
return TYPE_MEDIA;
else
return TYPE_SEPARATOR;
}
public void sortList(){
ArrayList<MediaWrapper> files = new ArrayList<MediaWrapper>(), dirs = new ArrayList<MediaWrapper>();
for (MediaWrapper media : mMediaList){
if (media.getType() == MediaWrapper.TYPE_DIR)
dirs.add(media);
else
files.add(media);
for (Object item : mMediaList){
if (item instanceof MediaWrapper) {
MediaWrapper media = (MediaWrapper) item;
if (media.getType() == MediaWrapper.TYPE_DIR)
dirs.add(media);
else
files.add(media);
}
}
Collections.sort(dirs, MediaComparators.byName);
Collections.sort(files, MediaComparators.byName);
......
......@@ -36,6 +36,7 @@ import android.view.ViewGroup;
import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.util.MediaBrowser;
import org.videolan.vlc.MediaDatabase;
import org.videolan.vlc.MediaWrapper;
import org.videolan.vlc.R;
import org.videolan.vlc.gui.BrowserFragment;
......@@ -43,6 +44,8 @@ import org.videolan.vlc.gui.DividerItemDecoration;
import org.videolan.vlc.interfaces.IRefreshable;
import org.videolan.vlc.util.WeakHandler;
import java.util.ArrayList;
public class NetworkFragment extends BrowserFragment implements IRefreshable, MediaBrowser.EventListener, SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "VLC/NetworkFragment";
......@@ -55,10 +58,10 @@ public class NetworkFragment extends BrowserFragment implements IRefreshable, Me
private MediaBrowser mMediaBrowser;
private RecyclerView mRecyclerView;
private SwipeRefreshLayout mSwipeRefreshLayout;
private NetworkAdapter madapter;
private NetworkAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private String mMrl;
private int savedPosition = -1;
public String mMrl;
private int savedPosition = -1, mFavorites = 0;
private boolean mRoot;
LibVLC mLibVLC = LibVLC.getExistingInstance();
......@@ -73,7 +76,7 @@ public class NetworkFragment extends BrowserFragment implements IRefreshable, Me
mMrl = SMB_ROOT;
mRoot = SMB_ROOT.equals(mMrl);
mHandler = new NetworkFragmentHandler(this);
madapter = new NetworkAdapter(this);
mAdapter = new NetworkAdapter(this);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
......@@ -83,7 +86,7 @@ public class NetworkFragment extends BrowserFragment implements IRefreshable, Me
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(madapter);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setOnScrollListener(mScrollListener);
mSwipeRefreshLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipeLayout);
......@@ -100,10 +103,13 @@ public class NetworkFragment extends BrowserFragment implements IRefreshable, Me
super.onStart();
if (mMediaBrowser == null)
mMediaBrowser = new MediaBrowser(mLibVLC, this);
if (madapter.isEmpty())
if (mAdapter.isEmpty()) {
refresh();
else if (savedPosition > 0)
mRecyclerView.scrollTo(0, savedPosition);
} else {
updateFavorites();
if (savedPosition > 0)
mRecyclerView.scrollTo(0, savedPosition);
}
}
public void onSaveInstanceState(Bundle outState){
......@@ -133,7 +139,7 @@ public class NetworkFragment extends BrowserFragment implements IRefreshable, Me
@Override
public void onMediaAdded(int index, Media media) {
madapter.addItem(media, mRoot);
mAdapter.addItem(media, mRoot, true);
if (mRoot)
mHandler.sendEmptyMessage(NetworkFragmentHandler.MSG_HIDE_LOADING);
}
......@@ -143,7 +149,7 @@ public class NetworkFragment extends BrowserFragment implements IRefreshable, Me
@Override
public void onBrowseEnd() {
madapter.sortList();
mAdapter.sortList();
mHandler.sendEmptyMessage(NetworkFragmentHandler.MSG_HIDE_LOADING);
int position = getArguments().getInt(KEY_POSITION);
if (position > 0)
......@@ -171,11 +177,51 @@ public class NetworkFragment extends BrowserFragment implements IRefreshable, Me
@Override
public void refresh() {
madapter.clear();
mAdapter.clear();
if (mRoot){
ArrayList<String> favs = MediaDatabase.getInstance().getAllNetworkFav();
if (!favs.isEmpty()) {
mFavorites = favs.size();
for (String fav : favs) {
mAdapter.addItem(new MediaWrapper(mLibVLC, fav), false, true);
mAdapter.notifyDataSetChanged();
}
mAdapter.addItem("Network favorites", false, true);
}
}
mMediaBrowser.browse(mMrl);
mHandler.sendEmptyMessageDelayed(NetworkFragmentHandler.MSG_SHOW_LOADING, 300);
}
private void updateFavorites(){
ArrayList<String> favs = MediaDatabase.getInstance().getAllNetworkFav();
int newSize = favs.size(), totalSize = mAdapter.getItemCount();
if (newSize == 0 && mFavorites == 0)
return;
for (int i = 1 ; i <= mFavorites ; ++i){ //remove former favorites
mAdapter.removeItem(totalSize-i);
}
if (newSize == 0)
mAdapter.removeItem(totalSize-mFavorites-1); //also remove separator if no more fav
else {
if (mFavorites == 0)
mAdapter.addItem("Network favorites", false, false); //add header if needed
for (String fav : favs)
mAdapter.addItem(new MediaWrapper(mLibVLC, fav), false, false); //add new favorites
}
mFavorites = newSize; //update count
}
public void toggleFavorite() {
MediaDatabase db = MediaDatabase.getInstance();
if (db.networkFavExists(mMrl))
db.deleteNetworkFav(mMrl);
else
db.addNetworkFavItem(mMrl);
getActivity().supportInvalidateOptionsMenu();
}
private static class NetworkFragmentHandler extends WeakHandler<NetworkFragment> {
public static final int MSG_SHOW_LOADING = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment