From 13e2eddb6a3da3e61d298354537ebbfd0bc9c488 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 27 Sep 2017 22:48:04 +1000 Subject: [PATCH 1/6] Static import of inner class to improve readability --- .../views/apps/AppListItemController.java | 29 +++++++++---------- .../fdroid/views/main/MainActivity.java | 6 ++-- .../items/AppStatusListItemController.java | 6 ++-- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java index b9a0b1168..e2bdf0dca 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java @@ -32,6 +32,7 @@ import com.nostra13.universalimageloader.core.ImageLoader; import org.fdroid.fdroid.AppDetails2; import org.fdroid.fdroid.AppUpdateStatusManager; +import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus; import org.fdroid.fdroid.R; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.data.Apk; @@ -57,7 +58,7 @@ import java.util.Iterator; * * * The state of the UI is defined in a dumb {@link AppListItemState} class, then applied to the UI - * in the {@link #refreshView(App, AppUpdateStatusManager.AppUpdateStatus)} method. + * in the {@link #refreshView(App, AppUpdateStatus)} method. */ public abstract class AppListItemController extends RecyclerView.ViewHolder { @@ -102,7 +103,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { private App currentApp; @Nullable - private AppUpdateStatusManager.AppUpdateStatus currentStatus; + private AppUpdateStatus currentStatus; @TargetApi(21) public AppListItemController(final Activity activity, View itemView) { @@ -166,10 +167,10 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { // Figures out the current install/update/download/etc status for the app we are viewing. // Then, asks the view to update itself to reflect this status. - Iterator statuses = + Iterator statuses = AppUpdateStatusManager.getInstance(activity).getByPackageName(app.packageName).iterator(); if (statuses.hasNext()) { - AppUpdateStatusManager.AppUpdateStatus status = statuses.next(); + AppUpdateStatus status = statuses.next(); updateAppStatus(app, status); } else { updateAppStatus(app, null); @@ -190,23 +191,22 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { * Updates both the progress bar and the circular install button (which shows progress around the outside of * the circle). Also updates the app label to indicate that the app is being downloaded. */ - private void updateAppStatus(@NonNull App app, @Nullable AppUpdateStatusManager.AppUpdateStatus status) { + private void updateAppStatus(@NonNull App app, @Nullable AppUpdateStatus status) { currentStatus = status; refreshView(app, status); } /** - * Queries the current state via {@link #getCurrentViewState(App, AppUpdateStatusManager.AppUpdateStatus)} + * Queries the current state via {@link #getCurrentViewState(App, AppUpdateStatus)} * and then updates the relevant widgets depending on that state. * * Should contain little to no business logic, this all belongs to - * {@link #getCurrentViewState(App, AppUpdateStatusManager.AppUpdateStatus)}. + * {@link #getCurrentViewState(App, AppUpdateStatus)}. * * @see AppListItemState - * @see #getCurrentViewState(App, AppUpdateStatusManager.AppUpdateStatus) + * @see #getCurrentViewState(App, AppUpdateStatus) */ - private void refreshView(@NonNull App app, - @Nullable AppUpdateStatusManager.AppUpdateStatus appStatus) { + private void refreshView(@NonNull App app, @Nullable AppUpdateStatus appStatus) { AppListItemState viewState = getCurrentViewState(app, appStatus); @@ -292,8 +292,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { } @NonNull - protected AppListItemState getCurrentViewState( - @NonNull App app, @Nullable AppUpdateStatusManager.AppUpdateStatus appStatus) { + protected AppListItemState getCurrentViewState(@NonNull App app, @Nullable AppUpdateStatus appStatus) { if (appStatus == null) { return getViewStateDefault(app); } else { @@ -328,8 +327,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { return state; } - protected AppListItemState getViewStateDownloading( - @NonNull App app, @NonNull AppUpdateStatusManager.AppUpdateStatus currentStatus) { + protected AppListItemState getViewStateDownloading(@NonNull App app, @NonNull AppUpdateStatus currentStatus) { CharSequence mainText = activity.getString( R.string.app_list__name__downloading_in_progress, app.name); @@ -384,8 +382,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { private final BroadcastReceiver onStatusChanged = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - AppUpdateStatusManager.AppUpdateStatus newStatus = - intent.getParcelableExtra(AppUpdateStatusManager.EXTRA_STATUS); + AppUpdateStatus newStatus = intent.getParcelableExtra(AppUpdateStatusManager.EXTRA_STATUS); if (currentApp == null || !TextUtils.equals(newStatus.app.packageName, currentApp.packageName) diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java index 5a5cc512c..72dfe5ef5 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java @@ -23,6 +23,7 @@ import com.ashokvarma.bottomnavigation.BottomNavigationItem; import org.fdroid.fdroid.AppDetails2; import org.fdroid.fdroid.AppUpdateStatusManager; +import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus; import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.NfcHelper; import org.fdroid.fdroid.Preferences; @@ -385,8 +386,7 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB } // Check if we have moved into the ReadyToInstall or Installed state. - AppUpdateStatusManager.AppUpdateStatus status = manager.get( - intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL)); + AppUpdateStatus status = manager.get(intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL)); boolean isStatusChange = intent.getBooleanExtra(AppUpdateStatusManager.EXTRA_IS_STATUS_UPDATE, false); if (isStatusChange && status != null @@ -396,7 +396,7 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB if (updateBadge) { int count = 0; - for (AppUpdateStatusManager.AppUpdateStatus s : manager.getAll()) { + for (AppUpdateStatus s : manager.getAll()) { if (s.status == AppUpdateStatusManager.Status.ReadyToInstall) { count++; } diff --git a/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java index ade2990fe..ed0b536a1 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java @@ -6,6 +6,7 @@ import android.support.annotation.Nullable; import android.view.View; import org.fdroid.fdroid.AppUpdateStatusManager; +import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus; import org.fdroid.fdroid.R; import org.fdroid.fdroid.data.App; import org.fdroid.fdroid.views.apps.AppListItemController; @@ -24,15 +25,14 @@ public class AppStatusListItemController extends AppListItemController { @NonNull @Override - protected AppListItemState getCurrentViewState( - @NonNull App app, @Nullable AppUpdateStatusManager.AppUpdateStatus appStatus) { + protected AppListItemState getCurrentViewState(@NonNull App app, @Nullable AppUpdateStatus appStatus) { return super.getCurrentViewState(app, appStatus) .setStatusText(getStatusText(appStatus)); } @Nullable - private CharSequence getStatusText(@Nullable AppUpdateStatusManager.AppUpdateStatus appStatus) { + private CharSequence getStatusText(@Nullable AppUpdateStatus appStatus) { if (appStatus != null) { switch (appStatus.status) { case ReadyToInstall: From 32c17e5f72d000799e2a86da83b78971aa9372d3 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 27 Sep 2017 22:53:00 +1000 Subject: [PATCH 2/6] Initial framework to allow for dismissing apps in updates tab. --- .../views/apps/AppListItemController.java | 36 ++++++++++ .../fdroid/views/updates/UpdatesAdapter.java | 2 + .../updates/UpdatesItemTouchCallback.java | 70 +++++++++++++++++++ .../views/updates/UpdatesViewBinder.java | 4 ++ 4 files changed, 112 insertions(+) create mode 100644 app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesItemTouchCallback.java diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java index e2bdf0dca..aa5d568e1 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java @@ -26,6 +26,7 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; +import android.widget.Toast; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; @@ -160,6 +161,11 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { itemView.setOnClickListener(onAppClicked); } + @Nullable + protected final AppUpdateStatus getCurrentStatus() { + return currentStatus; + } + public void bindModel(@NonNull App app) { currentApp = app; @@ -187,6 +193,36 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { broadcastManager.registerReceiver(onStatusChanged, intentFilter); } + /** To be overridden if required */ + public boolean canDismiss() { + return false; + } + + /** + * If able, forwards the request onto {@link #onDismissApp(App)}. + * This mainly exists to keep the API consistent, in that the {@link App} is threaded through to the relevant + * method with a guarantee that it is not null, rather than every method having to check if it is null or not. + */ + public final void onDismiss() { + if (currentApp != null && canDismiss()) { + CharSequence message = onDismissApp(currentApp); + if (message != null) { + Toast.makeText(activity, message, Toast.LENGTH_SHORT).show(); + } + } + } + + /** + * Override to respond to the user swiping an app to dismiss it from the list. + * @return Optionally return a description of what you did if it is not obvious to the user. It will be shown as + * a {@link android.widget.Toast} for a {@link android.widget.Toast#LENGTH_SHORT} time. + * @see #canDismiss() This must also be overriden and should return true. + */ + @Nullable + protected CharSequence onDismissApp(@NonNull App app) { + return null; + } + /** * Updates both the progress bar and the circular install button (which shows progress around the outside of * the circle). Also updates the app label to indicate that the app is being downloaded. diff --git a/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java index a993910a6..03ee0bd28 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java @@ -341,4 +341,6 @@ public class UpdatesAdapter extends RecyclerView.Adapter + *
  • + * {@link KnownVulnAppListItemController}: Will be marked as "Ignored" and wont warn the user in the future. + *
  • + *
  • + * {@link UpdateableAppListItemController}: Will get marked as "Ignore this update". + *
  • + *
  • + * {@link AppStatusListItemController}: + *
      + *
    • If downloading or queued to download, cancel the download.
    • + *
    • If downloaded waiting to install, forget that we downloaded it.
    • + *
    • If installed ready to run, stop prompting the user to run the app.
    • + *
    + *
  • + * + */ +public class UpdatesItemTouchCallback extends ItemTouchHelper.Callback { + + private final UpdatesAdapter adapter; + + public UpdatesItemTouchCallback(UpdatesAdapter adapter) { + this.adapter = adapter; + } + + @Override + public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + int swipeFlags = 0; + if (viewHolder instanceof AppListItemController) { + AppListItemController controller = (AppListItemController) viewHolder; + if (controller.canDismiss()) { + swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; + } + } + return makeMovementFlags(0, swipeFlags); + } + + @Override + public boolean onMove( + RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { + return false; + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + AppListItemController controller = (AppListItemController) viewHolder; + controller.onDismiss(); + adapter.onItemDismissed(); + } + + @Override + public boolean isItemViewSwipeEnabled() { + return true; + } + +} diff --git a/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesViewBinder.java b/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesViewBinder.java index 84602df5b..28420cb15 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesViewBinder.java +++ b/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesViewBinder.java @@ -3,6 +3,7 @@ package org.fdroid.fdroid.views.updates; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; @@ -28,6 +29,9 @@ public class UpdatesViewBinder { list.setLayoutManager(new LinearLayoutManager(activity)); list.setAdapter(adapter); + ItemTouchHelper touchHelper = new ItemTouchHelper(new UpdatesItemTouchCallback(adapter)); + touchHelper.attachToRecyclerView(list); + emptyState = (TextView) view.findViewById(R.id.empty_state); emptyImage = (ImageView) view.findViewById(R.id.image); } From 1d4f4ce01d9efa6c40c6db4869ac5d1f512a9c57 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 27 Sep 2017 22:53:27 +1000 Subject: [PATCH 3/6] Correctly handle swiping to dismiss items in updates tab. Items which can be updated (but have not yet been downloaded or queued for download) will act as if the user selected "Ignore this update" from the app details view. Items which represent app statuses (e.g. downloading, downloaded ready to install, installed ready to run) will have the status removed. If required, we will also forget that they are ready to install, so they wont be there next time. --- .../views/apps/AppListItemController.java | 14 ++++++---- .../fdroid/views/updates/UpdatesAdapter.java | 10 +++++++ .../items/AppStatusListItemController.java | 26 +++++++++++++++++++ .../items/KnownVulnAppListItemController.java | 15 +++++++++++ .../UpdateableAppListItemController.java | 20 ++++++++++++++ app/src/main/res/values/strings.xml | 2 ++ 6 files changed, 82 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java index aa5d568e1..4a007830d 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java @@ -510,11 +510,15 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { private final View.OnClickListener onCancelDownload = new View.OnClickListener() { @Override public void onClick(View v) { - if (currentStatus == null || currentStatus.status != AppUpdateStatusManager.Status.Downloading) { - return; - } - - InstallManagerService.cancel(activity, currentStatus.getUniqueKey()); + cancelDownload(); } }; + + protected final void cancelDownload() { + if (currentStatus == null || currentStatus.status != AppUpdateStatusManager.Status.Downloading) { + return; + } + + InstallManagerService.cancel(activity, currentStatus.getUniqueKey()); + } } diff --git a/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java index 03ee0bd28..046e8f1b1 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java @@ -341,6 +341,16 @@ public class UpdatesAdapter extends RecyclerView.AdapterDownloading %1$s %1$s installed Downloaded, ready to install + Update ignored + Vulnerability ignored Installed Apps Updates ignored From 25897df85bdab1b321a99cfeca9ac3de0dfcd64d Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 27 Sep 2017 23:30:54 +1000 Subject: [PATCH 4/6] Update the badge on the bottom nav when dismissing 'ready to install' apps --- .../fdroid/views/main/MainActivity.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java index 72dfe5ef5..1db90df67 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java @@ -107,9 +107,9 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB .addItem(new BottomNavigationItem(R.drawable.ic_settings, R.string.menu_settings)) .initialise(); - IntentFilter updateableAppsFilter = new IntentFilter( - AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED); + IntentFilter updateableAppsFilter = new IntentFilter(AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED); updateableAppsFilter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED); + updateableAppsFilter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED); LocalBroadcastManager.getInstance(this).registerReceiver(onUpdateableAppsChanged, updateableAppsFilter); if (savedInstanceState != null) { @@ -379,10 +379,24 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(context); String reason = intent.getStringExtra(AppUpdateStatusManager.EXTRA_REASON_FOR_CHANGE); - if (AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED.equals(intent.getAction()) && - (AppUpdateStatusManager.REASON_READY_TO_INSTALL.equals(reason) || - AppUpdateStatusManager.REASON_REPO_DISABLED.equals(reason))) { - updateBadge = true; + switch(intent.getAction()) { + // Apps which are added/removed from the list due to becoming ready to install or a repo being + // disabled both cause us to increase/decrease our badge count respectively. + case AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED: + if (AppUpdateStatusManager.REASON_READY_TO_INSTALL.equals(reason) || + AppUpdateStatusManager.REASON_REPO_DISABLED.equals(reason)) { + updateBadge = true; + } + break; + + // Apps which were previously "Ready to install" but have been removed. We need to lower our badge + // count in response to this. + case AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED: + AppUpdateStatus status = intent.getParcelableExtra(AppUpdateStatusManager.EXTRA_STATUS); + if (status != null && status.status == AppUpdateStatusManager.Status.ReadyToInstall) { + updateBadge = true; + } + break; } // Check if we have moved into the ReadyToInstall or Installed state. From b5ae78cf4da66061e03b85b7af5d22bf7a5d0036 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 27 Sep 2017 23:48:43 +1000 Subject: [PATCH 5/6] Specify whether dismissing an item requires a list rebuild or not. The controller in charge of dismissing an item will have an insight into whether it will cause a re-query for an existing cursor or not. If a re-query will occur in response to a `ContentResolver#notifyChange()` invokation (in this case in response to updating `AppPrefs`), then the `UpdatesAdapter` doesn't need to rebuild itself yet. If it is a status update, then it should update the adapter right away. Seeing as the controller was already returning one thing (a message to be displayed in a `Toast` and now it also needs to return an opinion on whether to rebuild the adapter or not, this has been extracted into a value object which has a message and a rebuild adapter flag. --- .../views/apps/AppListItemController.java | 18 ++++++------ .../fdroid/views/main/MainActivity.java | 2 +- .../fdroid/views/updates/DismissResult.java | 29 +++++++++++++++++++ .../fdroid/views/updates/UpdatesAdapter.java | 9 ++---- .../updates/UpdatesItemTouchCallback.java | 17 +++++++++-- .../views/updates/UpdatesViewBinder.java | 2 +- .../items/AppStatusListItemController.java | 7 +++-- .../items/KnownVulnAppListItemController.java | 5 ++-- .../UpdateableAppListItemController.java | 7 +++-- 9 files changed, 67 insertions(+), 29 deletions(-) create mode 100644 app/src/main/java/org/fdroid/fdroid/views/updates/DismissResult.java diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java index 4a007830d..935a0f720 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java @@ -26,7 +26,6 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; -import android.widget.Toast; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; @@ -43,6 +42,7 @@ import org.fdroid.fdroid.installer.ApkCache; import org.fdroid.fdroid.installer.InstallManagerService; import org.fdroid.fdroid.installer.Installer; import org.fdroid.fdroid.installer.InstallerFactory; +import org.fdroid.fdroid.views.updates.DismissResult; import java.io.File; import java.util.Iterator; @@ -203,13 +203,13 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { * This mainly exists to keep the API consistent, in that the {@link App} is threaded through to the relevant * method with a guarantee that it is not null, rather than every method having to check if it is null or not. */ - public final void onDismiss() { + @NonNull + public final DismissResult onDismiss() { if (currentApp != null && canDismiss()) { - CharSequence message = onDismissApp(currentApp); - if (message != null) { - Toast.makeText(activity, message, Toast.LENGTH_SHORT).show(); - } + return onDismissApp(currentApp); } + + return new DismissResult(); } /** @@ -218,9 +218,9 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { * a {@link android.widget.Toast} for a {@link android.widget.Toast#LENGTH_SHORT} time. * @see #canDismiss() This must also be overriden and should return true. */ - @Nullable - protected CharSequence onDismissApp(@NonNull App app) { - return null; + @NonNull + protected DismissResult onDismissApp(@NonNull App app) { + return new DismissResult(); } /** diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java index 1db90df67..50636c861 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java @@ -379,7 +379,7 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(context); String reason = intent.getStringExtra(AppUpdateStatusManager.EXTRA_REASON_FOR_CHANGE); - switch(intent.getAction()) { + switch (intent.getAction()) { // Apps which are added/removed from the list due to becoming ready to install or a repo being // disabled both cause us to increase/decrease our badge count respectively. case AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED: diff --git a/app/src/main/java/org/fdroid/fdroid/views/updates/DismissResult.java b/app/src/main/java/org/fdroid/fdroid/views/updates/DismissResult.java new file mode 100644 index 000000000..c68870128 --- /dev/null +++ b/app/src/main/java/org/fdroid/fdroid/views/updates/DismissResult.java @@ -0,0 +1,29 @@ +package org.fdroid.fdroid.views.updates; + +import android.support.annotation.Nullable; + +/** + * When dismissing an item from the Updates tab, there is two different things we need to return. + * This is a dumb data object to represent these things, because a method is only allowed to return one thing. + */ +public class DismissResult { + + @Nullable + public final CharSequence message; + + public final boolean requiresAdapterRefresh; + + public DismissResult() { + this(null, false); + } + + public DismissResult(boolean requiresAdapterRefresh) { + this(null, requiresAdapterRefresh); + } + + public DismissResult(@Nullable CharSequence message, boolean requiresAdapterRefresh) { + this.message = message; + this.requiresAdapterRefresh = requiresAdapterRefresh; + } + +} diff --git a/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java index 046e8f1b1..c657fe498 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java @@ -343,14 +343,9 @@ public class UpdatesAdapter extends RecyclerView.Adapter Date: Wed, 27 Sep 2017 23:56:38 +1000 Subject: [PATCH 6/6] Show 'download cancelled' message when dismissing downloading app --- .../views/updates/items/AppStatusListItemController.java | 6 +++++- app/src/main/res/values/strings.xml | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java index 37b27a5a6..981409eff 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/updates/items/AppStatusListItemController.java @@ -56,20 +56,24 @@ public class AppStatusListItemController extends AppListItemController { @Override protected DismissResult onDismissApp(@NonNull App app) { AppUpdateStatus status = getCurrentStatus(); + CharSequence message = null; if (status != null) { AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(activity); manager.removeApk(status.getUniqueKey()); switch (status.status) { case ReadyToInstall: manager.markAsNoLongerPendingInstall(status); + // Do this silently, because it should be pretty obvious based on the context + // of a "Ready to install" app being dismissed. break; case Downloading: cancelDownload(); + message = activity.getString(R.string.app_list__dismiss_downloading_app); break; } } - return new DismissResult(true); + return new DismissResult(message, true); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a3ea2f2f0..abf63d459 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -89,6 +89,7 @@ This often occurs with apps installed via Google Play or other sources, if they Downloaded, ready to install Update ignored Vulnerability ignored + Download canceled Installed Apps Updates ignored