package com.bigpupdev.synodroid.ui;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import com.bigpupdev.synodroid.R;
import com.bigpupdev.synodroid.Synodroid;
import com.bigpupdev.synodroid.action.DeleteTaskAction;
import com.bigpupdev.synodroid.action.DownloadOriginalLinkAction;
import com.bigpupdev.synodroid.action.EnumShareAction;
import com.bigpupdev.synodroid.action.GetDirectoryListShares;
import com.bigpupdev.synodroid.action.GetFilesAction;
import com.bigpupdev.synodroid.action.GetTaskPropertiesAction;
import com.bigpupdev.synodroid.action.PauseTaskAction;
import com.bigpupdev.synodroid.action.ResumeTaskAction;
import com.bigpupdev.synodroid.action.SetShared;
import com.bigpupdev.synodroid.action.UpdateTaskPropertiesAction;
import com.bigpupdev.synodroid.adapter.Detail;
import com.bigpupdev.synodroid.adapter.Detail2Progress;
import com.bigpupdev.synodroid.adapter.Detail2Text;
import com.bigpupdev.synodroid.adapter.DetailAction;
import com.bigpupdev.synodroid.adapter.DetailProgress;
import com.bigpupdev.synodroid.adapter.DetailText;
import com.bigpupdev.synodroid.data.DSMVersion;
import com.bigpupdev.synodroid.data.Folder;
import com.bigpupdev.synodroid.data.OriginalFile;
import com.bigpupdev.synodroid.data.SharedDirectory;
import com.bigpupdev.synodroid.data.SharedFolderSelection;
import com.bigpupdev.synodroid.data.Task;
import com.bigpupdev.synodroid.data.TaskDetail;
import com.bigpupdev.synodroid.data.TaskFile;
import com.bigpupdev.synodroid.data.TaskProperties;
import com.bigpupdev.synodroid.data.TaskStatus;
import com.bigpupdev.synodroid.protocol.ResponseHandler;
import com.bigpupdev.synodroid.server.SynoServer;
import com.bigpupdev.synodroid.utils.ActivityHelper;
import com.bigpupdev.synodroid.utils.EulaHelper;
import com.bigpupdev.synodroid.utils.UIUtils;
import com.bigpupdev.synodroid.utils.Utils;
import com.bigpupdev.synodroid.utils.ViewPagerIndicator;
import de.keyboardsurfer.android.widget.crouton.Crouton;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Environment;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.BadTokenException;
import android.widget.EditText;
import android.widget.Spinner;
public class DetailActivity extends BaseActivity{
private static final String PREFERENCE_FULLSCREEN = "general_cat.fullscreen";
private static final String PREFERENCE_GENERAL = "general_cat";
MyAdapter mAdapter;
ViewPager mPager;
ViewPagerIndicator mIndicator;
Task task;
TaskStatus status;
// The seeding ratio
private int seedingRatio;
// The seeding time
private int seedingTime;
private int ul_rate;
private int dl_rate;
private int priority;
private int max_peers;
private String destination;
private int[] priorities;
// Flag to know of the user changed seeding parameters
private boolean seedingChanged = false;
// The values of seeding time
private int[] seedingTimes;
private static final int MENU_PAUSE = 1;
private static final int MENU_DELETE = 2;
private static final int MENU_CANCEL = 3;
private static final int MENU_RESUME = 4;
private static final int MENU_RETRY = 5;
private static final int MENU_CLEAR = 6;
private static final int MENU_PARAMETERS = 7;
private static final int MENU_DESTINATION = 8;
private static final int MENU_SHARE = 9;
private static final int TASK_PARAMETERS_DIALOG = 3;
private static final int TASK_PROPERTIES_DIALOG = 4;
private static final int MAIN_ITEM = 0;
private static final int TRANSFER_ITEM = 1;
private static final int FILE_ITEM = 2;
public void setStatus(TaskStatus pStatus){
status = pStatus;
}
/*
* (non-Javadoc)
*
* @see android.app.Activity#onPause()
*/
@Override
public void onPause() {
super.onPause();
// Try to update the details
Synodroid app = (Synodroid) getApplication();
app.pauseServer();
}
/*
* (non-Javadoc)
*
* @see android.app.Activity#onResume()
*/
@Override
public void onResume() {
super.onResume();
try{
if (((Synodroid)getApplication()).DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Resuming detail activity.");
}
catch (Exception ex){/*DO NOTHING*/}
// Check for fullscreen
SharedPreferences preferences = getSharedPreferences(PREFERENCE_GENERAL, Activity.MODE_PRIVATE);
if (preferences.getBoolean(PREFERENCE_FULLSCREEN, false)) {
// Set fullscreen or not
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
// Launch the gets task's details recurrent action
Synodroid app = (Synodroid) getApplication();
SynoServer server = app.getServer();
if (server != null){
if ((server.isUsingLocalConnection() && app.shouldUsePublicConnection()) || (!server.isUsingLocalConnection() && !app.shouldUsePublicConnection())){
server.disconnect();
finish();
}
else{
app.resumeServer();
}
}
else{
finish();
}
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getActivityHelper().setupSubActivity();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
SharedPreferences preferences = getSharedPreferences(PREFERENCE_GENERAL, Activity.MODE_PRIVATE);
if (preferences.getBoolean(PREFERENCE_FULLSCREEN, false)) {
// Set fullscreen or not
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
}
/**
* Return a sub detail list for the general's tab
*/
private List<Detail> buildTransferDetails(TaskDetail details) {
ArrayList<Detail> result = new ArrayList<Detail>();
// Set the result to be returned to the previous activity
Intent previous = new Intent();
previous.putExtra("com.bigpupdev.synodroid.ds.Details", details);
setResult(Activity.RESULT_OK, previous);
// ------------ Status
try {
result.add(new DetailText(getString(R.string.detail_status), TaskStatus.getLabel(this, details.status)));
} catch (NullPointerException e) {
result.add(new DetailText(getString(R.string.detail_status), getString(R.string.detail_unknown)));
} catch (IllegalArgumentException e) {
result.add(new DetailText(getString(R.string.detail_status), getString(R.string.detail_unknown)));
}
// ------------ Transfered
String transfered = getString(R.string.detail_progress_download) + " " + Utils.bytesToFileSize(details.bytesDownloaded, true, getString(R.string.detail_unknown));
if (details.isTorrent) {
String upload = getString(R.string.detail_progress_upload) + " " + Utils.bytesToFileSize(details.bytesUploaded, true, getString(R.string.detail_unknown)) + " (" + details.bytesRatio + " %)";
Detail2Text tr = new Detail2Text(getString(R.string.detail_transfered));
tr.setValue1(transfered);
tr.setValue2(upload);
result.add(tr);
} else {
result.add(new DetailText(getString(R.string.detail_transfered), transfered));
}
// ------------- Progress
long downloaded = details.bytesDownloaded;
long filesize = details.fileSize;
String downPerStr = getString(R.string.detail_unknown);
int downPer = 0;
if (filesize != -1) {
try {
downPer = (int) ((downloaded * 100) / filesize);
} catch (ArithmeticException e) {
downPer = 100;
}
if (downPer == 100 && downloaded != filesize){
downPer = 99;
}
downPerStr = "" + downPer + "%";
}
int upPerc = 0;
String upPercStr = getString(R.string.detail_unknown);
Integer uploadPercentage = Utils.computeUploadPercent(details);
if (uploadPercentage != null) {
upPerc = uploadPercentage.intValue();
upPercStr = "" + upPerc + "%";
}
// If it is a torrent
Detail proDetail = null;
if (details.isTorrent) {
Detail2Progress progDetail = new Detail2Progress(getString(R.string.detail_progress));
proDetail = progDetail;
progDetail.setProgress1(getString(R.string.detail_progress_download) + " " + downPerStr, downPer);
progDetail.setProgress2(getString(R.string.detail_progress_upload) + " " + upPercStr, upPerc);
} else {
DetailProgress progDetail = new DetailProgress(getString(R.string.detail_progress), R.layout.details_progress_template1);
proDetail = progDetail;
progDetail.setProgress(getString(R.string.detail_progress_download) + " " + downPerStr, downPer);
}
result.add(proDetail);
// ------------ Speed
String speed = getString(R.string.detail_progress_download) + " " + details.speedDownload + " " +details.speedDownUnit + "B/s";
if (details.isTorrent) {
speed = speed + " - " + getString(R.string.detail_progress_upload) + " " + details.speedUpload + " " +details.speedUpUnit + "B/s";
}
result.add(new DetailText(getString(R.string.detail_speed), speed));
// ------------ Peers
if (details.isTorrent) {
String peers = details.peersCurrent + " / " + details.peersTotal;
result.add(new DetailText(getString(R.string.detail_peers), peers));
}
// ------------ Seeders / Leechers
if (details.isTorrent) {
String seedStr = getString(R.string.detail_unvailable);
String leechStr = getString(R.string.detail_unvailable);
if (details.seeders != null)
seedStr = details.seeders.toString();
if (details.leechers != null)
leechStr = details.leechers.toString();
String seeders = seedStr + " - " + leechStr;
result.add(new DetailText(getString(R.string.detail_seeders_leechers), seeders));
}
// ------------ ETAs
String etaUpload = getString(R.string.detail_unknown);
String etaDownload = getString(R.string.detail_unknown);
if (details.speedDownload != 0) {
long sizeLeft = filesize - downloaded;
long timeLeft = (long) (sizeLeft / (details.speedDownload * 1000));
etaDownload = Utils.computeTimeLeft(timeLeft);
} else {
if (downPer == 100) {
etaDownload = getString(R.string.detail_finished);
}
}
Long timeLeftSize = null;
long uploaded = details.bytesUploaded;
double ratio = ((double) (details.seedingRatio)) / 100.0d;
if (details.speedUpload != 0 && details.seedingRatio != 0) {
long sizeLeft = (long) ((filesize * ratio) - uploaded);
timeLeftSize = (long) (sizeLeft / (details.speedUpload * 1000));
}
// If the user defined a minimum seeding time AND we are in seeding
// mode
TaskStatus tsk_status = details.getStatus();
Long timeLeftTime = null;
if (details.seedingInterval != 0 && tsk_status == TaskStatus.TASK_SEEDING) {
timeLeftTime = (details.seedingInterval * 60) - details.seedingElapsed;
if (timeLeftTime < 0) {
timeLeftTime = null;
}
}
// At least one time has been computed
if (timeLeftTime != null || timeLeftSize != null) {
// By default take the size time
Long time = timeLeftSize;
// Except if it is null
if (timeLeftSize == null) {
time = timeLeftTime;
} else {
// If time is not null
if (timeLeftTime != null) {
// Get the higher value
if (timeLeftTime > timeLeftSize) {
time = timeLeftTime;
}
}
}
etaUpload = Utils.computeTimeLeft(time);
} else if (upPerc == 100) {
etaUpload = getString(R.string.detail_finished);
}
// In case the user set the seedin time to forever
if (details.seedingInterval == -1) {
etaUpload = getString(R.string.detail_forever);
}
Detail etaDet = null;
// If it is a torrent then show the upload ETA
if (details.isTorrent) {
Detail2Text etaDetail = new Detail2Text(getString(R.string.detail_eta));
etaDet = etaDetail;
etaDetail.setValue1(getString(R.string.detail_progress_download) + " " + etaDownload);
etaDetail.setValue2(getString(R.string.detail_progress_upload) + " " + etaUpload);
}
// Otherwise only show the download ETA
else {
DetailText etaDetail = new DetailText(getString(R.string.detail_eta));
etaDet = etaDetail;
etaDetail.setValue(getString(R.string.detail_progress_download) + " " + etaDownload);
}
result.add(etaDet);
// ------------ Pieces
if (details.isTorrent) {
String pieces = details.piecesCurrent + " / " + details.piecesTotal;
DetailProgress piecesDetail = new DetailProgress(getString(R.string.detail_pieces), R.layout.details_progress_template2);
int piProgress = 0;
if (details.piecesTotal != 0) {
piProgress = (int) ((details.piecesCurrent * 100) / details.piecesTotal);
}
piecesDetail.setProgress(pieces, piProgress);
result.add(piecesDetail);
}
// Update seeding parameters
seedingRatio = details.seedingRatio;
seedingTime = details.seedingInterval;
return result;
}
/**
* Return a sub detail list for the general's tab
*/
private List<Detail> buildGeneralDetails(TaskDetail details) {
ArrayList<Detail> result = new ArrayList<Detail>();
// FileName
result.add(new DetailText(getString(R.string.detail_filename), details.fileName));
setTitle(details.fileName);
// Destination
DetailText destDetail = new DetailText(getString(R.string.detail_destination), details.destination);
result.add(destDetail);
// File size
result.add(new DetailText(getString(R.string.detail_filesize), Utils.bytesToFileSize(details.fileSize, true, getString(R.string.detail_unknown))));
// Creation time
result.add(new DetailText(getString(R.string.detail_creationtime), Utils.computeDate(details.creationDate)));
// URL
final String originalLink = details.url;
DetailText urlDetail = new DetailText(getString(R.string.detail_url), originalLink);
task.originalLink = originalLink;
if ((task.isTorrent || task.isNZB)) {
urlDetail.setAction(new DetailAction() {
public void execute(Detail detailsP) {
Synodroid app = (Synodroid) getApplication();
app.executeAsynchronousAction((DetailMain)mAdapter.getItem(MAIN_ITEM), new DownloadOriginalLinkAction(task), false);
}
});
}
result.add(urlDetail);
// Username
result.add(new DetailText(getString(R.string.detail_username), details.userName));
return result;
}
public void updateActionBarTitle(String title){
ActivityHelper ah = getActivityHelper();
if (ah != null) ah.setActionBarTitle(title, false);
}
public void menuHelperInvalidate(){
ActivityHelper ah = getActivityHelper();
if (ah != null) ah.invalidateOptionMenu();
}
/*
* (non-Javadoc)
*
* @see android.app.Activity#onPrepareDialog(int, android.app.Dialog)
*/
@Override
protected void onPrepareDialog(int id, Dialog dialog) {
final EditText seedRatio = (EditText) dialog.findViewById(R.id.seedingPercentage);
final Spinner seedTime = (Spinner) dialog.findViewById(R.id.seedingTime);
switch (id) {
// Prepare the task's parameters dialog
case TASK_PARAMETERS_DIALOG:
seedRatio.setText("" + seedingRatio);
// Try to find the right value
int pos = 0;
for (int iLoop = 0; iLoop < seedingTimes.length; iLoop++) {
if (seedingTimes[iLoop] == seedingTime) {
pos = iLoop;
break;
}
}
seedTime.setSelection(pos);
break;
case TASK_PROPERTIES_DIALOG:
final EditText ul_rateP = (EditText) dialog.findViewById(R.id.ul_rate);
final EditText dl_rateP = (EditText) dialog.findViewById(R.id.dl_rate);
final EditText max_peersP = (EditText) dialog.findViewById(R.id.max_peers);
final Spinner priorityP = (Spinner) dialog.findViewById(R.id.priority);
ul_rateP.setText("" + ul_rate);
dl_rateP.setText("" + dl_rate);
max_peersP.setText("" + max_peers);
seedRatio.setText("" + seedingRatio);
// Try to find the right value
int position = 0;
for (int iLoop = 0; iLoop < seedingTimes.length; iLoop++) {
if (seedingTimes[iLoop] == seedingTime) {
position = iLoop;
break;
}
}
seedTime.setSelection(position);
// Try to find the right value
position = 0;
for (int iLoop = 0; iLoop < priorities.length; iLoop++) {
if (priorities[iLoop] == priority) {
position = iLoop;
break;
}
}
priorityP.setSelection(position);
break;
}
}
/*
* (non-Javadoc)
*
* @see android.app.Activity#onCreateDialog(int)
*/
@Override
protected Dialog onCreateDialog(int id) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
switch (id) {
// Create the task's parameters dialog
case TASK_PARAMETERS_DIALOG:
// Create the view
View container = inflater.inflate(R.layout.seeding_parameters, null, false);
final EditText seedRatio = (EditText) container.findViewById(R.id.seedingPercentage);
final Spinner seedTime = (Spinner) container.findViewById(R.id.seedingTime);
// Create the dialog
builder.setTitle(getString(R.string.seeding_parameters_time));
builder.setView(container);
builder.setPositiveButton(getString(R.string.button_ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogP, int whichP) {
seedingChanged = true;
try {
int seedR = Integer.parseInt(seedRatio.getText().toString());
seedingRatio = seedR;
int pos = seedTime.getSelectedItemPosition();
seedingTime = seedingTimes[pos];
// At the end, update the task.
updateTask(true);
}
// The ratio is not an integer
catch (NumberFormatException ex) {
// NTD: the input method does not allow to set a float or
// a string
}
}
});
builder.setNegativeButton(getString(R.string.button_cancel), null);
return builder.create();
case TASK_PROPERTIES_DIALOG:
// Create the view
View containerP = inflater.inflate(R.layout.task_properties, null, false);
final EditText seedRatioP = (EditText) containerP.findViewById(R.id.seedingPercentage);
final EditText ul_rateP = (EditText) containerP.findViewById(R.id.ul_rate);
final EditText dl_rateP = (EditText) containerP.findViewById(R.id.dl_rate);
final EditText max_peersP = (EditText) containerP.findViewById(R.id.max_peers);
final Spinner priorityP = (Spinner) containerP.findViewById(R.id.priority);
final Spinner seedTimeP = (Spinner) containerP.findViewById(R.id.seedingTime);
// Create the dialog
builder.setTitle(getString(R.string.task_parameters));
builder.setView(containerP);
builder.setPositiveButton(getString(R.string.button_ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogP, int whichP) {
seedingChanged = true;
try {
ul_rate = Integer.parseInt(ul_rateP.getText().toString());
dl_rate = Integer.parseInt(dl_rateP.getText().toString());
max_peers = Integer.parseInt(max_peersP.getText().toString());
priority = priorities[priorityP.getSelectedItemPosition()];
int seedR = Integer.parseInt(seedRatioP.getText().toString());
seedingRatio = seedR;
int pos = seedTimeP.getSelectedItemPosition();
seedingTime = seedingTimes[pos];
// At the end, update the task.
updateTask(true);
}
// The ratio is not an integer
catch (NumberFormatException ex) {
// NTD: the input method does not allow to set a float or
// a string
}
}
});
builder.setNegativeButton(getString(R.string.button_cancel), null);
return builder.create();
default:
return null;
}
}
@SuppressWarnings("unchecked")
public void handleMessage(Message msgP) {
final Synodroid app = (Synodroid) getApplication();
final DetailMain main = (DetailMain) mAdapter.getItem(MAIN_ITEM);
DetailFiles files = (DetailFiles)mAdapter.getItem(FILE_ITEM);
try{
if (((Synodroid)getApplication()).DEBUG) Log.v(Synodroid.DS_TAG, "DetailActivity: Message received with ID = "+ msgP.what);
}catch (Exception ex){/*DO NOTHING*/}
switch (msgP.what) {
case ResponseHandler.MSG_DETAILS_FILES_RETRIEVED:
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Receive file listing message.");
}catch (Exception ex){/*DO NOTHING*/}
List<TaskFile> tfile = (List<TaskFile>) msgP.obj;
try{
files.fileAdapter.updateFiles(tfile);
} catch (Exception e) {
if (app.DEBUG) Log.e(Synodroid.DS_TAG, "DetailActivity: An error occured while trying to update files list:", e);
}
break;
case ResponseHandler.MSG_PROPERTIES_RECEIVED:
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Receive task properties message.");
}catch (Exception ex){/*DO NOTHING*/}
TaskProperties tp = (TaskProperties) msgP.obj;
ul_rate = tp.ul_rate;
dl_rate = tp.dl_rate;
max_peers = tp.max_peers;
priority = tp.priority;
seedingRatio = tp.seeding_ratio;
seedingTime = tp.seeding_interval;
destination = tp.destination;
try {
showDialog(TASK_PROPERTIES_DIALOG);
} catch (Exception e) {}
break;
case ResponseHandler.MSG_SHARED_DIRECTORIES_RETRIEVED:
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Received shared directory listing message.");
}catch (Exception ex){/*DO NOTHING*/}
AlertDialog.Builder builder = new AlertDialog.Builder(DetailActivity.this);
if (((Synodroid)getApplication()).getServer().getDsmVersion().greaterThen(DSMVersion.VERSION3_0)){
final SharedFolderSelection sf = (SharedFolderSelection) msgP.obj;
final String[] dirNames = new String[sf.childrens.size()];
final String[] dirIDs = new String[sf.childrens.size()];
for (int iLoop = 0; iLoop < sf.childrens.size(); iLoop++) {
Folder sharedDir = sf.childrens.get(iLoop);
dirNames[iLoop] = sharedDir.name;
dirIDs[iLoop] = sharedDir.id;
}
builder.setTitle(getString(R.string.shared_dir_title)+":\n"+sf.name);
builder.setItems(dirNames, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
dialog.dismiss();
app.executeAsynchronousAction(main, new GetDirectoryListShares(dirIDs[item]), true);
}
});
builder.setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
dialog.dismiss();
}
});
if (!sf.name.equals("/")){
builder.setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
dialog.dismiss();
app.executeAsynchronousAction(main, new SetShared(task, sf.name), true);
}
});
}
}
else{
List<SharedDirectory> newDirs = (List<SharedDirectory>) msgP.obj;
final String[] dirNames = new String[newDirs.size()];
int selected = -1;
for (int iLoop = 0; iLoop < newDirs.size(); iLoop++) {
SharedDirectory sharedDir = newDirs.get(iLoop);
dirNames[iLoop] = sharedDir.name;
if (sharedDir.isCurrent) {
selected = iLoop;
}
}
builder.setTitle(getString(R.string.shared_dir_title));
builder.setSingleChoiceItems(dirNames, selected, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
dialog.dismiss();
app.executeAsynchronousAction(main, new SetShared(task, dirNames[item]), true);
}
});
}
AlertDialog alert = builder.create();
try {
alert.show();
} catch (BadTokenException e) {
// Unable to show dialog probably because intent has been closed. Ignoring...
}
break;
// Details updated
case ResponseHandler.MSG_DETAILS_RETRIEVED:
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Receive task detail message.");
}catch (Exception ex){/*DO NOTHING*/}
TaskDetail details = (TaskDetail) msgP.obj;
if (!task.isTorrent && !task.isNZB && files != null){
files.updateEmptyValues(getString(R.string.empty_file_list_wrong_type), false);
}
if (!task.status.equals(details.status) && files != null && (task.isTorrent || task.isNZB)){
if (details != null && details.status != null && details.status.equals(TaskStatus.TASK_DOWNLOADING.name())) {
files.updateEmptyValues(getString(R.string.empty_list_loading), true);
app.executeAsynchronousAction(main, new GetFilesAction(task), false);
}
else{
files.updateEmptyValues(getString(R.string.empty_file_list), false);
files.resetList();
}
}
task.status = details.status;
task.isTorrent = details.isTorrent;
task.isNZB = details.isNZB;
if (main != null){
main.genAdapter.updateDetails(buildGeneralDetails(details));
((DetailTransfer)mAdapter.getItem(TRANSFER_ITEM)).transAdapter.updateDetails(buildTransferDetails(details));
}
getIntent().putExtra("com.bigpupdev.synodroid.ds.Details", task);
destination = details.destination;
setStatus(details.getStatus());
updateActionBarTitle(details.fileName);
menuHelperInvalidate();
break;
case ResponseHandler.MSG_ERROR:
try{
if (app.DEBUG) Log.w(Synodroid.DS_TAG,"DetailActivity: Receive error message.");
}catch (Exception ex){/*DO NOTHING*/}
SynoServer server = ((Synodroid) getApplication()).getServer();
if (server != null)
server.setLastError((String) msgP.obj);
android.view.View.OnClickListener ocl = new android.view.View.OnClickListener() {
@Override
public void onClick(View v) {
Crouton.cancelAllCroutons();
DetailActivity.this.finish();
}
};
Crouton.makeText(DetailActivity.this, server.getLastError()+ "\n\n" + getText(R.string.click_dismiss), Synodroid.CROUTON_ERROR).setOnClickListener(ocl).show();
break;
case ResponseHandler.MSG_ORIGINAL_FILE_RETRIEVED:
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Receive original file retreived message.");
}catch (Exception ex){/*DO NOTHING*/}
OriginalFile oriFile = (OriginalFile) msgP.obj;
File path = Environment.getExternalStorageDirectory();
path = new File(path, "download");
File file = new File(path, oriFile.fileName);
try {
// Make sure the Pictures directory exists.
path.mkdirs();
StringBuffer rawData = oriFile.rawData;
OutputStream os = new FileOutputStream(file);
os.write(rawData.toString().getBytes());
os.close();
Crouton.makeText(DetailActivity.this, getString(R.string.action_download_original_saved), Synodroid.CROUTON_INFO).show();
} catch (Exception e) {
// Unable to create file, likely because external storage is
// not currently mounted.
try{
if (((Synodroid)getApplication()).DEBUG) Log.w(Synodroid.DS_TAG, "Error writing " + file + " to SDCard.", e);
}catch (Exception ex){/*DO NOTHING*/}
Crouton.makeText(DetailActivity.this, getString(R.string.action_download_original_failed), Synodroid.CROUTON_ALERT).show();
}
break;
default:
try{
if (app.DEBUG) Log.w(Synodroid.DS_TAG, "DetailActivity: Ignored message ID = "+ msgP.what);
}catch (Exception ex){/*DO NOTHING*/}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!UIUtils.isHoneycomb()){
getMenuInflater().inflate(R.menu.refresh_menu_items, menu);
}
super.onCreateOptionsMenu(menu);
return true;
}
/**
* Create the option menu of this activity
*/
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
if (UIUtils.isHoneycomb()){
getMenuInflater().inflate(R.menu.refresh_menu_items, menu);
}
if (status != null) {
switch (status) {
case TASK_DOWNLOADING:
menu.add(0, MENU_PAUSE, 0, getString(R.string.action_pause)).setIcon(R.drawable.ic_menu_pause);
menu.add(0, MENU_DELETE, 0, getString(R.string.action_delete)).setIcon(android.R.drawable.ic_menu_delete);
break;
case TASK_PRE_SEEDING:
case TASK_SEEDING:
menu.add(0, MENU_PAUSE, 0, getString(R.string.action_pause)).setIcon(R.drawable.ic_menu_pause);
menu.add(0, MENU_CANCEL, 0, getString(R.string.action_cancel)).setIcon(android.R.drawable.ic_menu_close_clear_cancel);
break;
case TASK_PAUSED:
menu.add(0, MENU_RESUME, 0, getString(R.string.action_resume)).setIcon(android.R.drawable.ic_menu_revert);
menu.add(0, MENU_DELETE, 0, getString(R.string.action_delete)).setIcon(android.R.drawable.ic_menu_delete);
break;
case TASK_UNKNOWN:
case TASK_ERROR:
case TASK_ERROR_DEST_NO_EXIST:
case TASK_ERROR_DEST_DENY:
case TASK_ERROR_QUOTA_REACHED:
case TASK_ERROR_TIMEOUT:
case TASK_ERROR_EXCEED_MAX_FS_SIZE:
case TASK_ERROR_BROKEN_LINK:
case TASK_ERROR_DISK_FULL:
case TASK_ERROR_EXCEED_MAX_TEMP_FS_SIZE:
case TASK_ERROR_EXCEED_MAX_DEST_FS_SIZE:
case TASK_ERROR_TORRENT_DUPLICATE:
case TASK_ERROR_NAME_TOO_LONG_ENCRYPTION:
case TASK_ERROR_NAME_TOO_LONG:
case TASK_ERROR_FILE_NO_EXIST:
case TASK_ERROR_REQUIRED_PREMIUM:
case TASK_ERROR_NOT_SUPPORT_TYPE:
case TASK_ERROR_FTP_ENCRYPTION_NOT_SUPPORT_TYPE:
case TASK_ERROR_EXTRACT_FAIL:
case TASK_ERROR_EXTRACT_WRONG_PASSWORD:
case TASK_ERROR_EXTRACT_INVALID_ARCHIVE:
case TASK_ERROR_EXTRACT_QUOTA_REACHED:
case TASK_ERROR_EXTRACT_DISK_FULL:
case TASK_ERROR_REQUIRED_ACCOUNT:
case TASK_ERROR_TORRENT_INVALID:
menu.add(0, MENU_RETRY, 0, getString(R.string.action_retry)).setIcon(android.R.drawable.ic_menu_revert);
menu.add(0, MENU_DELETE, 0, getString(R.string.action_delete)).setIcon(android.R.drawable.ic_menu_delete);
break;
case TASK_FINISHED:
menu.add(0, MENU_RESUME, 0, getString(R.string.action_resume)).setIcon(android.R.drawable.ic_menu_revert);
case TASK_FINISHING:
menu.add(0, MENU_CLEAR, 0, getString(R.string.action_clear)).setIcon(android.R.drawable.ic_menu_close_clear_cancel);
break;
case TASK_FILEHOSTING_WAITING:
case TASK_EXTRACTING:
case TASK_HASH_CHECKING:
case TASK_WAITING:
menu.add(0, MENU_PAUSE, 0, getString(R.string.action_pause)).setIcon(R.drawable.ic_menu_pause);
menu.add(0, MENU_DELETE, 0, getString(R.string.action_delete)).setIcon(android.R.drawable.ic_menu_delete);
break;
}
}
if (task.originalLink != null && (task.originalLink.toLowerCase().startsWith("http://") || task.originalLink.toLowerCase().startsWith("https://") || task.originalLink.toLowerCase().startsWith("ftp://") || task.originalLink.toLowerCase().startsWith("magnet:"))){
menu.add(0, MENU_SHARE, 0, getString(R.string.share)).setIcon(android.R.drawable.ic_menu_share);
}
try{
if (((Synodroid)getApplication()).getServer().getDsmVersion().greaterThen(DSMVersion.VERSION3_0)){
menu.add(0, MENU_DESTINATION, 0, getString(R.string.menu_destination)).setIcon(android.R.drawable.ic_menu_upload).setEnabled(true);
}
}catch (NullPointerException e){/*No need to catch the exception*/}
if (task.isTorrent) {
if (task.getStatus() == TaskStatus.TASK_DOWNLOADING || task.getStatus() == TaskStatus.TASK_SEEDING) {
menu.add(0, MENU_PARAMETERS, 0, getString(R.string.task_parameters)).setIcon(android.R.drawable.ic_menu_preferences).setEnabled(true);
} else {
menu.add(0, MENU_PARAMETERS, 0, getString(R.string.task_parameters)).setIcon(android.R.drawable.ic_menu_preferences).setEnabled(false);
}
}
return super.onPrepareOptionsMenu(menu);
}
/**
* Interact with the user when a menu is selected
*/
public boolean onOptionsItemSelected(MenuItem item) {
Synodroid app = (Synodroid) getApplication();
DetailMain main = (DetailMain)mAdapter.getItem(MAIN_ITEM);
if (item.getItemId() == R.id.menu_refresh) {
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Menu refresh selected.");
}catch (Exception ex){/*DO NOTHING*/}
DetailFiles file = (DetailFiles)mAdapter.getItem(FILE_ITEM);
app.forceRefresh();
if (task.isTorrent){
app.executeAsynchronousAction(file, new GetFilesAction(task), false);
}
return true;
}
else if (item.getItemId() == MENU_SHARE){
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Menu share selected.");
}catch (Exception ex){/*DO NOTHING*/}
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, task.originalLink);
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, task.fileName);
startActivity(Intent.createChooser(intent, "Share url"));
return true;
}
else if (item.getItemId() == MENU_PAUSE){
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Menu pause selected.");
}catch (Exception ex){/*DO NOTHING*/}
app.executeAction(main, new PauseTaskAction(task), true);
return true;
}
else if (item.getItemId() == MENU_DELETE || item.getItemId() == MENU_CANCEL || item.getItemId() == MENU_CLEAR){
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Menu cancel/delete/clear selected.");
}catch (Exception ex){/*DO NOTHING*/}
app.executeAction(main, new DeleteTaskAction(task), true);
return true;
}
else if (item.getItemId() == MENU_RESUME || item.getItemId() == MENU_RETRY){
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Menu resume/retry selected.");
}catch (Exception ex){/*DO NOTHING*/}
app.executeAction(main, new ResumeTaskAction(task), true);
return true;
}
else if (item.getItemId() == MENU_PARAMETERS){
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Menu task properties selected.");
}catch (Exception ex){/*DO NOTHING*/}
try {
if (app.getServer().getDsmVersion().greaterThen(DSMVersion.VERSION3_0)) {
app.executeAsynchronousAction(main, new GetTaskPropertiesAction(task), false, false);
} else {
showDialog(TASK_PARAMETERS_DIALOG);
}
} catch (Exception e) {
try{
if (app.DEBUG) Log.e(Synodroid.DS_TAG,"DetailActivity: Failed to execute action on task properties. Ignoring...");
}catch (Exception ex){/*DO NOTHING*/}
}
return true;
}
else if (item.getItemId() == MENU_DESTINATION){
try{
if (app.DEBUG) Log.v(Synodroid.DS_TAG,"DetailActivity: Menu destination selected.");
}catch (Exception ex){/*DO NOTHING*/}
try {
if (app.getServer().getDsmVersion().greaterThen(DSMVersion.VERSION3_0)){
app.executeAsynchronousAction(main, new GetDirectoryListShares("remote/"+destination), false);
}
else{
app.executeAsynchronousAction(main, new EnumShareAction(), false);
}
} catch (NullPointerException e) {
try{
if (app.DEBUG) Log.e(Synodroid.DS_TAG,"DetailActivity: Failed to execute action on task destination. Ignoring...");
}catch (Exception ex){/*DO NOTHING*/}
}
return true;
}
return super.onOptionsItemSelected(item);
}
public void updateRefreshStatus(boolean refreshing) {
getActivityHelper().setRefreshActionButtonCompatState(refreshing);
}
@Override
public boolean onSearchRequested() {
return false;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
// ignore orientation change
super.onConfigurationChanged(newConfig);
}
/**
* Update the current task
*/
public void updateTask(boolean forceRefreshP) {
Synodroid app = (Synodroid) getApplication();
DetailMain main = (DetailMain)mAdapter.getItem(MAIN_ITEM);
SynoServer server = null;
try {
server = app.getServer();
} catch (Exception e) {
}
if (server != null) {
if (server.getDsmVersion().greaterThen(DSMVersion.VERSION3_0)) {
if (seedingChanged) {
UpdateTaskPropertiesAction update = new UpdateTaskPropertiesAction(task, ul_rate, dl_rate, priority, max_peers, destination, seedingRatio, seedingTime);
app.getServer().executeAsynchronousAction(main, update, forceRefreshP);
seedingChanged = false;
}
}
}
}
public static class MyAdapter extends FragmentPagerAdapter implements ViewPagerIndicator.PageInfoProvider{
int mItemsNum;
private DetailActivity mCurActivity;
private DetailMain main;
private DetailFiles files;
private DetailTransfer transfer;
private boolean debug = false;
public MyAdapter(FragmentManager pFm, int pItemNum, DetailActivity pCurActivity, boolean p_debug) {
super(pFm);
mItemsNum = pItemNum;
mCurActivity = pCurActivity;
debug = p_debug;
}
/**
* This override prevents the pager to destroy non adjacent pages.
*/
@Override
public void destroyItem(View container, int position, Object object){
try{
if (debug) Log.v(Synodroid.DS_TAG, "DetailActivity: View pager attemps to destroy pager number: "+position);
}catch (Exception ex){/*DO NOTHING*/}
}
@Override
public int getCount() {
return mItemsNum;
}
@Override
public Fragment getItem(int position) {
if (position == 0){
if (main == null)
main = new DetailMain();
return main;
}
else if (position == 1){
if (transfer == null)
transfer = new DetailTransfer();
return transfer;
}
else{
if (files == null)
files = new DetailFiles();
return files;
}
}
public String getTitle(int pos){
if (pos == 0)
return mCurActivity.getString(R.string.tab_main);
else if (pos == 1)
return mCurActivity.getString(R.string.tab_transfer);
else
return mCurActivity.getString(R.string.tab_file);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!EulaHelper.hasAcceptedEula(this)) {
EulaHelper.showEula(false, this);
}
setContentView(R.layout.activity_detail);
Intent intent = getIntent();
task = (Task) intent.getSerializableExtra("com.bigpupdev.synodroid.ds.Details");
mAdapter = new MyAdapter(getSupportFragmentManager(), 3, this, ((Synodroid)getApplication()).DEBUG);
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setOffscreenPageLimit(2);
mPager.setAdapter(mAdapter);
// Find the indicator from the layout
mIndicator = (ViewPagerIndicator)findViewById(R.id.indicator);
// Set the indicator as the pageChangeListener
mPager.setOnPageChangeListener(mIndicator);
// Initialize the indicator. We need some information here:
// * What page do we start on.
// * How many pages are there in total
// * A callback to get page titles
mIndicator.init(0, mAdapter.getCount(), mAdapter);
mIndicator.setFocusedTextColor(new int[]{255, 255, 255});
mIndicator.setUnfocusedTextColor(new int[]{90, 90, 90});
mIndicator.setOnClickListener(new OnIndicatorClickListener());
// Create the seeding time int array
String[] timesArray = getResources().getStringArray(R.array.seeding_time_array_values);
seedingTimes = new int[timesArray.length];
for (int iLoop = 0; iLoop < timesArray.length; iLoop++) {
seedingTimes[iLoop] = Integer.parseInt(timesArray[iLoop]);
}
String[] priorityArray = getResources().getStringArray(R.array.priority_array_value);
priorities = new int[priorityArray.length];
for (int iLoop = 0; iLoop < priorityArray.length; iLoop++) {
priorities[iLoop] = Integer.parseInt(priorityArray[iLoop]);
}
getActivityHelper().setupActionBar(task.fileName, false, null);
}
class OnIndicatorClickListener implements ViewPagerIndicator.OnClickListener{
public void onCurrentClicked(View v) {}
public void onNextClicked(View v) {
mPager.setCurrentItem(Math.min(mAdapter.getCount() - 1, mIndicator.getCurrentPosition() + 1));
}
public void onPreviousClicked(View v) {
mPager.setCurrentItem(Math.max(0, mIndicator.getCurrentPosition() - 1));
}
}
}