package de.luhmer.owncloudnewsreader;
import android.app.Activity;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.DialogFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import net.rdrei.android.dirchooser.DirectoryChooserConfig;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
public class NewsDetailImageDialogFragment extends DialogFragment {
private static final int REQUEST_DIRECTORY = 0;
public enum TYPE { IMAGE, URL }
private static final String TAG = NewsDetailImageDialogFragment.class.getCanonicalName();
static NewsDetailImageDialogFragment newInstanceImage(String dialogTitle, Integer titleIcon, String dialogText, URL imageUrl) {
NewsDetailImageDialogFragment f = new NewsDetailImageDialogFragment();
if(titleIcon == null) {
titleIcon = android.R.drawable.ic_menu_info_details;
}
Bundle args = new Bundle();
args.putSerializable("dialogType", TYPE.IMAGE);
args.putInt("titleIcon", titleIcon);
args.putString("title", dialogTitle);
args.putString("text", dialogText);
args.putSerializable("imageUrl", imageUrl);
f.setArguments(args);
return f;
}
static NewsDetailImageDialogFragment newInstanceUrl(String dialogTitle, String dialogText) {
NewsDetailImageDialogFragment f = new NewsDetailImageDialogFragment();
Bundle args = new Bundle();
args.putSerializable("dialogType", TYPE.URL);
args.putInt("titleIcon", android.R.drawable.ic_menu_info_details);
args.putString("title", dialogTitle);
args.putString("text", dialogText);
f.setArguments(args);
return f;
}
private int mDialogIcon;
private String mDialogTitle;
private String mDialogText;
private URL mImageUrl;
private TYPE mDialogType;
private ListView mListView;
private long downloadID;
private DownloadManager downloadManager;
private BroadcastReceiver downloadCompleteReceiver;
private LinkedHashMap<String, MenuAction> mMenuItems;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDialogIcon = getArguments().getInt("titleIcon");
mDialogTitle = getArguments().getString("title");
mDialogText = getArguments().getString("text");
mImageUrl = (URL) getArguments().getSerializable("imageUrl");
mDialogType = (TYPE) getArguments().getSerializable("dialogType");
mMenuItems = new LinkedHashMap<>();
//Build the menu
switch(mDialogType) {
case IMAGE:
if(mImageUrl.toString().startsWith("http")) { //Only allow download for http[s] images (prevent download of cached images)
mMenuItems.put(getString(R.string.action_img_download), new MenuActionLongClick() {
@Override
public void execute() {
downloadImage(mImageUrl);
}
public void executeLongClick() {
changeDownloadDir();
}
});
mMenuItems.put(getString(R.string.action_img_open), new MenuAction() {
@Override
public void execute() {
openLinkInBrowser(mImageUrl);
}
});
mMenuItems.put(getString(R.string.action_img_sharelink), new MenuAction() {
@Override
public void execute() {
shareImage();
}
});
mMenuItems.put(getString(R.string.action_img_copylink), new MenuAction() {
@Override
public void execute() {
copyToClipboard(mDialogTitle, mImageUrl.toString());
}
});
} else {
mDialogTitle = "Cached image";
}
break;
case URL:
mMenuItems.put(getString(R.string.action_link_open), new MenuAction() {
@Override
public void execute() {
try {
openLinkInBrowser(new URL(mDialogText));
} catch (MalformedURLException e) {
Toast.makeText(getActivity(), getString(R.string.error_invalid_url), Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
});
mMenuItems.put(getString(R.string.action_link_share), new MenuAction() {
@Override
public void execute() {
shareLink();
}
});
mMenuItems.put(getString(R.string.action_link_copy), new MenuAction() {
@Override
public void execute() {
copyToClipboard(mDialogTitle, mDialogText);
}
});
break;
}
int style = DialogFragment.STYLE_NO_TITLE;
int theme = ThemeChooser.isDarkTheme(getActivity())
? R.style.FloatingDialog
: R.style.FloatingDialogLight;
setStyle(style, theme);
}
@Override
public void onStart() {
showDownloadShowcase();
super.onStart();
}
private void showDownloadShowcase() {
if(mMenuItems.containsKey(getActivity().getString(R.string.action_img_download))) {
List<String> menuItemsList = new ArrayList<>(mMenuItems.keySet());
int position = menuItemsList.indexOf(getActivity().getString(R.string.action_img_download));
Log.v(TAG, "Position of Download Menu: " + position);
/*
// Bug in the Library.. ShowcaseView is rendered behind the DialogFragment //TODO check https://github.com/deano2390/MaterialShowcaseView/issues/51 for updates
new MaterialShowcaseView.Builder(getActivity())
.setTarget(mListView /*.getChildAt(position) *//*)
.setDismissText("GOT IT")
.setContentText("Long press to change the target download directory")
.setDelay(300) // optional but starting animations immediately in onCreate can make them choppy
.singleUse("LONG_PRESS_DOWNLOAD_TARGET_DIR") // provide a unique ID used to ensure it is only shown once
.show();
*/
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_dialog_image, container, false);
TextView tvTitle = (TextView) v.findViewById(R.id.ic_menu_title);
TextView tvText = (TextView) v.findViewById(R.id.ic_menu_item_text);
ImageView imgTitle = (ImageView) v.findViewById(R.id.ic_menu_gallery);
tvTitle.setText(mDialogTitle);
tvText.setText(mDialogText);
imgTitle.setImageResource(mDialogIcon);
if(mDialogType == TYPE.IMAGE) {
registerImageDownloadReceiver();
if(mDialogText.equals(mDialogTitle) || mDialogText.equals("")) {
tvText.setVisibility(View.GONE);
}
}
mListView = (ListView) v.findViewById(R.id.ic_menu_item_list);
List<String> menuItemsList = new ArrayList<>(mMenuItems.keySet());
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(
getActivity(),
R.layout.fragment_dialog_listviewitem,
menuItemsList);
mListView.setAdapter(arrayAdapter);
mListView.setLongClickable(true);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String key = arrayAdapter.getItem(i);
MenuAction mAction = mMenuItems.get(key);
mAction.execute();
}
});
mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) {
String key = arrayAdapter.getItem(position);
try {
MenuActionLongClick mAction = (MenuActionLongClick) mMenuItems.get(key);
mAction.executeLongClick();
} catch (ClassCastException e) {
return false;
}
return true;
}
});
return v;
}
@Override
public void onDestroyView() {
unregisterImageDownloadReceiver();
super.onDestroyView();
}
private void copyToClipboard(String label, String text) {
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Activity.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(label, text);
clipboard.setPrimaryClip(clip);
Toast.makeText(getActivity(), getString(R.string.toast_copied_to_clipboard), Toast.LENGTH_SHORT).show();
dismiss();
}
private void shareImage() {
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, mDialogText);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, mImageUrl.toString());
startActivity(Intent.createChooser(sharingIntent, getString(R.string.intent_title_share)));
dismiss();
}
private void shareLink() {
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, mDialogTitle);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, mDialogText);
startActivity(Intent.createChooser(sharingIntent, getString(R.string.intent_title_share)));
dismiss();
}
private void openLinkInBrowser(URL url) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url.toString()));
startActivity(i);
dismiss();
}
private void downloadImage(URL url) {
Toast.makeText(getActivity().getApplicationContext(), getString(R.string.toast_img_download_wait), Toast.LENGTH_SHORT).show();
if(isExternalStorageWritable()) {
String filename = url.getFile().substring(url.getFile().lastIndexOf('/') + 1, url.getFile().length());
downloadManager = (DownloadManager) getActivity().getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url.toString()));
request.setDestinationUri(getDownloadDir(filename));
request.setTitle("Downloading image");
request.setDescription(filename);
request.setVisibleInDownloadsUi(false);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
downloadID = downloadManager.enqueue(request);
getDialog().hide();
} else {
Toast.makeText(getActivity().getApplicationContext(), getString(R.string.toast_img_notwriteable), Toast.LENGTH_LONG).show();
dismiss();
}
}
private void changeDownloadDir() {
final Intent chooserIntent = new Intent(getActivity(), DirectoryChooserActivity.class);
final DirectoryChooserConfig config = DirectoryChooserConfig.builder()
.initialDirectory(getActivity().getPreferences(Context.MODE_PRIVATE).getString("manualImageDownloadLocation", ""))
.newDirectoryName("new folder")
.allowNewDirectoryNameModification(true)
.allowReadOnlyDirectory(false)
.build();
chooserIntent.putExtra(DirectoryChooserActivity.EXTRA_CONFIG, config);
startActivityForResult(chooserIntent, REQUEST_DIRECTORY);
}
private void setNewDownloadDir(String path) {
if(path.equals("")) {
path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();
}
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("manualImageDownloadLocation", path);
editor.commit();
}
private Uri getDownloadDir(String filename) {
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
String dir = sharedPref.getString("manualImageDownloadLocation", "");
if(dir.equals("")) { //sharedPref has never been set
setNewDownloadDir(""); //set to default public download dir
return getDownloadDir(filename);
}
String tmp = "file://" +dir +"/" +filename;
return Uri.parse(tmp);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_DIRECTORY) {
if (resultCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) {
String dir = data.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR);
setNewDownloadDir(dir);
}
}
}
private void unregisterImageDownloadReceiver() {
if (downloadCompleteReceiver != null) {
getActivity().unregisterReceiver(downloadCompleteReceiver);
downloadCompleteReceiver = null;
}
}
private void registerImageDownloadReceiver() {
if(downloadCompleteReceiver != null) return;
downloadCompleteReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long refID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (downloadID == refID) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(refID);
Cursor cursor = downloadManager.query(query);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
int status = cursor.getInt(columnIndex);
int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
int reason = cursor.getInt(columnReason);
switch (status) {
case DownloadManager.STATUS_SUCCESSFUL:
Toast.makeText(getActivity().getApplicationContext(), getString(R.string.toast_img_saved), Toast.LENGTH_LONG).show();
try { dismiss(); }
catch (Exception e) {}
break;
case DownloadManager.STATUS_FAILED:
Toast.makeText(getActivity().getApplicationContext(), getString(R.string.error_download_failed) + ": " + reason, Toast.LENGTH_LONG).show();
try { dismiss(); }
catch (Exception e) {}
break;
}
}
}
};
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
getActivity().registerReceiver(downloadCompleteReceiver, intentFilter);
}
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
return Environment.MEDIA_MOUNTED.equals(state);
}
interface MenuAction {
void execute();
}
interface MenuActionLongClick extends MenuAction {
void executeLongClick();
}
}