Browse Source

Merge branch 'dev'

pull/506/head
Eric Kok 6 years ago
parent
commit
133aa177a0
  1. 20
      app/build.gradle
  2. 1
      app/proguard-rules.pro
  3. 4
      app/src/lite/res/values/strings.xml
  4. 5
      app/src/main/AndroidManifest.xml
  5. 11
      app/src/main/java/org/transdroid/core/gui/DetailsActivity.java
  6. 4
      app/src/main/java/org/transdroid/core/gui/DetailsFragment.java
  7. 18
      app/src/main/java/org/transdroid/core/gui/TorrentsActivity.java
  8. 17
      app/src/main/java/org/transdroid/core/gui/TorrentsFragment.java
  9. 5
      app/src/main/java/org/transdroid/core/gui/lists/LocalTorrent.java
  10. 48
      app/src/main/java/org/transdroid/core/gui/lists/SortByListItem.java
  11. 2
      app/src/main/java/org/transdroid/core/gui/log/DatabaseHelper.java
  12. 47
      app/src/main/java/org/transdroid/core/gui/settings/InterceptableEditTextPreference.java
  13. 7
      app/src/main/java/org/transdroid/core/gui/settings/MainSettingsActivity.java
  14. 30
      app/src/main/java/org/transdroid/core/gui/settings/ServerSettingsActivity.java
  15. 48
      app/src/main/java/org/transdroid/core/service/ConnectivityHelper.java
  16. 2
      app/src/main/java/org/transdroid/daemon/DummyAdapter.java
  17. 5
      app/src/main/java/org/transdroid/daemon/Rtorrent/RtorrentAdapter.java
  18. 6
      app/src/main/res/values/changelog.xml
  19. 6
      app/src/main/res/values/strings.xml
  20. 5
      app/src/main/res/xml/pref_server.xml
  21. 6
      build.gradle
  22. 3
      gradle.properties
  23. 2
      gradle/wrapper/gradle-wrapper.properties

20
app/build.gradle

