Merge branch 'issue-1131--swipe-to-dismiss-updates' into 'master'
Swipe to dismiss updates Closes #1131 See merge request fdroid/fdroidclient!584
This commit is contained in:
commit
695394fe71
@ -32,6 +32,7 @@ import com.nostra13.universalimageloader.core.ImageLoader;
|
|||||||
|
|
||||||
import org.fdroid.fdroid.AppDetails2;
|
import org.fdroid.fdroid.AppDetails2;
|
||||||
import org.fdroid.fdroid.AppUpdateStatusManager;
|
import org.fdroid.fdroid.AppUpdateStatusManager;
|
||||||
|
import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.data.Apk;
|
import org.fdroid.fdroid.data.Apk;
|
||||||
@ -41,6 +42,7 @@ import org.fdroid.fdroid.installer.ApkCache;
|
|||||||
import org.fdroid.fdroid.installer.InstallManagerService;
|
import org.fdroid.fdroid.installer.InstallManagerService;
|
||||||
import org.fdroid.fdroid.installer.Installer;
|
import org.fdroid.fdroid.installer.Installer;
|
||||||
import org.fdroid.fdroid.installer.InstallerFactory;
|
import org.fdroid.fdroid.installer.InstallerFactory;
|
||||||
|
import org.fdroid.fdroid.views.updates.DismissResult;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -57,7 +59,7 @@ import java.util.Iterator;
|
|||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* The state of the UI is defined in a dumb {@link AppListItemState} class, then applied to the UI
|
* 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 {
|
public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
@ -102,7 +104,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
private App currentApp;
|
private App currentApp;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private AppUpdateStatusManager.AppUpdateStatus currentStatus;
|
private AppUpdateStatus currentStatus;
|
||||||
|
|
||||||
@TargetApi(21)
|
@TargetApi(21)
|
||||||
public AppListItemController(final Activity activity, View itemView) {
|
public AppListItemController(final Activity activity, View itemView) {
|
||||||
@ -159,6 +161,11 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
itemView.setOnClickListener(onAppClicked);
|
itemView.setOnClickListener(onAppClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected final AppUpdateStatus getCurrentStatus() {
|
||||||
|
return currentStatus;
|
||||||
|
}
|
||||||
|
|
||||||
public void bindModel(@NonNull App app) {
|
public void bindModel(@NonNull App app) {
|
||||||
currentApp = app;
|
currentApp = app;
|
||||||
|
|
||||||
@ -166,10 +173,10 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
|
|
||||||
// Figures out the current install/update/download/etc status for the app we are viewing.
|
// 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.
|
// Then, asks the view to update itself to reflect this status.
|
||||||
Iterator<AppUpdateStatusManager.AppUpdateStatus> statuses =
|
Iterator<AppUpdateStatus> statuses =
|
||||||
AppUpdateStatusManager.getInstance(activity).getByPackageName(app.packageName).iterator();
|
AppUpdateStatusManager.getInstance(activity).getByPackageName(app.packageName).iterator();
|
||||||
if (statuses.hasNext()) {
|
if (statuses.hasNext()) {
|
||||||
AppUpdateStatusManager.AppUpdateStatus status = statuses.next();
|
AppUpdateStatus status = statuses.next();
|
||||||
updateAppStatus(app, status);
|
updateAppStatus(app, status);
|
||||||
} else {
|
} else {
|
||||||
updateAppStatus(app, null);
|
updateAppStatus(app, null);
|
||||||
@ -186,27 +193,56 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
broadcastManager.registerReceiver(onStatusChanged, intentFilter);
|
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.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public final DismissResult onDismiss() {
|
||||||
|
if (currentApp != null && canDismiss()) {
|
||||||
|
return onDismissApp(currentApp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DismissResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
protected DismissResult onDismissApp(@NonNull App app) {
|
||||||
|
return new DismissResult();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates both the progress bar and the circular install button (which shows progress around the outside of
|
* 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.
|
* 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;
|
currentStatus = status;
|
||||||
refreshView(app, 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.
|
* and then updates the relevant widgets depending on that state.
|
||||||
*
|
*
|
||||||
* Should contain little to no business logic, this all belongs to
|
* Should contain little to no business logic, this all belongs to
|
||||||
* {@link #getCurrentViewState(App, AppUpdateStatusManager.AppUpdateStatus)}.
|
* {@link #getCurrentViewState(App, AppUpdateStatus)}.
|
||||||
*
|
*
|
||||||
* @see AppListItemState
|
* @see AppListItemState
|
||||||
* @see #getCurrentViewState(App, AppUpdateStatusManager.AppUpdateStatus)
|
* @see #getCurrentViewState(App, AppUpdateStatus)
|
||||||
*/
|
*/
|
||||||
private void refreshView(@NonNull App app,
|
private void refreshView(@NonNull App app, @Nullable AppUpdateStatus appStatus) {
|
||||||
@Nullable AppUpdateStatusManager.AppUpdateStatus appStatus) {
|
|
||||||
|
|
||||||
AppListItemState viewState = getCurrentViewState(app, appStatus);
|
AppListItemState viewState = getCurrentViewState(app, appStatus);
|
||||||
|
|
||||||
@ -292,8 +328,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
protected AppListItemState getCurrentViewState(
|
protected AppListItemState getCurrentViewState(@NonNull App app, @Nullable AppUpdateStatus appStatus) {
|
||||||
@NonNull App app, @Nullable AppUpdateStatusManager.AppUpdateStatus appStatus) {
|
|
||||||
if (appStatus == null) {
|
if (appStatus == null) {
|
||||||
return getViewStateDefault(app);
|
return getViewStateDefault(app);
|
||||||
} else {
|
} else {
|
||||||
@ -328,8 +363,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AppListItemState getViewStateDownloading(
|
protected AppListItemState getViewStateDownloading(@NonNull App app, @NonNull AppUpdateStatus currentStatus) {
|
||||||
@NonNull App app, @NonNull AppUpdateStatusManager.AppUpdateStatus currentStatus) {
|
|
||||||
CharSequence mainText = activity.getString(
|
CharSequence mainText = activity.getString(
|
||||||
R.string.app_list__name__downloading_in_progress, app.name);
|
R.string.app_list__name__downloading_in_progress, app.name);
|
||||||
|
|
||||||
@ -384,8 +418,7 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
private final BroadcastReceiver onStatusChanged = new BroadcastReceiver() {
|
private final BroadcastReceiver onStatusChanged = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
AppUpdateStatusManager.AppUpdateStatus newStatus =
|
AppUpdateStatus newStatus = intent.getParcelableExtra(AppUpdateStatusManager.EXTRA_STATUS);
|
||||||
intent.getParcelableExtra(AppUpdateStatusManager.EXTRA_STATUS);
|
|
||||||
|
|
||||||
if (currentApp == null
|
if (currentApp == null
|
||||||
|| !TextUtils.equals(newStatus.app.packageName, currentApp.packageName)
|
|| !TextUtils.equals(newStatus.app.packageName, currentApp.packageName)
|
||||||
@ -477,11 +510,15 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
private final View.OnClickListener onCancelDownload = new View.OnClickListener() {
|
private final View.OnClickListener onCancelDownload = new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (currentStatus == null || currentStatus.status != AppUpdateStatusManager.Status.Downloading) {
|
cancelDownload();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
InstallManagerService.cancel(activity, currentStatus.getUniqueKey());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected final void cancelDownload() {
|
||||||
|
if (currentStatus == null || currentStatus.status != AppUpdateStatusManager.Status.Downloading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstallManagerService.cancel(activity, currentStatus.getUniqueKey());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import com.ashokvarma.bottomnavigation.BottomNavigationItem;
|
|||||||
|
|
||||||
import org.fdroid.fdroid.AppDetails2;
|
import org.fdroid.fdroid.AppDetails2;
|
||||||
import org.fdroid.fdroid.AppUpdateStatusManager;
|
import org.fdroid.fdroid.AppUpdateStatusManager;
|
||||||
|
import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus;
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.NfcHelper;
|
import org.fdroid.fdroid.NfcHelper;
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
@ -106,9 +107,9 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB
|
|||||||
.addItem(new BottomNavigationItem(R.drawable.ic_settings, R.string.menu_settings))
|
.addItem(new BottomNavigationItem(R.drawable.ic_settings, R.string.menu_settings))
|
||||||
.initialise();
|
.initialise();
|
||||||
|
|
||||||
IntentFilter updateableAppsFilter = new IntentFilter(
|
IntentFilter updateableAppsFilter = new IntentFilter(AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED);
|
||||||
AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED);
|
|
||||||
updateableAppsFilter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED);
|
updateableAppsFilter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED);
|
||||||
|
updateableAppsFilter.addAction(AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED);
|
||||||
LocalBroadcastManager.getInstance(this).registerReceiver(onUpdateableAppsChanged, updateableAppsFilter);
|
LocalBroadcastManager.getInstance(this).registerReceiver(onUpdateableAppsChanged, updateableAppsFilter);
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
@ -378,15 +379,28 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB
|
|||||||
AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(context);
|
AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(context);
|
||||||
|
|
||||||
String reason = intent.getStringExtra(AppUpdateStatusManager.EXTRA_REASON_FOR_CHANGE);
|
String reason = intent.getStringExtra(AppUpdateStatusManager.EXTRA_REASON_FOR_CHANGE);
|
||||||
if (AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED.equals(intent.getAction()) &&
|
switch (intent.getAction()) {
|
||||||
(AppUpdateStatusManager.REASON_READY_TO_INSTALL.equals(reason) ||
|
// Apps which are added/removed from the list due to becoming ready to install or a repo being
|
||||||
AppUpdateStatusManager.REASON_REPO_DISABLED.equals(reason))) {
|
// disabled both cause us to increase/decrease our badge count respectively.
|
||||||
updateBadge = true;
|
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.
|
// Check if we have moved into the ReadyToInstall or Installed state.
|
||||||
AppUpdateStatusManager.AppUpdateStatus status = manager.get(
|
AppUpdateStatus status = manager.get(intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL));
|
||||||
intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL));
|
|
||||||
boolean isStatusChange = intent.getBooleanExtra(AppUpdateStatusManager.EXTRA_IS_STATUS_UPDATE, false);
|
boolean isStatusChange = intent.getBooleanExtra(AppUpdateStatusManager.EXTRA_IS_STATUS_UPDATE, false);
|
||||||
if (isStatusChange
|
if (isStatusChange
|
||||||
&& status != null
|
&& status != null
|
||||||
@ -396,7 +410,7 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB
|
|||||||
|
|
||||||
if (updateBadge) {
|
if (updateBadge) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (AppUpdateStatusManager.AppUpdateStatus s : manager.getAll()) {
|
for (AppUpdateStatus s : manager.getAll()) {
|
||||||
if (s.status == AppUpdateStatusManager.Status.ReadyToInstall) {
|
if (s.status == AppUpdateStatusManager.Status.ReadyToInstall) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -341,4 +341,11 @@ public class UpdatesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If an item representing an {@link org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus} is dismissed,
|
||||||
|
* then we should rebuild the list of app statuses and update the adapter.
|
||||||
|
*/
|
||||||
|
public void refreshStatuses() {
|
||||||
|
onAppStatusRemoved();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
package org.fdroid.fdroid.views.updates;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.views.apps.AppListItemController;
|
||||||
|
import org.fdroid.fdroid.views.updates.items.AppStatusListItemController;
|
||||||
|
import org.fdroid.fdroid.views.updates.items.KnownVulnAppListItemController;
|
||||||
|
import org.fdroid.fdroid.views.updates.items.UpdateableAppListItemController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Certain views within the {@link UpdatesAdapter} can be swiped to dismiss. Depending on which item is swiped, there
|
||||||
|
* is a different behaviour, but all of it revolves around dismissing the item.
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* {@link KnownVulnAppListItemController}: Will be marked as "Ignored" and wont warn the user in the future.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* {@link UpdateableAppListItemController}: Will get marked as "Ignore this update".
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* {@link AppStatusListItemController}:
|
||||||
|
* <ul>
|
||||||
|
* <li>If downloading or queued to download, cancel the download.</li>
|
||||||
|
* <li>If downloaded waiting to install, forget that we downloaded it.</li>
|
||||||
|
* <li>If installed ready to run, stop prompting the user to run the app.</li>
|
||||||
|
* </ul>
|
||||||
|
* <li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public class UpdatesItemTouchCallback extends ItemTouchHelper.Callback {
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
private final UpdatesAdapter adapter;
|
||||||
|
|
||||||
|
public UpdatesItemTouchCallback(Context context, UpdatesAdapter adapter) {
|
||||||
|
this.context = context;
|
||||||
|
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;
|
||||||
|
DismissResult result = controller.onDismiss();
|
||||||
|
|
||||||
|
if (result.message != null) {
|
||||||
|
Toast.makeText(context, result.message, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.requiresAdapterRefresh) {
|
||||||
|
adapter.refreshStatuses();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isItemViewSwipeEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -4,6 +4,7 @@ import android.support.v4.widget.SwipeRefreshLayout;
|
|||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
@ -30,6 +31,9 @@ public class UpdatesViewBinder {
|
|||||||
list.setLayoutManager(new LinearLayoutManager(activity));
|
list.setLayoutManager(new LinearLayoutManager(activity));
|
||||||
list.setAdapter(adapter);
|
list.setAdapter(adapter);
|
||||||
|
|
||||||
|
ItemTouchHelper touchHelper = new ItemTouchHelper(new UpdatesItemTouchCallback(activity, adapter));
|
||||||
|
touchHelper.attachToRecyclerView(list);
|
||||||
|
|
||||||
emptyState = (TextView) view.findViewById(R.id.empty_state);
|
emptyState = (TextView) view.findViewById(R.id.empty_state);
|
||||||
emptyImage = (ImageView) view.findViewById(R.id.image);
|
emptyImage = (ImageView) view.findViewById(R.id.image);
|
||||||
|
|
||||||
|
@ -6,10 +6,12 @@ import android.support.annotation.Nullable;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.fdroid.fdroid.AppUpdateStatusManager;
|
import org.fdroid.fdroid.AppUpdateStatusManager;
|
||||||
|
import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.data.App;
|
import org.fdroid.fdroid.data.App;
|
||||||
import org.fdroid.fdroid.views.apps.AppListItemController;
|
import org.fdroid.fdroid.views.apps.AppListItemController;
|
||||||
import org.fdroid.fdroid.views.apps.AppListItemState;
|
import org.fdroid.fdroid.views.apps.AppListItemState;
|
||||||
|
import org.fdroid.fdroid.views.updates.DismissResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows apps which are:
|
* Shows apps which are:
|
||||||
@ -24,15 +26,14 @@ public class AppStatusListItemController extends AppListItemController {
|
|||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected AppListItemState getCurrentViewState(
|
protected AppListItemState getCurrentViewState(@NonNull App app, @Nullable AppUpdateStatus appStatus) {
|
||||||
@NonNull App app, @Nullable AppUpdateStatusManager.AppUpdateStatus appStatus) {
|
|
||||||
|
|
||||||
return super.getCurrentViewState(app, appStatus)
|
return super.getCurrentViewState(app, appStatus)
|
||||||
.setStatusText(getStatusText(appStatus));
|
.setStatusText(getStatusText(appStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private CharSequence getStatusText(@Nullable AppUpdateStatusManager.AppUpdateStatus appStatus) {
|
private CharSequence getStatusText(@Nullable AppUpdateStatus appStatus) {
|
||||||
if (appStatus != null) {
|
if (appStatus != null) {
|
||||||
switch (appStatus.status) {
|
switch (appStatus.status) {
|
||||||
case ReadyToInstall:
|
case ReadyToInstall:
|
||||||
@ -45,4 +46,34 @@ public class AppStatusListItemController extends AppListItemController {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canDismiss() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@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(message, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import org.fdroid.fdroid.installer.Installer;
|
|||||||
import org.fdroid.fdroid.installer.InstallerService;
|
import org.fdroid.fdroid.installer.InstallerService;
|
||||||
import org.fdroid.fdroid.views.apps.AppListItemController;
|
import org.fdroid.fdroid.views.apps.AppListItemController;
|
||||||
import org.fdroid.fdroid.views.apps.AppListItemState;
|
import org.fdroid.fdroid.views.apps.AppListItemState;
|
||||||
|
import org.fdroid.fdroid.views.updates.DismissResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the user that an app they have installed has a known vulnerability.
|
* Tell the user that an app they have installed has a known vulnerability.
|
||||||
@ -82,8 +83,23 @@ public class KnownVulnAppListItemController extends AppListItemController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canDismiss() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DismissResult onDismissApp(@NonNull App app) {
|
||||||
|
this.ignoreVulnerableApp(app);
|
||||||
|
return new DismissResult(activity.getString(R.string.app_list__dismiss_vulnerable_app), false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSecondaryButtonPressed(@NonNull App app) {
|
protected void onSecondaryButtonPressed(@NonNull App app) {
|
||||||
|
this.ignoreVulnerableApp(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ignoreVulnerableApp(@NonNull App app) {
|
||||||
AppPrefs prefs = app.getPrefs(activity);
|
AppPrefs prefs = app.getPrefs(activity);
|
||||||
prefs.ignoreVulnerabilities = true;
|
prefs.ignoreVulnerabilities = true;
|
||||||
AppPrefsProvider.Helper.update(activity, app, prefs);
|
AppPrefsProvider.Helper.update(activity, app, prefs);
|
||||||
|
@ -6,9 +6,13 @@ import android.support.annotation.Nullable;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.fdroid.fdroid.AppUpdateStatusManager;
|
import org.fdroid.fdroid.AppUpdateStatusManager;
|
||||||
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.data.App;
|
import org.fdroid.fdroid.data.App;
|
||||||
|
import org.fdroid.fdroid.data.AppPrefs;
|
||||||
|
import org.fdroid.fdroid.data.AppPrefsProvider;
|
||||||
import org.fdroid.fdroid.views.apps.AppListItemController;
|
import org.fdroid.fdroid.views.apps.AppListItemController;
|
||||||
import org.fdroid.fdroid.views.apps.AppListItemState;
|
import org.fdroid.fdroid.views.apps.AppListItemState;
|
||||||
|
import org.fdroid.fdroid.views.updates.DismissResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Very trimmed down list item. Only displays the app icon, name, and a download button.
|
* Very trimmed down list item. Only displays the app icon, name, and a download button.
|
||||||
@ -28,4 +32,21 @@ public class UpdateableAppListItemController extends AppListItemController {
|
|||||||
return new AppListItemState(app)
|
return new AppListItemState(app)
|
||||||
.setShowInstallButton(true);
|
.setShowInstallButton(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canDismiss() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
protected DismissResult onDismissApp(@NonNull App app) {
|
||||||
|
AppPrefs prefs = app.getPrefs(activity);
|
||||||
|
prefs.ignoreThisUpdate = app.suggestedVersionCode;
|
||||||
|
|
||||||
|
// The act of updating here will trigger a re-query of the "can update" apps, so no need to do anything else
|
||||||
|
// to update the UI in response to this.
|
||||||
|
AppPrefsProvider.Helper.update(activity, app, prefs);
|
||||||
|
return new DismissResult(activity.getString(R.string.app_list__dismiss_app_update), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,9 @@ This often occurs with apps installed via Google Play or other sources, if they
|
|||||||
<string name="app_list__name__downloading_in_progress">Downloading %1$s</string>
|
<string name="app_list__name__downloading_in_progress">Downloading %1$s</string>
|
||||||
<string name="app_list__name__successfully_installed">%1$s installed</string>
|
<string name="app_list__name__successfully_installed">%1$s installed</string>
|
||||||
<string name="app_list_download_ready">Downloaded, ready to install</string>
|
<string name="app_list_download_ready">Downloaded, ready to install</string>
|
||||||
|
<string name="app_list__dismiss_app_update">Update ignored</string>
|
||||||
|
<string name="app_list__dismiss_vulnerable_app">Vulnerability ignored</string>
|
||||||
|
<string name="app_list__dismiss_downloading_app">Download canceled</string>
|
||||||
|
|
||||||
<string name="installed_apps__activity_title">Installed Apps</string>
|
<string name="installed_apps__activity_title">Installed Apps</string>
|
||||||
<string name="installed_app__updates_ignored">Updates ignored</string>
|
<string name="installed_app__updates_ignored">Updates ignored</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user