You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
401 lines
17 KiB
401 lines
17 KiB
/* |
|
* Copyright 2010-2018 Eric Kok et al. |
|
* |
|
* Transdroid is free software: you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation, either version 3 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* Transdroid is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with Transdroid. If not, see <http://www.gnu.org/licenses/>. |
|
*/ |
|
package org.transdroid.core.gui; |
|
|
|
import android.annotation.TargetApi; |
|
import android.content.Intent; |
|
import android.os.Build; |
|
import android.os.Bundle; |
|
|
|
import androidx.appcompat.app.AppCompatActivity; |
|
import androidx.appcompat.widget.Toolbar; |
|
|
|
import com.nispok.snackbar.Snackbar; |
|
import com.nispok.snackbar.SnackbarManager; |
|
|
|
import org.androidannotations.annotations.AfterViews; |
|
import org.androidannotations.annotations.Background; |
|
import org.androidannotations.annotations.Bean; |
|
import org.androidannotations.annotations.EActivity; |
|
import org.androidannotations.annotations.Extra; |
|
import org.androidannotations.annotations.FragmentById; |
|
import org.androidannotations.annotations.InstanceState; |
|
import org.androidannotations.annotations.OptionsItem; |
|
import org.androidannotations.annotations.OptionsMenu; |
|
import org.androidannotations.annotations.UiThread; |
|
import org.androidannotations.annotations.ViewById; |
|
import org.transdroid.R; |
|
import org.transdroid.core.app.settings.ApplicationSettings; |
|
import org.transdroid.core.app.settings.ServerSetting; |
|
import org.transdroid.core.app.settings.SettingsUtils; |
|
import org.transdroid.core.gui.lists.LocalTorrent; |
|
import org.transdroid.core.gui.log.Log; |
|
import org.transdroid.core.gui.navigation.Label; |
|
import org.transdroid.core.gui.navigation.NavigationHelper; |
|
import org.transdroid.core.gui.navigation.RefreshableActivity; |
|
import org.transdroid.core.service.ConnectivityHelper; |
|
import org.transdroid.daemon.Daemon; |
|
import org.transdroid.daemon.IDaemonAdapter; |
|
import org.transdroid.daemon.Priority; |
|
import org.transdroid.daemon.Torrent; |
|
import org.transdroid.daemon.TorrentDetails; |
|
import org.transdroid.daemon.TorrentFile; |
|
import org.transdroid.daemon.task.DaemonTaskFailureResult; |
|
import org.transdroid.daemon.task.DaemonTaskResult; |
|
import org.transdroid.daemon.task.DaemonTaskSuccessResult; |
|
import org.transdroid.daemon.task.ToggleSequentialDownloadTask; |
|
import org.transdroid.daemon.task.ToggleFirstLastPieceDownloadTask; |
|
import org.transdroid.daemon.task.ForceRecheckTask; |
|
import org.transdroid.daemon.task.GetFileListTask; |
|
import org.transdroid.daemon.task.GetFileListTaskSuccessResult; |
|
import org.transdroid.daemon.task.GetTorrentDetailsTask; |
|
import org.transdroid.daemon.task.GetTorrentDetailsTaskSuccessResult; |
|
import org.transdroid.daemon.task.PauseTask; |
|
import org.transdroid.daemon.task.RemoveTask; |
|
import org.transdroid.daemon.task.ResumeTask; |
|
import org.transdroid.daemon.task.RetrieveTask; |
|
import org.transdroid.daemon.task.RetrieveTaskSuccessResult; |
|
import org.transdroid.daemon.task.SetDownloadLocationTask; |
|
import org.transdroid.daemon.task.SetFilePriorityTask; |
|
import org.transdroid.daemon.task.SetLabelTask; |
|
import org.transdroid.daemon.task.SetTrackersTask; |
|
import org.transdroid.daemon.task.StartTask; |
|
import org.transdroid.daemon.task.StopTask; |
|
|
|
import java.util.ArrayList; |
|
import java.util.List; |
|
|
|
/** |
|
* An activity that holds a single torrents details fragment. It is used on devices (i.e. phones) where there is no room to show details in the {@link |
|
* TorrentsActivity} directly. Task execution, such as loading of more details and updating file priorities, is performed in this activity via |
|
* background methods. |
|
* |
|
* @author Eric Kok |
|
*/ |
|
@EActivity(R.layout.activity_details) |
|
@OptionsMenu(R.menu.activity_details) |
|
public class DetailsActivity extends AppCompatActivity implements TorrentTasksExecutor, RefreshableActivity { |
|
|
|
@Extra |
|
@InstanceState |
|
protected Torrent torrent; |
|
@Extra |
|
@InstanceState |
|
protected ArrayList<Label> currentLabels; |
|
|
|
// Settings |
|
@Bean |
|
protected Log log; |
|
@Bean |
|
protected NavigationHelper navigationHelper; |
|
@Bean |
|
protected ConnectivityHelper connectivityHelper; |
|
@Bean |
|
protected ApplicationSettings applicationSettings; |
|
private IDaemonAdapter currentConnection = null; |
|
|
|
// Details view components |
|
@ViewById |
|
protected Toolbar selectionToolbar; |
|
@FragmentById(R.id.torrentdetails_fragment) |
|
protected DetailsFragment fragmentDetails; |
|
|
|
@Override |
|
public void onCreate(Bundle savedInstanceState) { |
|
SettingsUtils.applyDayNightTheme(this); |
|
super.onCreate(savedInstanceState); |
|
} |
|
|
|
@AfterViews |
|
protected void init() { |
|
|
|
// We require a torrent to be specified; otherwise close the activity |
|
if (torrent == null) { |
|
finish(); |
|
return; |
|
} |
|
|
|
// Simple action bar with up, torrent name as title and refresh button |
|
setSupportActionBar(selectionToolbar); |
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true); |
|
getSupportActionBar().setTitle(NavigationHelper.buildCondensedFontString(torrent.getName())); |
|
|
|
// Connect to the last used server |
|
ServerSetting lastUsed = applicationSettings.getLastUsedServer(); |
|
fragmentDetails.setCurrentServerSettings(lastUsed); |
|
currentConnection = lastUsed.createServerAdapter(connectivityHelper.getConnectedNetworkName(), this); |
|
|
|
// Show details and load fine stats and torrent files |
|
fragmentDetails.updateTorrent(torrent); |
|
fragmentDetails.updateLabels(currentLabels); |
|
|
|
} |
|
|
|
@TargetApi(Build.VERSION_CODES.HONEYCOMB) |
|
@OptionsItem(android.R.id.home) |
|
protected void navigateUp() { |
|
TorrentsActivity_.intent(this).flags(Intent.FLAG_ACTIVITY_CLEAR_TOP).start(); |
|
} |
|
|
|
@OptionsItem(R.id.action_refresh) |
|
public void refreshScreen() { |
|
fragmentDetails.updateIsLoading(true, null); |
|
refreshTorrent(); |
|
refreshTorrentDetails(torrent); |
|
refreshTorrentFiles(torrent); |
|
} |
|
|
|
@Background |
|
protected void refreshTorrent() { |
|
DaemonTaskResult result = RetrieveTask.create(currentConnection).execute(log); |
|
if (result instanceof RetrieveTaskSuccessResult) { |
|
onTorrentsRetrieved(((RetrieveTaskSuccessResult) result).getTorrents(), ((RetrieveTaskSuccessResult) result).getLabels()); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, true); |
|
} |
|
} |
|
|
|
@Background |
|
public void refreshTorrentDetails(Torrent torrent) { |
|
if (currentConnection == null) return; |
|
if (!Daemon.supportsFineDetails(torrent.getDaemon())) { |
|
return; |
|
} |
|
DaemonTaskResult result = GetTorrentDetailsTask.create(currentConnection, torrent).execute(log); |
|
if (result instanceof GetTorrentDetailsTaskSuccessResult) { |
|
onTorrentDetailsRetrieved(torrent, ((GetTorrentDetailsTaskSuccessResult) result).getTorrentDetails()); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
public void refreshTorrentFiles(Torrent torrent) { |
|
if (currentConnection == null) return; |
|
if (!Daemon.supportsFileListing(torrent.getDaemon())) { |
|
return; |
|
} |
|
DaemonTaskResult result = GetFileListTask.create(currentConnection, torrent).execute(log); |
|
if (result instanceof GetFileListTaskSuccessResult) { |
|
onTorrentFilesRetrieved(torrent, ((GetFileListTaskSuccessResult) result).getFiles()); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void resumeTorrent(Torrent torrent) { |
|
if (currentConnection == null) return; |
|
torrent.mimicResume(); |
|
DaemonTaskResult result = ResumeTask.create(currentConnection, torrent).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
onTaskSucceeded((DaemonTaskSuccessResult) result, getString(R.string.result_resumed, torrent.getName())); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void pauseTorrent(Torrent torrent) { |
|
torrent.mimicPause(); |
|
DaemonTaskResult result = PauseTask.create(currentConnection, torrent).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
onTaskSucceeded((DaemonTaskSuccessResult) result, getString(R.string.result_paused, torrent.getName())); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void startTorrent(Torrent torrent, boolean forced) { |
|
torrent.mimicStart(); |
|
DaemonTaskResult result = StartTask.create(currentConnection, torrent, forced).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
onTaskSucceeded((DaemonTaskSuccessResult) result, getString(R.string.result_started, torrent.getName())); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void stopTorrent(Torrent torrent) { |
|
torrent.mimicStop(); |
|
DaemonTaskResult result = StopTask.create(currentConnection, torrent).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
onTaskSucceeded((DaemonTaskSuccessResult) result, getString(R.string.result_stopped, torrent.getName())); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void removeTorrent(Torrent torrent, boolean withData) { |
|
DaemonTaskResult result = RemoveTask.create(currentConnection, torrent, withData).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
// Close the details activity (as the torrent is now removed) |
|
closeActivity(getString(withData ? R.string.result_removed_with_data : R.string.result_removed, torrent.getName())); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@UiThread |
|
protected void closeActivity(String closeText) { |
|
setResult(RESULT_OK, new Intent().putExtra("torrent_removed", true).putExtra("affected_torrent", torrent)); |
|
finish(); |
|
if (closeText != null) { |
|
SnackbarManager.show(Snackbar.with(this).text(closeText)); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void updateLabel(Torrent torrent, String newLabel) { |
|
torrent.mimicNewLabel(newLabel); |
|
DaemonTaskResult result = SetLabelTask.create(currentConnection, torrent, newLabel == null ? "" : newLabel).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
onTaskSucceeded((DaemonTaskSuccessResult) result, getString(R.string.result_labelset, newLabel)); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void toggleSequentialDownload(Torrent torrent, boolean sequentialState) { |
|
torrent.mimicSequentialDownload(sequentialState); |
|
String onState = getString(R.string.result_togglesequential_onstate); |
|
String offState = getString(R.string.result_togglesequential_offstate); |
|
String stateString = sequentialState ? onState : offState; |
|
DaemonTaskResult result = ToggleSequentialDownloadTask.create(currentConnection, torrent).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
onTaskSucceeded((DaemonTaskSuccessResult) result, getString(R.string.result_togglesequential, torrent.getName(), stateString)); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void toggleFirstLastPieceDownload(Torrent torrent, boolean firstLastPieceState) { |
|
torrent.mimicFirstLastPieceDownload(firstLastPieceState); |
|
String onState = getString(R.string.result_togglefirstlastpiece_onstate); |
|
String offState = getString(R.string.result_togglefirstlastpiece_offstate); |
|
String stateString = firstLastPieceState ? onState : offState; |
|
DaemonTaskResult result = ToggleFirstLastPieceDownloadTask.create(currentConnection, torrent).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
onTaskSucceeded((DaemonTaskSuccessResult) result, getString(R.string.result_togglefirstlastpiece, torrent.getName(), stateString)); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void forceRecheckTorrent(Torrent torrent) { |
|
torrent.mimicCheckingStatus(); |
|
DaemonTaskResult result = ForceRecheckTask.create(currentConnection, torrent).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
onTaskSucceeded((DaemonTaskSuccessResult) result, getString(R.string.result_recheckedstarted, torrent.getName())); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void updateTrackers(Torrent torrent, List<String> newTrackers) { |
|
DaemonTaskResult result = SetTrackersTask.create(currentConnection, torrent, newTrackers).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
onTaskSucceeded((DaemonTaskSuccessResult) result, getString(R.string.result_trackersupdated)); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void updateLocation(Torrent torrent, String newLocation) { |
|
DaemonTaskResult result = SetDownloadLocationTask.create(currentConnection, torrent, newLocation).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
onTaskSucceeded((DaemonTaskSuccessResult) result, getString(R.string.result_locationset, newLocation)); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@Background |
|
@Override |
|
public void updatePriority(Torrent torrent, List<TorrentFile> files, Priority priority) { |
|
DaemonTaskResult result = SetFilePriorityTask.create(currentConnection, torrent, priority, new ArrayList<>(files)).execute(log); |
|
if (result instanceof DaemonTaskSuccessResult) { |
|
onTaskSucceeded((DaemonTaskSuccessResult) result, getString(R.string.result_priotitiesset)); |
|
} else { |
|
onCommunicationError((DaemonTaskFailureResult) result, false); |
|
} |
|
} |
|
|
|
@UiThread |
|
protected void onTaskSucceeded(DaemonTaskSuccessResult result, String successMessage) { |
|
// Set the activity result so the calling activity knows it needs to update its view |
|
setResult(RESULT_OK, new Intent().putExtra("torrent_updated", true).putExtra("affected_torrent", torrent)); |
|
// Refresh the screen as well |
|
refreshTorrent(); |
|
refreshTorrentDetails(torrent); |
|
SnackbarManager.show(Snackbar.with(this).text(successMessage).duration(Snackbar.SnackbarDuration.LENGTH_SHORT)); |
|
} |
|
|
|
@UiThread |
|
protected void onTorrentDetailsRetrieved(Torrent torrent, TorrentDetails torrentDetails) { |
|
// Update the details fragment with the new fine details for the shown torrent |
|
if (fragmentDetails.isResumed()) |
|
fragmentDetails.updateTorrentDetails(torrent, torrentDetails); |
|
} |
|
|
|
@UiThread |
|
protected void onTorrentFilesRetrieved(Torrent torrent, List<TorrentFile> torrentFiles) { |
|
// Update the details fragment with the newly retrieved list of files |
|
if (fragmentDetails.isResumed()) |
|
fragmentDetails.updateTorrentFiles(torrent, new ArrayList<>(torrentFiles)); |
|
} |
|
|
|
@UiThread |
|
protected void onCommunicationError(DaemonTaskFailureResult result, boolean isCritical) { |
|
log.i(this, result.getException().toString()); |
|
String error = getString(LocalTorrent.getResourceForDaemonException(result.getException())); |
|
if (fragmentDetails.isResumed()) |
|
fragmentDetails.updateIsLoading(false, isCritical ? error : null); |
|
SnackbarManager.show(Snackbar.with(this).text(getString(LocalTorrent.getResourceForDaemonException(result.getException()))) |
|
.colorResource(R.color.red)); |
|
} |
|
|
|
@UiThread |
|
protected void onTorrentsRetrieved(List<Torrent> torrents, List<org.transdroid.daemon.Label> labels) { |
|
// Update the details fragment accordingly |
|
if (fragmentDetails.isResumed()) { |
|
fragmentDetails.updateIsLoading(false, null); |
|
fragmentDetails.perhapsUpdateTorrent(torrents); |
|
fragmentDetails.updateLabels(Label.convertToNavigationLabels(labels, getResources().getString(R.string.labels_unlabeled))); |
|
} |
|
} |
|
|
|
}
|
|
|