@ -8,8 +8,8 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 15 minSdkVersion 15
targetSdkVersion 28 targetSdkVersion 28
versionCode 234 versionCode 235
versionName '2.5.14' versionName '2.5.15'
javaCompileOptions { javaCompileOptions {
annotationProcessorOptions { annotationProcessorOptions {
@ -36,9 +36,14 @@ android {
} }
} }
buildTypes { buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
release { release {
signingConfig signingConfigs.releaseConfig signingConfig signingConfigs.releaseConfig
minifyEnabled false minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
flavorDimensions "version" flavorDimensions "version"
@ -60,12 +65,13 @@ android {
} }
dependencies { dependencies {
implementation 'org.androidannotations:androidannotations-api:4.5.2' implementation 'org.androidannotations:androidannotations-api:4.6.0'
implementation 'org.androidannotations:ormlite-api:4.5.2' implementation 'org.androidannotations:ormlite-api:4.6.0'
implementation 'com.j256.ormlite:ormlite-core:4.48' implementation 'com.j256.ormlite:ormlite-core:4.48'
implementation 'com.j256.ormlite:ormlite-android:4.48' implementation 'com.j256.ormlite:ormlite-android:4.48'
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.android.support:support-annotations:28.0.0' implementation 'com.android.support:support-annotations:28.0.0'
implementation 'com.getbase:floatingactionbutton:1.10.1' implementation 'com.getbase:floatingactionbutton:1.10.1'
implementation 'com.nispok:snackbar:2.11.0' implementation 'com.nispok:snackbar:2.11.0'
@ -74,7 +80,7 @@ dependencies {
transitive = true transitive = true
} }
implementation 'com.evernote:android-job:1.2.6' implementation 'com.evernote:android-job:1.2.6'
annotationProcessor 'org.androidannotations:androidannotations:4.5.2' annotationProcessor 'org.androidannotations:androidannotations:4.6.0'
annotationProcessor 'org.androidannotations:ormlite:4.5.2' annotationProcessor 'org.androidannotations:ormlite:4.6.0'
} }

1
app/proguard-rules.pro vendored

@ -0,0 +1 @@
-dontobfuscate

4
app/src/lite/res/values/strings.xml

@ -18,7 +18,7 @@
<string name="app_name" translatable="false">Transdrone</string> <string name="app_name" translatable="false">Transdrone</string>
<string name="donate_text">Donate via transdroid.org</string> <string name="donate_text"></string>
<string name="donate_url">https://transdroid.org</string> <string name="donate_url"></string>
</resources> </resources>

5
app/src/main/AndroidManifest.xml

@ -29,10 +29,15 @@
android:xlargeScreens="true" /> android:xlargeScreens="true" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<!-- To check for an active connection -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- To check currently connected wifi network name -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- To start rss and torrents background check services -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<!-- To export settings file to external storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature <uses-feature

11
app/src/main/java/org/transdroid/core/gui/DetailsActivity.java

@ -170,6 +170,7 @@ public class DetailsActivity extends AppCompatActivity implements TorrentTasksEx
@Background @Background
public void refreshTorrentDetails(Torrent torrent) { public void refreshTorrentDetails(Torrent torrent) {
if (currentConnection == null) return;
if (!Daemon.supportsFineDetails(torrent.getDaemon())) { if (!Daemon.supportsFineDetails(torrent.getDaemon())) {
return; return;
} }
@ -183,6 +184,7 @@ public class DetailsActivity extends AppCompatActivity implements TorrentTasksEx
@Background @Background
public void refreshTorrentFiles(Torrent torrent) { public void refreshTorrentFiles(Torrent torrent) {
if (currentConnection == null) return;
if (!Daemon.supportsFileListing(torrent.getDaemon())) { if (!Daemon.supportsFileListing(torrent.getDaemon())) {
return; return;
} }
@ -197,6 +199,7 @@ public class DetailsActivity extends AppCompatActivity implements TorrentTasksEx
@Background @Background
@Override @Override
public void resumeTorrent(Torrent torrent) { public void resumeTorrent(Torrent torrent) {
if (currentConnection == null) return;
torrent.mimicResume(); torrent.mimicResume();
DaemonTaskResult result = ResumeTask.create(currentConnection, torrent).execute(log); DaemonTaskResult result = ResumeTask.create(currentConnection, torrent).execute(log);
if (result instanceof DaemonTaskSuccessResult) { if (result instanceof DaemonTaskSuccessResult) {
@ -333,14 +336,14 @@ public class DetailsActivity extends AppCompatActivity implements TorrentTasksEx
@UiThread @UiThread
protected void onTorrentDetailsRetrieved(Torrent torrent, TorrentDetails torrentDetails) { protected void onTorrentDetailsRetrieved(Torrent torrent, TorrentDetails torrentDetails) {
// Update the details fragment with the new fine details for the shown torrent // Update the details fragment with the new fine details for the shown torrent
if (fragmentDetails.isAdded()) if (fragmentDetails.isResumed())
fragmentDetails.updateTorrentDetails(torrent, torrentDetails); fragmentDetails.updateTorrentDetails(torrent, torrentDetails);
} }
@UiThread @UiThread
protected void onTorrentFilesRetrieved(Torrent torrent, List<TorrentFile> torrentFiles) { protected void onTorrentFilesRetrieved(Torrent torrent, List<TorrentFile> torrentFiles) {
// Update the details fragment with the newly retrieved list of files // Update the details fragment with the newly retrieved list of files
if (fragmentDetails.isAdded()) if (fragmentDetails.isResumed())
fragmentDetails.updateTorrentFiles(torrent, new ArrayList<>(torrentFiles)); fragmentDetails.updateTorrentFiles(torrent, new ArrayList<>(torrentFiles));
} }
@ -348,7 +351,7 @@ public class DetailsActivity extends AppCompatActivity implements TorrentTasksEx
protected void onCommunicationError(DaemonTaskFailureResult result, boolean isCritical) { protected void onCommunicationError(DaemonTaskFailureResult result, boolean isCritical) {
log.i(this, result.getException().toString()); log.i(this, result.getException().toString());
String error = getString(LocalTorrent.getResourceForDaemonException(result.getException())); String error = getString(LocalTorrent.getResourceForDaemonException(result.getException()));
if (fragmentDetails.isAdded()) if (fragmentDetails.isResumed())
fragmentDetails.updateIsLoading(false, isCritical ? error : null); fragmentDetails.updateIsLoading(false, isCritical ? error : null);
SnackbarManager.show(Snackbar.with(this).text(getString(LocalTorrent.getResourceForDaemonException(result.getException()))) SnackbarManager.show(Snackbar.with(this).text(getString(LocalTorrent.getResourceForDaemonException(result.getException())))
.colorResource(R.color.red)); .colorResource(R.color.red));
@ -357,7 +360,7 @@ public class DetailsActivity extends AppCompatActivity implements TorrentTasksEx
@UiThread @UiThread
protected void onTorrentsRetrieved(List<Torrent> torrents, List<org.transdroid.daemon.Label> labels) { protected void onTorrentsRetrieved(List<Torrent> torrents, List<org.transdroid.daemon.Label> labels) {
// Update the details fragment accordingly // Update the details fragment accordingly
if (fragmentDetails.isAdded()) { if (fragmentDetails.isResumed()) {
fragmentDetails.updateIsLoading(false, null); fragmentDetails.updateIsLoading(false, null);
fragmentDetails.perhapsUpdateTorrent(torrents); fragmentDetails.perhapsUpdateTorrent(torrents);
fragmentDetails.updateLabels(Label.convertToNavigationLabels(labels, getResources().getString(R.string.labels_unlabeled))); fragmentDetails.updateLabels(Label.convertToNavigationLabels(labels, getResources().getString(R.string.labels_unlabeled)));

4
app/src/main/java/org/transdroid/core/gui/DetailsFragment.java

@ -150,10 +150,10 @@ public class DetailsFragment extends Fragment implements OnTrackersUpdatedListen
if (torrent != null) { if (torrent != null) {
updateTorrent(torrent); updateTorrent(torrent);
} }
if (torrentDetails != null) { if (torrent != null && torrentDetails != null) {
updateTorrentDetails(torrent, torrentDetails); updateTorrentDetails(torrent, torrentDetails);
} }
if (torrentFiles != null) { if (torrent != null && torrentFiles != null) {
updateTorrentFiles(torrent, torrentFiles); updateTorrentFiles(torrent, torrentFiles);
} }

18
app/src/main/java/org/transdroid/core/gui/TorrentsActivity.java

@ -566,7 +566,7 @@ public class TorrentsActivity extends AppCompatActivity implements TorrentTasksE
// Clear the currently shown list of torrents and perhaps the details // Clear the currently shown list of torrents and perhaps the details
fragmentTorrents.clear(true, true); fragmentTorrents.clear(true, true);
if (fragmentDetails != null && fragmentDetails.isAdded() && fragmentDetails.getActivity() != null) { if (fragmentDetails != null && fragmentDetails.isResumed() && fragmentDetails.getActivity() != null) {
fragmentDetails.updateIsLoading(false, null); fragmentDetails.updateIsLoading(false, null);
fragmentDetails.clear(); fragmentDetails.clear();
fragmentDetails.setCurrentServerSettings(server); fragmentDetails.setCurrentServerSettings(server);
@ -586,7 +586,7 @@ public class TorrentsActivity extends AppCompatActivity implements TorrentTasksE
// Remember that the user last selected this // Remember that the user last selected this
applicationSettings.setLastUsedNavigationFilter(currentFilter); applicationSettings.setLastUsedNavigationFilter(currentFilter);
// Clear the details view // Clear the details view
if (fragmentDetails != null && fragmentDetails.isAdded()) { if (fragmentDetails != null && fragmentDetails.isResumed()) {
fragmentDetails.updateIsLoading(false, null); fragmentDetails.updateIsLoading(false, null);
fragmentDetails.clear(); fragmentDetails.clear();
} }
@ -599,7 +599,7 @@ public class TorrentsActivity extends AppCompatActivity implements TorrentTasksE
* @param hasServerSettings Whether there are server settings available, so we can continue to connect * @param hasServerSettings Whether there are server settings available, so we can continue to connect
*/ */
private void updateFragmentVisibility(boolean hasServerSettings) { private void updateFragmentVisibility(boolean hasServerSettings) {
if (fragmentDetails != null && fragmentDetails.isAdded()) { if (fragmentDetails != null && fragmentDetails.isResumed()) {
if (hasServerSettings) { if (hasServerSettings) {
getFragmentManager().beginTransaction().show(fragmentDetails).commit(); getFragmentManager().beginTransaction().show(fragmentDetails).commit();
} else { } else {
@ -905,7 +905,7 @@ public class TorrentsActivity extends AppCompatActivity implements TorrentTasksE
* @param torrent The torrent to show detailed statistics for * @param torrent The torrent to show detailed statistics for
*/ */
public void openDetails(Torrent torrent) { public void openDetails(Torrent torrent) {
if (fragmentDetails != null && fragmentDetails.isAdded()) { if (fragmentDetails != null && fragmentDetails.isResumed()) {
fragmentDetails.updateTorrent(torrent); fragmentDetails.updateTorrent(torrent);
} else { } else {
DetailsActivity_.intent(this).torrent(torrent).currentLabels(lastNavigationLabels).startForResult(RESULT_DETAILS); DetailsActivity_.intent(this).torrent(torrent).currentLabels(lastNavigationLabels).startForResult(RESULT_DETAILS);
@ -1296,7 +1296,7 @@ public class TorrentsActivity extends AppCompatActivity implements TorrentTasksE
fragmentTorrents.updateIsLoading(false); fragmentTorrents.updateIsLoading(false);
if (isCritical) { if (isCritical) {
fragmentTorrents.updateError(error); fragmentTorrents.updateError(error);
if (fragmentDetails != null && fragmentDetails.isAdded()) { if (fragmentDetails != null && fragmentDetails.isResumed()) {
fragmentDetails.updateIsLoading(false, error); fragmentDetails.updateIsLoading(false, error);
} }
} }
@ -1312,13 +1312,13 @@ public class TorrentsActivity extends AppCompatActivity implements TorrentTasksE
fragmentTorrents.updateTorrents(new ArrayList<>(torrents), lastNavigationLabels); fragmentTorrents.updateTorrents(new ArrayList<>(torrents), lastNavigationLabels);
// Update the details fragment if the currently shown torrent is in the newly retrieved list // Update the details fragment if the currently shown torrent is in the newly retrieved list
if (fragmentDetails != null && fragmentDetails.isAdded()) { if (fragmentDetails != null && fragmentDetails.isResumed()) {
fragmentDetails.perhapsUpdateTorrent(torrents); fragmentDetails.perhapsUpdateTorrent(torrents);
} }
// Update local list of labels in the navigation // Update local list of labels in the navigation
navigationListAdapter.updateLabels(lastNavigationLabels); navigationListAdapter.updateLabels(lastNavigationLabels);
if (fragmentDetails != null && fragmentDetails.isAdded()) { if (fragmentDetails != null && fragmentDetails.isResumed()) {
fragmentDetails.updateLabels(lastNavigationLabels); fragmentDetails.updateLabels(lastNavigationLabels);
} }
@ -1347,7 +1347,7 @@ public class TorrentsActivity extends AppCompatActivity implements TorrentTasksE
@UiThread @UiThread
protected void onTorrentDetailsRetrieved(Torrent torrent, TorrentDetails torrentDetails) { protected void onTorrentDetailsRetrieved(Torrent torrent, TorrentDetails torrentDetails) {
// Update the details fragment with the new fine details for the shown torrent // Update the details fragment with the new fine details for the shown torrent
if (fragmentDetails != null && fragmentDetails.isAdded()) { if (fragmentDetails != null && fragmentDetails.isResumed()) {
fragmentDetails.updateTorrentDetails(torrent, torrentDetails); fragmentDetails.updateTorrentDetails(torrent, torrentDetails);
} }
} }
@ -1355,7 +1355,7 @@ public class TorrentsActivity extends AppCompatActivity implements TorrentTasksE
@UiThread @UiThread
protected void onTorrentFilesRetrieved(Torrent torrent, List<TorrentFile> torrentFiles) { protected void onTorrentFilesRetrieved(Torrent torrent, List<TorrentFile> torrentFiles) {
// Update the details fragment with the newly retrieved list of files // Update the details fragment with the newly retrieved list of files
if (fragmentDetails != null && fragmentDetails.isAdded()) { if (fragmentDetails != null && fragmentDetails.isResumed()) {
fragmentDetails.updateTorrentFiles(torrent, new ArrayList<>(torrentFiles)); fragmentDetails.updateTorrentFiles(torrent, new ArrayList<>(torrentFiles));
} }
} }

17
app/src/main/java/org/transdroid/core/gui/TorrentsFragment.java

@ -74,8 +74,8 @@ public class TorrentsFragment extends Fragment implements OnLabelPickedListener
protected ApplicationSettings applicationSettings; protected ApplicationSettings applicationSettings;
@Bean @Bean
protected SystemSettings systemSettings; protected SystemSettings systemSettings;
@InstanceState // HACK Working around #391 while hopefully we rework the UI in the future to persist the list in db or something
protected ArrayList<Torrent> torrents = null; protected static ArrayList<Torrent> torrents = null;
@InstanceState @InstanceState
protected ArrayList<Torrent> lastMultiSelectedTorrents; protected ArrayList<Torrent> lastMultiSelectedTorrents;
@InstanceState @InstanceState
@ -144,7 +144,8 @@ public class TorrentsFragment extends Fragment implements OnLabelPickedListener
* @param newTorrents The new, updated list of torrents * @param newTorrents The new, updated list of torrents
*/ */
public void updateTorrents(ArrayList<Torrent> newTorrents, ArrayList<Label> currentLabels) { public void updateTorrents(ArrayList<Torrent> newTorrents, ArrayList<Label> currentLabels) {
this.torrents = newTorrents; if (!isResumed()) return;
torrents = newTorrents;
this.currentLabels = currentLabels; this.currentLabels = currentLabels;
applyAllFilters(); applyAllFilters();
} }
@ -155,8 +156,9 @@ public class TorrentsFragment extends Fragment implements OnLabelPickedListener
* @param wasRemoved Whether the affected torrent was indeed removed; otherwise it was updated somehow * @param wasRemoved Whether the affected torrent was indeed removed; otherwise it was updated somehow
*/ */
public void quickUpdateTorrent(Torrent affected, boolean wasRemoved) { public void quickUpdateTorrent(Torrent affected, boolean wasRemoved) {
if (!isResumed()) return;
// Remove the old torrent object first // Remove the old torrent object first
Iterator<Torrent> iter = this.torrents.iterator(); Iterator<Torrent> iter = torrents.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
Torrent torrent = iter.next(); Torrent torrent = iter.next();
if (torrent.getUniqueID().equals(affected.getUniqueID())) { if (torrent.getUniqueID().equals(affected.getUniqueID())) {
@ -166,7 +168,7 @@ public class TorrentsFragment extends Fragment implements OnLabelPickedListener
} }
// In case it was an update, add the updated torrent object // In case it was an update, add the updated torrent object
if (!wasRemoved) { if (!wasRemoved) {
this.torrents.add(affected); torrents.add(affected);
} }
// Now refresh the screen // Now refresh the screen
applyAllFilters(); applyAllFilters();
@ -178,7 +180,7 @@ public class TorrentsFragment extends Fragment implements OnLabelPickedListener
* @param clearFilter Also clear any selected filter * @param clearFilter Also clear any selected filter
*/ */
public void clear(boolean clearError, boolean clearFilter) { public void clear(boolean clearError, boolean clearFilter) {
this.torrents = null; torrents = null;
if (clearError) { if (clearError) {
this.connectionErrorMessage = null; this.connectionErrorMessage = null;
} }
@ -420,6 +422,7 @@ public class TorrentsFragment extends Fragment implements OnLabelPickedListener
* @param hasAConnection True if the user has servers configured and therefore has a connection that can be used * @param hasAConnection True if the user has servers configured and therefore has a connection that can be used
*/ */
public void updateConnectionStatus(boolean hasAConnection, Daemon daemonType) { public void updateConnectionStatus(boolean hasAConnection, Daemon daemonType) {
if (!isResumed()) return;
this.hasAConnection = hasAConnection; this.hasAConnection = hasAConnection;
this.daemonType = daemonType; this.daemonType = daemonType;
if (!hasAConnection) { if (!hasAConnection) {
@ -440,6 +443,7 @@ public class TorrentsFragment extends Fragment implements OnLabelPickedListener
* @param isLoading True if the list of torrents is (re)loading, false otherwise * @param isLoading True if the list of torrents is (re)loading, false otherwise
*/ */
public void updateIsLoading(boolean isLoading) { public void updateIsLoading(boolean isLoading) {
if (!isResumed()) return;
this.isLoading = isLoading; this.isLoading = isLoading;
if (isLoading) { if (isLoading) {
clear(true, false); // Indirectly also calls updateViewVisibility() clear(true, false); // Indirectly also calls updateViewVisibility()
@ -453,6 +457,7 @@ public class TorrentsFragment extends Fragment implements OnLabelPickedListener
* @param connectionErrorMessage The error message from the last failed connection attempt, or null to clear the visible error text * @param connectionErrorMessage The error message from the last failed connection attempt, or null to clear the visible error text
*/ */
public void updateError(String connectionErrorMessage) { public void updateError(String connectionErrorMessage) {
if (!isResumed()) return;
this.connectionErrorMessage = connectionErrorMessage; this.connectionErrorMessage = connectionErrorMessage;
errorText.setText(connectionErrorMessage); errorText.setText(connectionErrorMessage);
if (connectionErrorMessage != null) { if (connectionErrorMessage != null) {

5
app/src/main/java/org/transdroid/core/gui/lists/LocalTorrent.java

@ -50,6 +50,7 @@ public class LocalTorrent {
} }
private static final String DECIMAL_FORMATTER = "%.1f"; private static final String DECIMAL_FORMATTER = "%.1f";
private static final String DECIMAL_FORMATTER_2 = "%.2f";
/** /**
* Builds a string showing the upload/download seed ratio. If not downloading, it will base the ratio on the total * Builds a string showing the upload/download seed ratio. If not downloading, it will base the ratio on the total
@ -63,11 +64,11 @@ public class LocalTorrent {
baseSize = t.getDownloadedEver(); baseSize = t.getDownloadedEver();
} }
if (baseSize <= 0) { if (baseSize <= 0) {
return String.format(Locale.getDefault(), DECIMAL_FORMATTER, 0d); return String.format(Locale.getDefault(), DECIMAL_FORMATTER_2, 0d);
} else if (t.getRatio() == Double.POSITIVE_INFINITY) { } else if (t.getRatio() == Double.POSITIVE_INFINITY) {
return "\u221E"; return "\u221E";
} else { } else {
return String.format(Locale.getDefault(), DECIMAL_FORMATTER, t.getRatio()); return String.format(Locale.getDefault(), DECIMAL_FORMATTER_2, t.getRatio());
} }
} }

48
app/src/main/java/org/transdroid/core/gui/lists/SortByListItem.java

@ -16,11 +16,10 @@
*/ */
package org.transdroid.core.gui.lists; package org.transdroid.core.gui.lists;
import android.content.Context;
import org.transdroid.R; import org.transdroid.R;
import org.transdroid.daemon.TorrentsSortBy; import org.transdroid.daemon.TorrentsSortBy;
import android.content.Context;
/** /**
* Represents a way in which a torrents list can be sorted. * Represents a way in which a torrents list can be sorted.
* @author Eric Kok * @author Eric Kok
@ -33,24 +32,33 @@ public class SortByListItem implements SimpleListItem {
public SortByListItem(Context context, TorrentsSortBy sortBy) { public SortByListItem(Context context, TorrentsSortBy sortBy) {
this.sortBy = sortBy; this.sortBy = sortBy;
switch (sortBy) { switch (sortBy) {
case DateAdded: case DateAdded:
this.name = context.getString(R.string.action_sort_added); this.name = context.getString(R.string.action_sort_added);
break; break;
case DateDone: case DateDone:
this.name = context.getString(R.string.action_sort_done); this.name = context.getString(R.string.action_sort_done);
break; break;
case Ratio: case Ratio:
this.name = context.getString(R.string.action_sort_ratio); this.name = context.getString(R.string.action_sort_ratio);
break; break;
case Status: case Status:
this.name = context.getString(R.string.action_sort_status); this.name = context.getString(R.string.action_sort_status);
break; break;
case UploadSpeed: case UploadSpeed:
this.name = context.getString(R.string.action_sort_upspeed); this.name = context.getString(R.string.action_sort_upspeed);
break; break;
default: case DownloadSpeed:
this.name = context.getString(R.string.action_sort_alpha); this.name = context.getString(R.string.action_sort_downspeed);
break; break;
case Percent:
this.name = context.getString(R.string.action_sort_percent);
break;
case Size:
this.name = context.getString(R.string.action_sort_size);
break;
default:
this.name = context.getString(R.string.action_sort_alpha);
break;
} }
} }

2
app/src/main/java/org/transdroid/core/gui/log/DatabaseHelper.java

@ -20,6 +20,7 @@ import java.sql.SQLException;
import android.content.Context; import android.content.Context;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.Keep;
import android.util.Log; import android.util.Log;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
@ -35,6 +36,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "transdroid.db"; private static final String DATABASE_NAME = "transdroid.db";
private static final int DATABASE_VERSION = 1; private static final int DATABASE_VERSION = 1;
@Keep
public DatabaseHelper(Context context) { public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION); super(context, DATABASE_NAME, null, DATABASE_VERSION);
} }

47
app/src/main/java/org/transdroid/core/gui/settings/InterceptableEditTextPreference.java

@ -0,0 +1,47 @@
package org.transdroid.core.gui.settings;
import android.content.Context;
import android.os.Build;
import android.preference.EditTextPreference;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
public class InterceptableEditTextPreference extends EditTextPreference {
private OnPreferenceClickListener overrideClickListener = null;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public InterceptableEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public InterceptableEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public InterceptableEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public InterceptableEditTextPreference(Context context) {
super(context);
}
@Override
public OnPreferenceClickListener getOnPreferenceClickListener() {
return overrideClickListener;
}
@Override
public void setOnPreferenceClickListener(OnPreferenceClickListener onPreferenceClickListener) {
this.overrideClickListener = onPreferenceClickListener;
}
@Override
protected void onClick() {
if (overrideClickListener == null || !overrideClickListener.onPreferenceClick(this)) {
super.onClick();
}
}
}

7
app/src/main/java/org/transdroid/core/gui/settings/MainSettingsActivity.java

@ -178,6 +178,7 @@ public class MainSettingsActivity extends PreferenceCompatActivity {
boolean enableSearchUi = navigationHelper.enableSearchUi(); boolean enableSearchUi = navigationHelper.enableSearchUi();
boolean enableRssUi = navigationHelper.enableRssUi(); boolean enableRssUi = navigationHelper.enableRssUi();
boolean enableDonateLink = !getString(R.string.donate_url).isEmpty();
// Load the preference menu and attach actions // Load the preference menu and attach actions
addPreferencesFromResource(R.xml.pref_main); addPreferencesFromResource(R.xml.pref_main);
@ -191,7 +192,11 @@ public class MainSettingsActivity extends PreferenceCompatActivity {
findPreference("header_background").setOnPreferenceClickListener(onBackgroundSettings); findPreference("header_background").setOnPreferenceClickListener(onBackgroundSettings);
findPreference("header_system").setOnPreferenceClickListener(onSystemSettings); findPreference("header_system").setOnPreferenceClickListener(onSystemSettings);
findPreference("header_help").setOnPreferenceClickListener(onHelpSettings); findPreference("header_help").setOnPreferenceClickListener(onHelpSettings);
findPreference("header_donate").setOnPreferenceClickListener(onDonate); if (enableDonateLink) {
findPreference("header_donate").setOnPreferenceClickListener(onDonate);
} else {
getPreferenceScreen().removePreference(findPreference("header_donate"));
}
// Keep a list of the server codes and names (for default server selection) // Keep a list of the server codes and names (for default server selection)
List<String> serverCodes = new ArrayList<>(); List<String> serverCodes = new ArrayList<>();

30
app/src/main/java/org/transdroid/core/gui/settings/ServerSettingsActivity.java

@ -26,14 +26,16 @@ import android.content.SharedPreferences;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.preference.EditTextPreference; import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.TextUtils; import android.support.annotation.NonNull;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EActivity; import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.OptionsItem; import org.androidannotations.annotations.OptionsItem;
import org.androidannotations.annotations.OptionsMenu; import org.androidannotations.annotations.OptionsMenu;
import org.transdroid.R; import org.transdroid.R;
import org.transdroid.core.app.settings.ApplicationSettings_; import org.transdroid.core.app.settings.ApplicationSettings_;
import org.transdroid.core.service.ConnectivityHelper;
import org.transdroid.daemon.Daemon; import org.transdroid.daemon.Daemon;
/** /**
@ -44,9 +46,12 @@ import org.transdroid.daemon.Daemon;
@OptionsMenu(R.menu.activity_deleteableprefs) @OptionsMenu(R.menu.activity_deleteableprefs)
public class ServerSettingsActivity extends KeyBoundPreferencesActivity { public class ServerSettingsActivity extends KeyBoundPreferencesActivity {
@Bean
protected ConnectivityHelper connectivityHelper;
private static final int DIALOG_CONFIRMREMOVE = 0; private static final int DIALOG_CONFIRMREMOVE = 0;
private EditTextPreference extraPass, folder, downloadDir, excludeFilter, includeFilter; private EditTextPreference extraPass, folder, downloadDir, excludeFilter, includeFilter, localNetworkPreference;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -63,7 +68,7 @@ public class ServerSettingsActivity extends KeyBoundPreferencesActivity {
initTextPreference("server_user"); initTextPreference("server_user");
initTextPreference("server_pass"); initTextPreference("server_pass");
extraPass = initTextPreference("server_extrapass"); extraPass = initTextPreference("server_extrapass");
initTextPreference("server_localnetwork"); localNetworkPreference = initTextPreference("server_localnetwork");
initTextPreference("server_localaddress"); initTextPreference("server_localaddress");
initTextPreference("server_localport"); initTextPreference("server_localport");
folder = initTextPreference("server_folder"); folder = initTextPreference("server_folder");
@ -83,6 +88,16 @@ public class ServerSettingsActivity extends KeyBoundPreferencesActivity {
initTextPreference("server_ssltrustkey", null, "server_sslenabled"); initTextPreference("server_ssltrustkey", null, "server_sslenabled");
onPreferencesChanged(); onPreferencesChanged();
localNetworkPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(final Preference preference) {
if (!connectivityHelper.hasNetworkNamePermission(ServerSettingsActivity.this)) {
connectivityHelper.askNetworkNamePermission(ServerSettingsActivity.this);
return true;
}
return false;
}
});
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB) @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@ -113,6 +128,13 @@ public class ServerSettingsActivity extends KeyBoundPreferencesActivity {
return null; return null;
} }
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (connectivityHelper.requestedPermissionWasGranted(requestCode, permissions, grantResults)) {
localNetworkPreference.getOnPreferenceClickListener().onPreferenceClick(localNetworkPreference);
}
}
@Override @Override
protected void onPreferencesChanged() { protected void onPreferencesChanged() {

48
app/src/main/java/org/transdroid/core/service/ConnectivityHelper.java

@ -16,17 +16,26 @@
*/ */
package org.transdroid.core.service; package org.transdroid.core.service;
import org.androidannotations.annotations.EBean; import android.Manifest;
import org.androidannotations.annotations.SystemService; import android.app.Activity;
import org.androidannotations.annotations.EBean.Scope;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import org.androidannotations.annotations.EBean;
import org.androidannotations.annotations.EBean.Scope;
import org.androidannotations.annotations.SystemService;
import org.transdroid.R;
@EBean(scope = Scope.Singleton) @EBean(scope = Scope.Singleton)
public class ConnectivityHelper { public class ConnectivityHelper {
private static final int REQUEST_LOCATION_PERMISSION = 0;
@SystemService @SystemService
protected ConnectivityManager connectivityManager; protected ConnectivityManager connectivityManager;
@SystemService @SystemService
@ -39,10 +48,39 @@ public class ConnectivityHelper {
} }
public String getConnectedNetworkName() { public String getConnectedNetworkName() {
if (wifiManager.getConnectionInfo() != null && wifiManager.getConnectionInfo().getSSID() != null) { if (wifiManager != null && wifiManager.getConnectionInfo() != null && wifiManager.getConnectionInfo().getSSID() != null) {
return wifiManager.getConnectionInfo().getSSID().replace("\"", ""); return wifiManager.getConnectionInfo().getSSID().replace("\"", "");
} }
return null; return null;
} }
public boolean hasNetworkNamePermission(final Context activityContext) {
return ContextCompat.checkSelfPermission(activityContext, Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED;
}
public void askNetworkNamePermission(final Activity activity) {
new AlertDialog.Builder(activity)
.setTitle(R.string.pref_local_permission_title)
.setMessage(activity.getString(R.string.pref_local_permission_rationale,
activity.getString(R.string.app_name)))
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION);
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
public boolean requestedPermissionWasGranted(int requestCode, String[] permissions, int[] grantResults) {
return (requestCode == REQUEST_LOCATION_PERMISSION
&& permissions != null
&& grantResults != null
&& permissions[0].equals(Manifest.permission.ACCESS_FINE_LOCATION)
&& grantResults[0] == PackageManager.PERMISSION_GRANTED);
}
} }

2
app/src/main/java/org/transdroid/daemon/DummyAdapter.java

@ -80,7 +80,7 @@ public class DummyAdapter implements IDaemonAdapter {
TorrentStatus.Paused, TorrentStatus.Queued, TorrentStatus.Downloading, TorrentStatus.Seeding, TorrentStatus.Paused, TorrentStatus.Queued, TorrentStatus.Downloading, TorrentStatus.Seeding,
TorrentStatus.Error }; TorrentStatus.Error };
Random random = new Random(); Random random = new Random();
for (int i = 1; i < 26; i++) { for (int i = 1; i < 2026; i++) {
String name = names[i % names.length] + Integer.toString(i); String name = names[i % names.length] + Integer.toString(i);
TorrentStatus status = statuses[i % statuses.length]; TorrentStatus status = statuses[i % statuses.length];
int peersGetting = status == TorrentStatus.Downloading ? i * random.nextInt(16) : 0; int peersGetting = status == TorrentStatus.Downloading ? i * random.nextInt(16) : 0;

5
app/src/main/java/org/transdroid/daemon/Rtorrent/RtorrentAdapter.java

@ -337,8 +337,11 @@ public class RtorrentAdapter implements IDaemonAdapter {
} }
try { try {
log.d(LOG_NAME, "Calling " + serverMethod + " with params [" + log.d(LOG_NAME, "Calling " + serverMethod + " with params [" +
(params.length() > 100 ? params.substring(0, 100) + "..." : params) + " ]"); (params.length() > 100 ? params.substring(0, 100) + "..." : params) + " ]");
return rpcclient.call(serverMethod, arguments); return rpcclient.call(serverMethod, arguments);
} catch (IllegalArgumentException e) {
log.d(LOG_NAME, "Using " + buildWebUIUrl() + ": " + e.toString());
throw new DaemonException(ExceptionType.ConnectionError, "Error making call to " + serverMethod);
} catch (XMLRPCException e) { } catch (XMLRPCException e) {
log.d(LOG_NAME, e.toString()); log.d(LOG_NAME, e.toString());
if (e.getCause() instanceof UnauthorizdException) { if (e.getCause() instanceof UnauthorizdException) {

6
app/src/main/res/values/changelog.xml

@ -17,6 +17,12 @@
--> -->
<resources> <resources>
<string name="system_changelog"> <string name="system_changelog">
Transdroid 2.5.15\n
- Support local network config on Android 8.1+ by asking for location permission\n
- Hacky fix to prevent crashes on > 1000 torrents\n
- Fix crashes during background or config changes\n
- Removed donate link in Transdrone\n
\n
Transdroid 2.5.14\n Transdroid 2.5.14\n
- Fix crashes in the UI here and there\n - Fix crashes in the UI here and there\n
- Fix notifications on Android 8+\n - Fix notifications on Android 8+\n

6
app/src/main/res/values/strings.xml

@ -251,7 +251,7 @@
<string name="pref_reqauth">Requires authentication</string> <string name="pref_reqauth">Requires authentication</string>
<string name="pref_reqauth_info">Opens links in the webbrowser for user login</string> <string name="pref_reqauth_info">Opens links in the webbrowser for user login</string>
<string name="pref_alarmrssnew">New item notification</string> <string name="pref_alarmrssnew">New item notification</string>
<string name="pref_alarmrssnew_info">Nofity when new torrents are released</string> <string name="pref_alarmrssnew_info">Notify when new torrents are released</string>
<string name="pref_alarmrssexclude">Exclude filter</string> <string name="pref_alarmrssexclude">Exclude filter</string>
<string name="pref_alarmrssexclude_info">Don\'t show torrents whose name matches these |-separated words</string> <string name="pref_alarmrssexclude_info">Don\'t show torrents whose name matches these |-separated words</string>
<string name="pref_alarmrssinclude">Include filter</string> <string name="pref_alarmrssinclude">Include filter</string>
@ -270,6 +270,8 @@
<string name="pref_localport">Local port number</string> <string name="pref_localport">Local port number</string>
<string name="pref_localnetwork">Local network</string> <string name="pref_localnetwork">Local network</string>
<string name="pref_localnetwork_info">The server\'s local network SSID</string> <string name="pref_localnetwork_info">The server\'s local network SSID</string>
<string name="pref_local_permission_title">Location permission</string>
<string name="pref_local_permission_rationale">To known the connected Wifi network SSID name, %1$s requires the location permission</string>
<string name="pref_folder">Folder</string> <string name="pref_folder">Folder</string>
<string name="pref_folder_info">Usually empty</string> <string name="pref_folder_info">Usually empty</string>
<string name="pref_scgifolder">SCGI mount point</string> <string name="pref_scgifolder">SCGI mount point</string>
@ -277,7 +279,7 @@
<string name="pref_alarmdone">Finished notification</string> <string name="pref_alarmdone">Finished notification</string>
<string name="pref_alarmdone_info">Notify when a torrent finishes</string> <string name="pref_alarmdone_info">Notify when a torrent finishes</string>
<string name="pref_alarmnew">New torrent notification</string> <string name="pref_alarmnew">New torrent notification</string>
<string name="pref_alarmnew_info">Nofity when a torrent was added</string> <string name="pref_alarmnew_info">Notify when a torrent was added</string>
<string name="pref_alarmexclude">Exclude filter</string> <string name="pref_alarmexclude">Exclude filter</string>
<string name="pref_alarmexclude_info">Notify only if torrent name matches these |-separated words</string> <string name="pref_alarmexclude_info">Notify only if torrent name matches these |-separated words</string>
<string name="pref_alarminclude">Include filter</string> <string name="pref_alarminclude">Include filter</string>

5
app/src/main/res/xml/pref_server.xml

@ -15,7 +15,8 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Transdroid. If not, see <http://www.gnu.org/licenses/>. along with Transdroid. If not, see <http://www.gnu.org/licenses/>.
--> -->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<EditTextPreference <EditTextPreference
android:key="server_name" android:key="server_name"
@ -49,7 +50,7 @@
android:key="server_port" android:key="server_port"
android:title="@string/pref_port" android:title="@string/pref_port"
android:inputType="numberSigned" /> android:inputType="numberSigned" />
<EditTextPreference <org.transdroid.core.gui.settings.InterceptableEditTextPreference
android:key="server_localnetwork" android:key="server_localnetwork"
android:title="@string/pref_localnetwork" android:title="@string/pref_localnetwork"
android:summary="@string/pref_localnetwork_info" android:summary="@string/pref_localnetwork_info"

6
build.gradle

@ -1,18 +1,18 @@
buildscript { buildscript {
repositories { repositories {
google() google()
jcenter() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.2.1' classpath 'com.android.tools.build:gradle:3.3.2'
} }
} }
allprojects { allprojects {
repositories { repositories {
google() google()
mavenCentral()
jcenter() jcenter()
mavenLocal()
maven { url "https://jitpack.io" } maven { url "https://jitpack.io" }
} }
} }

3
gradle.properties

@ -15,4 +15,5 @@
# When configured, Gradle will run in incubating parallel mode. # When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit # This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true # org.gradle.parallel=true
android.enableR8=true

2
gradle/wrapper/gradle-wrapper.properties vendored

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip

Loading…
Cancel
Save