Merge branch 'new-ui--feedback-from-alpha' into 'master'
Implement a handful of UX tweaks in response to alpha feedback Closes #879 See merge request !464
This commit is contained in:
commit
e28e29455e
@ -9,8 +9,10 @@ import android.content.DialogInterface;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.database.ContentObserver;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.support.design.widget.AppBarLayout;
|
import android.support.design.widget.AppBarLayout;
|
||||||
import android.support.design.widget.CoordinatorLayout;
|
import android.support.design.widget.CoordinatorLayout;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
@ -188,6 +190,13 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog
|
|||||||
if (app != null) {
|
if (app != null) {
|
||||||
visiblePackageName = app.packageName;
|
visiblePackageName = app.packageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
appObserver = new AppObserver(new Handler());
|
||||||
|
getContentResolver().registerContentObserver(
|
||||||
|
AppProvider.getHighestPriorityMetadataUri(app.packageName),
|
||||||
|
true,
|
||||||
|
appObserver);
|
||||||
|
|
||||||
updateNotificationsForApp();
|
updateNotificationsForApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,6 +204,8 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog
|
|||||||
super.onStop();
|
super.onStop();
|
||||||
visiblePackageName = null;
|
visiblePackageName = null;
|
||||||
|
|
||||||
|
getContentResolver().unregisterContentObserver(appObserver);
|
||||||
|
|
||||||
// When leaving the app details, make sure to refresh app status for this app, since
|
// When leaving the app details, make sure to refresh app status for this app, since
|
||||||
// we might want to show notifications for it now.
|
// we might want to show notifications for it now.
|
||||||
updateNotificationsForApp();
|
updateNotificationsForApp();
|
||||||
@ -432,7 +443,9 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog
|
|||||||
case Installer.ACTION_INSTALL_COMPLETE:
|
case Installer.ACTION_INSTALL_COMPLETE:
|
||||||
adapter.clearProgress();
|
adapter.clearProgress();
|
||||||
unregisterInstallReceiver();
|
unregisterInstallReceiver();
|
||||||
onAppChanged();
|
// Don't try and update the view here, because the InstalledAppProviderService
|
||||||
|
// hasn't had time to do its thing and mark the app as installed. Instead, we
|
||||||
|
// wait for that service to notify us, and then we will respond in appObserver.
|
||||||
break;
|
break;
|
||||||
case Installer.ACTION_INSTALL_INTERRUPTED:
|
case Installer.ACTION_INSTALL_INTERRUPTED:
|
||||||
adapter.clearProgress();
|
adapter.clearProgress();
|
||||||
@ -457,8 +470,14 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog
|
|||||||
unregisterInstallReceiver();
|
unregisterInstallReceiver();
|
||||||
break;
|
break;
|
||||||
case Installer.ACTION_INSTALL_USER_INTERACTION:
|
case Installer.ACTION_INSTALL_USER_INTERACTION:
|
||||||
PendingIntent installPendingIntent =
|
Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK);
|
||||||
intent.getParcelableExtra(Installer.EXTRA_USER_INTERACTION_PI);
|
if (!isAppVisible(apk.packageName)) {
|
||||||
|
Utils.debugLog(TAG, "Ignore request for user interaction from installer, because " + apk.packageName + " is no longer showing.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils.debugLog(TAG, "Automatically showing package manager for " + apk.packageName + " as it is being viewed by the user.");
|
||||||
|
PendingIntent installPendingIntent = intent.getParcelableExtra(Installer.EXTRA_USER_INTERACTION_PI);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
installPendingIntent.send();
|
installPendingIntent.send();
|
||||||
@ -649,4 +668,26 @@ public class AppDetails2 extends AppCompatActivity implements ShareChooserDialog
|
|||||||
}
|
}
|
||||||
startUninstall();
|
startUninstall();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// observer to update view when package has been installed/deleted
|
||||||
|
private AppObserver appObserver;
|
||||||
|
|
||||||
|
class AppObserver extends ContentObserver {
|
||||||
|
|
||||||
|
AppObserver(Handler handler) {
|
||||||
|
super(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChange(boolean selfChange) {
|
||||||
|
onChange(selfChange, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChange(boolean selfChange, Uri uri) {
|
||||||
|
onAppChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -330,14 +330,13 @@ class NotificationHelper {
|
|||||||
App app = entry.app;
|
App app = entry.app;
|
||||||
AppUpdateStatusManager.Status status = entry.status;
|
AppUpdateStatusManager.Status status = entry.status;
|
||||||
|
|
||||||
int iconSmall = R.drawable.ic_launcher;
|
|
||||||
Bitmap iconLarge = getLargeIconForEntry(entry);
|
Bitmap iconLarge = getLargeIconForEntry(entry);
|
||||||
NotificationCompat.Builder builder =
|
NotificationCompat.Builder builder =
|
||||||
new NotificationCompat.Builder(context)
|
new NotificationCompat.Builder(context)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setContentTitle(getSingleItemTitleString(app, status))
|
.setContentTitle(getSingleItemTitleString(app, status))
|
||||||
.setContentText(getSingleItemContentString(app, status))
|
.setContentText(getSingleItemContentString(app, status))
|
||||||
.setSmallIcon(iconSmall)
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
||||||
.setLargeIcon(iconLarge)
|
.setLargeIcon(iconLarge)
|
||||||
.setLocalOnly(true)
|
.setLocalOnly(true)
|
||||||
@ -416,7 +415,7 @@ class NotificationHelper {
|
|||||||
NotificationCompat.Builder builder =
|
NotificationCompat.Builder builder =
|
||||||
new NotificationCompat.Builder(context)
|
new NotificationCompat.Builder(context)
|
||||||
.setAutoCancel(!useStackedNotifications())
|
.setAutoCancel(!useStackedNotifications())
|
||||||
.setSmallIcon(R.drawable.ic_launcher)
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
||||||
.setContentTitle(title)
|
.setContentTitle(title)
|
||||||
.setContentText(text)
|
.setContentText(text)
|
||||||
@ -444,7 +443,7 @@ class NotificationHelper {
|
|||||||
new NotificationCompat.Builder(context)
|
new NotificationCompat.Builder(context)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setLargeIcon(iconLarge)
|
.setLargeIcon(iconLarge)
|
||||||
.setSmallIcon(R.drawable.ic_launcher)
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
||||||
.setContentTitle(app.name)
|
.setContentTitle(app.name)
|
||||||
.setContentText(context.getString(R.string.notification_content_single_installed))
|
.setContentText(context.getString(R.string.notification_content_single_installed))
|
||||||
@ -491,7 +490,7 @@ class NotificationHelper {
|
|||||||
NotificationCompat.Builder builder =
|
NotificationCompat.Builder builder =
|
||||||
new NotificationCompat.Builder(context)
|
new NotificationCompat.Builder(context)
|
||||||
.setAutoCancel(!useStackedNotifications())
|
.setAutoCancel(!useStackedNotifications())
|
||||||
.setSmallIcon(R.drawable.ic_launcher)
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
.setColor(ContextCompat.getColor(context, R.color.fdroid_blue))
|
||||||
.setContentTitle(title)
|
.setContentTitle(title)
|
||||||
.setContentText(text)
|
.setContentText(text)
|
||||||
|
@ -21,7 +21,6 @@ import java.io.FilenameFilter;
|
|||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import rx.functions.Action1;
|
import rx.functions.Action1;
|
||||||
import rx.schedulers.Schedulers;
|
import rx.schedulers.Schedulers;
|
||||||
@ -64,7 +63,7 @@ public class InstalledAppProviderService extends IntentService {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
notifyEvents = PublishSubject.create();
|
notifyEvents = PublishSubject.create();
|
||||||
notifyEvents.debounce(1, TimeUnit.SECONDS)
|
notifyEvents
|
||||||
.subscribeOn(Schedulers.newThread())
|
.subscribeOn(Schedulers.newThread())
|
||||||
.subscribe(new Action1<Void>() {
|
.subscribe(new Action1<Void>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -35,7 +35,6 @@ import android.widget.Toast;
|
|||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
|
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
|
||||||
import org.fdroid.fdroid.BuildConfig;
|
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
@ -413,15 +412,12 @@ public class AppDetailsRecyclerViewAdapter
|
|||||||
} else {
|
} else {
|
||||||
lastUpdateView.setVisibility(View.GONE);
|
lastUpdateView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Apk suggestedApk = getSuggestedApk();
|
Apk suggestedApk = getSuggestedApk();
|
||||||
// TODO replace this whatsNew test code with what comes from suggestedApk once that exists
|
|
||||||
//if (suggestedApk == null || TextUtils.isEmpty(suggestedApk.whatsNew)) {
|
// TODO populate whatsNew with suggestedApk.whatsNew once that exists
|
||||||
String whatsNew = null;
|
String whatsNew = null;
|
||||||
if (BuildConfig.DEBUG) {
|
//noinspection ConstantConditions
|
||||||
if (Math.random() > 0.5) {
|
|
||||||
whatsNew = "This section will contain the 'what's new' information for the apk.\n\n\t• Bug fixes.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (suggestedApk == null || TextUtils.isEmpty(whatsNew)) {
|
if (suggestedApk == null || TextUtils.isEmpty(whatsNew)) {
|
||||||
whatsNewView.setVisibility(View.GONE);
|
whatsNewView.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
@ -431,7 +427,7 @@ public class AppDetailsRecyclerViewAdapter
|
|||||||
StringBuilder sbWhatsNew = new StringBuilder();
|
StringBuilder sbWhatsNew = new StringBuilder();
|
||||||
sbWhatsNew.append(whatsNewView.getContext().getString(R.string.details_new_in_version, suggestedApk.versionName).toUpperCase(locale));
|
sbWhatsNew.append(whatsNewView.getContext().getString(R.string.details_new_in_version, suggestedApk.versionName).toUpperCase(locale));
|
||||||
sbWhatsNew.append("\n\n");
|
sbWhatsNew.append("\n\n");
|
||||||
sbWhatsNew.append("This section will contain the 'what's new' information for the apk.\n\n\t• Bug fixes.");
|
sbWhatsNew.append(whatsNew);
|
||||||
whatsNewView.setText(sbWhatsNew);
|
whatsNewView.setText(sbWhatsNew);
|
||||||
whatsNewView.setVisibility(View.VISIBLE);
|
whatsNewView.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ public class AppListActivity extends AppCompatActivity implements LoaderManager.
|
|||||||
Schema.AppMetadataTable.Cols.ALL,
|
Schema.AppMetadataTable.Cols.ALL,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null
|
Schema.AppMetadataTable.Cols.NAME
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,14 +448,15 @@ public class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
private final BroadcastReceiver onInstallAction = new BroadcastReceiver() {
|
private final BroadcastReceiver onInstallAction = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (currentApp == null || installButton == null) {
|
Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK);
|
||||||
|
if (currentApp == null || !TextUtils.equals(apk.packageName, currentApp.packageName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
configureAppName(currentApp);
|
configureAppName(currentApp);
|
||||||
|
configureActionButton(currentApp);
|
||||||
|
|
||||||
Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK);
|
if (installButton == null) {
|
||||||
if (!TextUtils.equals(apk.packageName, currentApp.packageName)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ public class CategoryController extends RecyclerView.ViewHolder implements Loade
|
|||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null
|
Schema.AppMetadataTable.Cols.NAME
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,9 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.LoaderManager;
|
|
||||||
import android.support.v4.content.CursorLoader;
|
|
||||||
import android.support.v4.content.Loader;
|
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
@ -32,9 +28,7 @@ import org.fdroid.fdroid.R;
|
|||||||
import org.fdroid.fdroid.UpdateService;
|
import org.fdroid.fdroid.UpdateService;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.compat.UriCompat;
|
import org.fdroid.fdroid.compat.UriCompat;
|
||||||
import org.fdroid.fdroid.data.AppProvider;
|
|
||||||
import org.fdroid.fdroid.data.NewRepoConfig;
|
import org.fdroid.fdroid.data.NewRepoConfig;
|
||||||
import org.fdroid.fdroid.data.Schema;
|
|
||||||
import org.fdroid.fdroid.views.ManageReposActivity;
|
import org.fdroid.fdroid.views.ManageReposActivity;
|
||||||
import org.fdroid.fdroid.views.apps.AppListActivity;
|
import org.fdroid.fdroid.views.apps.AppListActivity;
|
||||||
import org.fdroid.fdroid.views.swap.SwapWorkflowActivity;
|
import org.fdroid.fdroid.views.swap.SwapWorkflowActivity;
|
||||||
@ -53,8 +47,7 @@ import org.fdroid.fdroid.views.swap.SwapWorkflowActivity;
|
|||||||
* When switching from one screen to the next, we stay within this activity. The new screen will
|
* When switching from one screen to the next, we stay within this activity. The new screen will
|
||||||
* get inflated (if required)
|
* get inflated (if required)
|
||||||
*/
|
*/
|
||||||
public class MainActivity extends AppCompatActivity implements BottomNavigationBar.OnTabSelectedListener,
|
public class MainActivity extends AppCompatActivity implements BottomNavigationBar.OnTabSelectedListener {
|
||||||
LoaderManager.LoaderCallbacks<Cursor> {
|
|
||||||
|
|
||||||
private static final String TAG = "MainActivity";
|
private static final String TAG = "MainActivity";
|
||||||
|
|
||||||
@ -66,8 +59,6 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB
|
|||||||
|
|
||||||
private static final String STATE_SELECTED_MENU_ID = "selectedMenuId";
|
private static final String STATE_SELECTED_MENU_ID = "selectedMenuId";
|
||||||
|
|
||||||
private static final int LOADER_NUM_UPDATES = 1;
|
|
||||||
|
|
||||||
private static final int REQUEST_SWAP = 3;
|
private static final int REQUEST_SWAP = 3;
|
||||||
|
|
||||||
private RecyclerView pager;
|
private RecyclerView pager;
|
||||||
@ -89,7 +80,7 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB
|
|||||||
pager.setLayoutManager(new NonScrollingHorizontalLayoutManager(this));
|
pager.setLayoutManager(new NonScrollingHorizontalLayoutManager(this));
|
||||||
pager.setAdapter(adapter);
|
pager.setAdapter(adapter);
|
||||||
|
|
||||||
updatesBadge = new BadgeItem();
|
updatesBadge = new BadgeItem().hide(false);
|
||||||
|
|
||||||
bottomNavigation = (BottomNavigationBar) findViewById(R.id.bottom_navigation);
|
bottomNavigation = (BottomNavigationBar) findViewById(R.id.bottom_navigation);
|
||||||
bottomNavigation.setTabSelectedListener(this)
|
bottomNavigation.setTabSelectedListener(this)
|
||||||
@ -105,8 +96,8 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB
|
|||||||
.initialise();
|
.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);
|
||||||
LocalBroadcastManager.getInstance(this).registerReceiver(onUpdateableAppsChanged, updateableAppsFilter);
|
LocalBroadcastManager.getInstance(this).registerReceiver(onUpdateableAppsChanged, updateableAppsFilter);
|
||||||
getSupportLoaderManager().initLoader(LOADER_NUM_UPDATES, null, this);
|
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
selectedMenuId = savedInstanceState.getInt(STATE_SELECTED_MENU_ID, R.id.whats_new);
|
selectedMenuId = savedInstanceState.getInt(STATE_SELECTED_MENU_ID, R.id.whats_new);
|
||||||
@ -319,22 +310,6 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
|
||||||
Uri uri = AppProvider.getCanUpdateUri();
|
|
||||||
String[] projection = new String[]{Schema.AppMetadataTable.Cols._COUNT};
|
|
||||||
|
|
||||||
return new CursorLoader(this, uri, projection, null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
|
||||||
cursor.moveToFirst();
|
|
||||||
int canUpdateCount = cursor.getInt(cursor.getColumnIndex(Schema.AppMetadataTable.Cols._COUNT));
|
|
||||||
cursor.close();
|
|
||||||
refreshUpdatesBadge(canUpdateCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshUpdatesBadge(int canUpdateCount) {
|
private void refreshUpdatesBadge(int canUpdateCount) {
|
||||||
if (canUpdateCount == 0) {
|
if (canUpdateCount == 0) {
|
||||||
updatesBadge.hide(true);
|
updatesBadge.hide(true);
|
||||||
@ -344,11 +319,6 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoaderReset(Loader<Cursor> loader) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class NonScrollingHorizontalLayoutManager extends LinearLayoutManager {
|
private static class NonScrollingHorizontalLayoutManager extends LinearLayoutManager {
|
||||||
NonScrollingHorizontalLayoutManager(Context context) {
|
NonScrollingHorizontalLayoutManager(Context context) {
|
||||||
super(context, LinearLayoutManager.HORIZONTAL, false);
|
super(context, LinearLayoutManager.HORIZONTAL, false);
|
||||||
@ -365,11 +335,43 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There are a bunch of reasons why we would get notified about app statuses.
|
||||||
|
* The ones we are interested in are those which would result in the "items requiring user interaction"
|
||||||
|
* to increase or decrease:
|
||||||
|
* * Bulk updates of ready-to-install-apps (relating to {@link org.fdroid.fdroid.AppUpdateStatusService}.
|
||||||
|
* * Change in status to:
|
||||||
|
* * {@link AppUpdateStatusManager.Status#ReadyToInstall} (Causes the count to go UP by one)
|
||||||
|
* * {@link AppUpdateStatusManager.Status#Installed} (Causes the count to go DOWN by one)
|
||||||
|
*/
|
||||||
private final BroadcastReceiver onUpdateableAppsChanged = new BroadcastReceiver() {
|
private final BroadcastReceiver onUpdateableAppsChanged = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (AppUpdateStatusManager.REASON_UPDATES_AVAILABLE.equals(intent.getStringExtra(AppUpdateStatusManager.EXTRA_REASON_FOR_CHANGE))) {
|
boolean updateBadge = false;
|
||||||
getSupportLoaderManager().restartLoader(LOADER_NUM_UPDATES, null, MainActivity.this);
|
|
||||||
|
AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(context);
|
||||||
|
|
||||||
|
if (AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED.equals(intent.getAction()) &&
|
||||||
|
AppUpdateStatusManager.REASON_READY_TO_INSTALL.equals(intent.getStringExtra(AppUpdateStatusManager.EXTRA_REASON_FOR_CHANGE))) {
|
||||||
|
updateBadge = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we have moved into the ReadyToInstall or Installed state.
|
||||||
|
AppUpdateStatusManager.AppUpdateStatus status = manager.get(intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL));
|
||||||
|
boolean isStatusChange = intent.getBooleanExtra(AppUpdateStatusManager.EXTRA_IS_STATUS_UPDATE, false);
|
||||||
|
if (isStatusChange && status != null && (status.status == AppUpdateStatusManager.Status.ReadyToInstall || status.status == AppUpdateStatusManager.Status.Installed)) {
|
||||||
|
updateBadge = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateBadge) {
|
||||||
|
int count = 0;
|
||||||
|
for (AppUpdateStatusManager.AppUpdateStatus s : manager.getAll()) {
|
||||||
|
if (s.status == AppUpdateStatusManager.Status.ReadyToInstall) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshUpdatesBadge(count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
7
app/src/main/res/drawable/ic_notification.xml
Normal file
7
app/src/main/res/drawable/ic_notification.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<vector android:height="24dp" android:viewportHeight="48.0"
|
||||||
|
android:viewportWidth="48.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillAlpha="1" android:fillColor="#ffffff"
|
||||||
|
android:pathData="m2.61,1.25c-0.45,0.01 -0.76,0.19 -0.98,0.45 0,0 0,0 0.01,0.01 -0,0 -0.01,0.01 -0.01,0.01 -0,-0 -0,-0 -0,-0.01 -0,0 -0.01,0.02 -0.02,0.03 -0.01,0.01 -0.01,0.02 -0.02,0.03 -0.15,0.2 -0.49,0.8 0.01,1.5L5.21,7.93C5.08,8.26 5,8.62 5,9v3,1 2.46L5,16c0,1.66 1.34,3 3,3h32c1.66,0 3,-1.34 3,-3L43,15.46 43,9.54 43,9C43,8.62 42.92,8.26 42.79,7.93l3.61,-4.66c0.5,-0.7 0.16,-1.3 0.01,-1.5 -0.01,-0.01 -0.01,-0.02 -0.02,-0.03 -0,-0.01 -0.01,-0.02 -0.02,-0.03 -0,0 -0,0 -0,0.01 -0,-0 -0.01,-0.01 -0.01,-0.01 0,-0 0,-0 0.01,-0.01 -0.22,-0.26 -0.53,-0.44 -0.98,-0.45 -0.38,0.01 -0.74,0.18 -0.97,0.49L40.99,6.18C40.86,6.13 40.74,6.09 40.61,6.06 40.41,6.02 40.21,6 40,6L8,6C7.65,6 7.32,6.07 7.01,6.18L3.58,1.74C3.35,1.43 2.99,1.26 2.61,1.25ZM14.38,9.75c1.86,0 3.38,1.51 3.38,3.38 0,1.86 -1.51,3.38 -3.38,3.38C12.51,16.5 11,14.99 11,13.13 11,11.26 12.51,9.75 14.38,9.75ZM33.88,9.75c1.86,0 3.38,1.51 3.38,3.38 0,1.86 -1.51,3.38 -3.38,3.38 -1.86,0 -3.38,-1.51 -3.38,-3.38 0,-1.86 1.51,-3.38 3.38,-3.38zM8,20.97c-1.66,0 -3,1.34 -3,3L5,30 5,36 5,42.23 5,43c0,1.66 1.34,3 3,3h32c1.66,0 3,-1.34 3,-3L43,42.23 43,24.73 43,23.97c0,-1.66 -1.34,-3 -3,-3z"
|
||||||
|
android:strokeAlpha="1" android:strokeColor="#00000000"
|
||||||
|
android:strokeLineCap="round" android:strokeLineJoin="miter" android:strokeWidth="2.5"/>
|
||||||
|
</vector>
|
@ -35,6 +35,8 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@+id/header_height"
|
app:layout_constraintTop_toTopOf="@+id/header_height"
|
||||||
|
android:foreground="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
>
|
>
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout
|
<android.support.constraint.ConstraintLayout
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:foreground="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true">
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout
|
<android.support.constraint.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="220dp">
|
android:layout_height="220dp"
|
||||||
|
android:foreground="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true">
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout
|
<android.support.constraint.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:foreground="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true">
|
||||||
|
|
||||||
<android.support.constraint.ConstraintLayout
|
<android.support.constraint.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="true"
|
||||||
|
android:background="?attr/selectableItemBackground">
|
||||||
|
|
||||||
<!-- Ignore ContentDescription because it is kind of meaningless to have TTS read out "App icon"
|
<!-- Ignore ContentDescription because it is kind of meaningless to have TTS read out "App icon"
|
||||||
when it will inevitably read out the name of the app straight after. -->
|
when it will inevitably read out the name of the app straight after. -->
|
||||||
|
@ -78,10 +78,6 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingTop="@dimen/category_preview__app_list__padding__vertical"
|
android:paddingTop="@dimen/category_preview__app_list__padding__vertical"
|
||||||
android:paddingBottom="@dimen/category_preview__app_list__padding__vertical"
|
android:paddingBottom="@dimen/category_preview__app_list__padding__vertical"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false" />
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
android:layout_marginRight="8dp"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="8dp" />
|
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
@ -7,7 +7,9 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="4dp"
|
android:padding="4dp"
|
||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingBottom="8dp">
|
android:paddingBottom="8dp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:background="?attr/selectableItemBackground">
|
||||||
|
|
||||||
<!-- Ignore ContentDescription because it is kind of meaningless to have TTS read out "App icon"
|
<!-- Ignore ContentDescription because it is kind of meaningless to have TTS read out "App icon"
|
||||||
when it will inevitably read out the name of the app straight after. -->
|
when it will inevitably read out the name of the app straight after. -->
|
||||||
|
Loading…
x
Reference in New Issue
Block a user