Commit ae0da86c authored by Geoffrey Métais's avatar Geoffrey Métais
Browse files

Handle custom directories creation and deletion

parent 055265f3
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/directory_remove_custom_path"
android:title="@string/remove_custom_path" />
</menu>
\ No newline at end of file
......@@ -9,6 +9,12 @@
android:nextFocusDown="@+id/ml_menu_search"
android:visible="false"
vlc:showAsAction="ifRoom" />
<item
android:id="@+id/ml_menu_add_dir"
android:icon="@drawable/ic_add_white"
android:title="@string/add_custom_path"
android:visible="false"
vlc:showAsAction="always" />
<item
android:id="@+id/ml_menu_clean"
android:icon="@drawable/ic_trash_normal_w"
......
......@@ -74,6 +74,7 @@ import org.videolan.vlc.gui.SidebarAdapter.SidebarEntry;
import org.videolan.vlc.gui.audio.AudioBrowserFragment;
import org.videolan.vlc.gui.audio.AudioPlayer;
import org.videolan.vlc.gui.browser.BaseBrowserFragment;
import org.videolan.vlc.gui.browser.FileBrowserFragment;
import org.videolan.vlc.gui.browser.MediaBrowserFragment;
import org.videolan.vlc.gui.browser.NetworkBrowserFragment;
import org.videolan.vlc.gui.video.VideoGridFragment;
......@@ -522,6 +523,10 @@ public class MainActivity extends AppCompatActivity implements OnItemClickListen
boolean showLast = current instanceof AudioBrowserFragment || (current instanceof VideoGridFragment && mSettings.getString(PreferencesActivity.VIDEO_LAST, null) != null);
menu.findItem(R.id.ml_menu_last_playlist).setVisible(showLast);
if (current instanceof FileBrowserFragment && ((FileBrowserFragment) current).isRootDirectory())
menu.findItem(R.id.ml_menu_add_dir).setVisible(true);
else
menu.findItem(R.id.ml_menu_add_dir).setVisible(false);
return true;
}
......@@ -593,6 +598,10 @@ public class MainActivity extends AppCompatActivity implements OnItemClickListen
((NetworkBrowserFragment)current).toggleFavorite();
item.setIcon(R.drawable.ic_menu_bookmark_w);
break;
case R.id.ml_menu_add_dir:
if (current != null && current instanceof FileBrowserFragment)
((FileBrowserFragment) current).showAddDirectoryDialog();
break;
}
mRootContainer.closeDrawer(mListView);
return super.onOptionsItemSelected(item);
......
......@@ -38,10 +38,13 @@ import org.videolan.vlc.MediaDatabase;
import org.videolan.vlc.MediaWrapper;
import org.videolan.vlc.R;
import org.videolan.vlc.gui.audio.MediaComparators;
import org.videolan.vlc.util.CustomDirectories;
import org.videolan.vlc.util.Strings;
import org.videolan.vlc.util.Util;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
......@@ -59,6 +62,7 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
BaseBrowserFragment fragment;
MediaDatabase mDbManager;
LinkedList<String> mMediaDirsLocation;
List<String> mCustomDirsLocation;
public BaseBrowserAdapter(BaseBrowserFragment fragment){
this.fragment = fragment;
......@@ -84,85 +88,99 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
if (viewType == TYPE_MEDIA) {
final MediaViewHolder vh = (MediaViewHolder) holder;
final MediaWrapper media = (MediaWrapper) getItem(position);
boolean hasContextMenu = (media.getType() == MediaWrapper.TYPE_AUDIO ||
media.getType() == MediaWrapper.TYPE_VIDEO ||
(media.getType() == MediaWrapper.TYPE_DIR && Util.canWrite(media.getLocation())));
vh.checkBox.setVisibility(View.GONE);
vh.title.setText(media.getTitle());
if (!TextUtils.isEmpty(media.getDescription())) {
vh.text.setVisibility(View.VISIBLE);
vh.text.setText(media.getDescription());
} else
vh.text.setVisibility(View.INVISIBLE);
vh.icon.setImageResource(getIconResId(media));
vh.more.setVisibility(hasContextMenu ? View.VISIBLE : View.GONE);
vh.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaWrapper mw = (MediaWrapper) getItem(holder.getAdapterPosition());
if (mw.getType() == MediaWrapper.TYPE_DIR)
fragment.browse(mw, holder.getPosition());
else if (mw.getType() == MediaWrapper.TYPE_VIDEO) {
Util.openMedia(v.getContext(), mw);
} else {
int position = 0;
LinkedList<String> mediaLocations = new LinkedList<String>();
MediaWrapper mediaItem;
for (Object item : mMediaList)
if (item instanceof MediaWrapper){
mediaItem = (MediaWrapper) item;
if (mediaItem.getType() == MediaWrapper.TYPE_VIDEO || mediaItem.getType() == MediaWrapper.TYPE_AUDIO) {
mediaLocations.add(mediaItem.getLocation());
if (mediaItem.equals(mw))
position = mediaLocations.size()-1;
}
onBindMediaViewHolder(holder, position);
} else if (viewType == TYPE_STORAGE) {
onBindStorageViewHolder(holder, position);
} else {
SeparatorViewHolder vh = (SeparatorViewHolder) holder;
vh.title.setText(getItem(position).toString());
}
}
private void onBindMediaViewHolder(final RecyclerView.ViewHolder holder, int position) {
final MediaViewHolder vh = (MediaViewHolder) holder;
final MediaWrapper media = (MediaWrapper) getItem(position);
boolean hasContextMenu = (media.getType() == MediaWrapper.TYPE_AUDIO ||
media.getType() == MediaWrapper.TYPE_VIDEO ||
(media.getType() == MediaWrapper.TYPE_DIR && Util.canWrite(media.getLocation())));
vh.checkBox.setVisibility(View.GONE);
vh.title.setText(media.getTitle());
if (!TextUtils.isEmpty(media.getDescription())) {
vh.text.setVisibility(View.VISIBLE);
vh.text.setText(media.getDescription());
} else
vh.text.setVisibility(View.INVISIBLE);
vh.icon.setImageResource(getIconResId(media));
vh.more.setVisibility(hasContextMenu ? View.VISIBLE : View.GONE);
vh.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaWrapper mw = (MediaWrapper) getItem(holder.getAdapterPosition());
if (mw.getType() == MediaWrapper.TYPE_DIR)
fragment.browse(mw, holder.getAdapterPosition());
else {
int position = 0;
LinkedList<String> mediaLocations = new LinkedList<String>();
MediaWrapper mediaItem;
for (Object item : mMediaList)
if (item instanceof MediaWrapper) {
mediaItem = (MediaWrapper) item;
if (mediaItem.getType() == MediaWrapper.TYPE_VIDEO || mediaItem.getType() == MediaWrapper.TYPE_AUDIO) {
mediaLocations.add(mediaItem.getLocation());
if (mediaItem.equals(mw))
position = mediaLocations.size() - 1;
}
Util.openList(v.getContext(), mediaLocations, position);
}
}
Util.openList(v.getContext(), mediaLocations, position);
}
});
if (hasContextMenu) {
vh.more.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
fragment.onPopupMenu(vh.more, holder.getAdapterPosition());
}
});
vh.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
fragment.mRecyclerView.openContextMenu(holder.getAdapterPosition());
return true;
}
});
}
} else if (viewType == TYPE_STORAGE) {
final MediaViewHolder vh = (MediaViewHolder) holder;
final Storage storage = (Storage) getItem(position);
vh.title.setText(storage.getName());
vh.icon.setVisibility(View.GONE);
vh.checkBox.setVisibility(View.VISIBLE);
vh.more.setVisibility(View.GONE);
String description = storage.getDescription();
if (!TextUtils.isEmpty(description)) {
vh.text.setVisibility(View.VISIBLE);
vh.text.setText(description);
} else
vh.text.setVisibility(View.INVISIBLE);
vh.itemView.setOnClickListener(new View.OnClickListener() {
});
if (hasContextMenu) {
vh.more.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaWrapper mw = new MediaWrapper(((Storage)getItem(vh.getAdapterPosition())).getPath());
mw.setType(MediaWrapper.TYPE_DIR);
fragment.browse(mw, holder.getAdapterPosition());
fragment.onPopupMenu(vh.more, holder.getAdapterPosition());
}
});
vh.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
fragment.mRecyclerView.openContextMenu(holder.getAdapterPosition());
return true;
}
});
vh.checkBox.setChecked(TextUtils.equals(storage.getPath(), Environment.getExternalStorageDirectory().getPath()) ||
mMediaDirsLocation == null || mMediaDirsLocation.isEmpty() ||
mMediaDirsLocation.contains(storage.getPath()));
}
}
private void onBindStorageViewHolder(final RecyclerView.ViewHolder holder, int position) {
final MediaViewHolder vh = (MediaViewHolder) holder;
final Storage storage = (Storage) getItem(position);
boolean isPublicStorage = TextUtils.equals(storage.getPath(), Environment.getExternalStorageDirectory().getPath());
boolean hasContextMenu = !isPublicStorage && mCustomDirsLocation.contains(storage.getPath());
vh.title.setText(storage.getName());
vh.icon.setVisibility(View.GONE);
vh.checkBox.setVisibility(View.VISIBLE);
vh.more.setVisibility(hasContextMenu ? View.VISIBLE : View.GONE);
String description = storage.getDescription();
if (!TextUtils.isEmpty(description)) {
vh.text.setVisibility(View.VISIBLE);
vh.text.setText(description);
} else
vh.text.setVisibility(View.INVISIBLE);
vh.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaWrapper mw = new MediaWrapper(((Storage)getItem(vh.getAdapterPosition())).getPath());
mw.setType(MediaWrapper.TYPE_DIR);
fragment.browse(mw, holder.getAdapterPosition());
}
});
vh.checkBox.setChecked(isPublicStorage ||
mMediaDirsLocation == null || mMediaDirsLocation.isEmpty() ||
mMediaDirsLocation.contains(storage.getPath()));
if (!isPublicStorage) {
vh.checkBox.setEnabled(true);
vh.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
......@@ -183,10 +201,23 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
}
});
} else {
SeparatorViewHolder vh = (SeparatorViewHolder) holder;
vh.title.setText(getItem(position).toString());
}
if (hasContextMenu) {
vh.more.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
fragment.onPopupMenu(vh.more, holder.getAdapterPosition());
}
});
vh.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
fragment.mRecyclerView.openContextMenu(holder.getAdapterPosition());
return true;
}
});
}
} else
vh.checkBox.setEnabled(false);
}
@Override
......@@ -296,6 +327,7 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
for (File dir : mediaDirs){
mMediaDirsLocation.add(dir.getPath());
}
mCustomDirsLocation = Arrays.asList(CustomDirectories.getCustomDirectories());
}
public void addAll(ArrayList<MediaWrapper> mediaList){
......
......@@ -337,7 +337,7 @@ public abstract class BaseBrowserFragment extends MediaBrowserFragment implement
setContextMenu(getActivity().getMenuInflater(), menu, info.position);
}
private void setContextMenu(MenuInflater inflater, Menu menu, int position) {
protected void setContextMenu(MenuInflater inflater, Menu menu, int position) {
MediaWrapper mw = (MediaWrapper) mAdapter.getItem(position);
boolean canWrite = Util.canWrite(mw.getLocation());
if (mw.getType() == MediaWrapper.TYPE_AUDIO || mw.getType() == MediaWrapper.TYPE_VIDEO) {
......@@ -381,7 +381,7 @@ public abstract class BaseBrowserFragment extends MediaBrowserFragment implement
popupMenu.show();
}
private boolean handleContextItemSelected(MenuItem item, int position) {
protected boolean handleContextItemSelected(MenuItem item, int position) {
int id = item.getItemId();
if (! (mAdapter.getItem(position) instanceof MediaWrapper))
return super.onContextItemSelected(item);
......
......@@ -25,18 +25,32 @@ package org.videolan.vlc.gui.browser;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.AppCompatEditText;
import android.text.InputType;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
import org.videolan.vlc.MediaWrapper;
import org.videolan.libvlc.LibVlcUtil;
import org.videolan.vlc.MediaDatabase;
import org.videolan.vlc.R;
import org.videolan.vlc.util.AndroidDevices;
import org.videolan.vlc.util.CustomDirectories;
import java.io.File;
public class FileBrowserFragment extends BaseBrowserFragment {
private AlertDialog mAlertDialog;
public FileBrowserFragment() {
super();
ROOT = Environment.getExternalStorageDirectory().getPath();
......@@ -60,6 +74,7 @@ public class FileBrowserFragment extends BaseBrowserFragment {
@Override
protected void browseRoot() {
mAdapter.updateMediaDirs();
String storages[] = AndroidDevices.getMediaDirectories();
BaseBrowserAdapter.Storage storage;
for (String mediaDirLocation : storages) {
......@@ -99,6 +114,68 @@ public class FileBrowserFragment extends BaseBrowserFragment {
public void onStop() {
super.onStop();
getActivity().unregisterReceiver(storageReceiver);
if (mAlertDialog != null && mAlertDialog.isShowing())
mAlertDialog.dismiss();
}
public void showAddDirectoryDialog() {
final Context context = getActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
final AppCompatEditText input = new AppCompatEditText(context);
if (!LibVlcUtil.isHoneycombOrLater()) {
input.setTextColor(getResources().getColor(R.color.grey50));
}
input.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
builder.setTitle(R.string.add_custom_path);
builder.setMessage(R.string.add_custom_path_description);
builder.setView(input);
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
return;
}
});
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String path = input.getText().toString().trim();
File f = new File(path);
if (!f.exists() || !f.isDirectory()) {
Toast.makeText(context, getString(R.string.directorynotfound, path), Toast.LENGTH_SHORT).show();
return;
}
CustomDirectories.addCustomDirectory(f.getAbsolutePath());
refresh();
}
});
mAlertDialog = builder.show();
}
protected void setContextMenu(MenuInflater inflater, Menu menu, int position) {
if (mRoot) {
BaseBrowserAdapter.Storage storage = (BaseBrowserAdapter.Storage) mAdapter.getItem(position);
boolean isCustom = CustomDirectories.contains(storage.getPath());
if (isCustom)
inflater.inflate(R.menu.directory_custom_dir, menu);
} else
super.setContextMenu(inflater, menu, position);
}
@Override
protected boolean handleContextItemSelected(MenuItem item, int position) {
if (mRoot) {
if (item.getItemId() == R.id.directory_remove_custom_path){
BaseBrowserAdapter.Storage storage = (BaseBrowserAdapter.Storage) mAdapter.getItem(position);
MediaDatabase.getInstance().recursiveRemoveDir(storage.getPath());
CustomDirectories.removeCustomDirectory(storage.getPath());
mAdapter.updateMediaDirs();
mAdapter.removeItem(position, true);
return true;
} else
return false;
} else
return super.handleContextItemSelected(item, position);
}
private final BroadcastReceiver storageReceiver = new BroadcastReceiver() {
......
......@@ -22,6 +22,7 @@ package org.videolan.vlc.util;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import org.videolan.vlc.VLCApplication;
......@@ -81,4 +82,13 @@ public class CustomDirectories {
return custom_paths.split(":");
}
public static boolean contains(String directory){
directory = directory.trim();
String[] directories = getCustomDirectories();
for (int i = 0 ; i < directories.length ; ++i){
if (TextUtils.equals(directory, directories[i]))
return true;
}
return false;
}
}
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