Enhance AppList UI/UX

This commit is contained in:
Mr. Dragon
2018-05-07 00:05:47 +05:30
parent 972ca01988
commit a3d498cb51
28 changed files with 672 additions and 381 deletions

View File

@@ -18,27 +18,27 @@ public class UpdateAllReceiver extends BroadcastReceiver {
static public final String EXTRA_PACKAGE_NAME = "EXTRA_PACKAGE_NAME";
static public final String EXTRA_UPDATE_ACTUALLY_INSTALLED = "EXTRA_UPDATE_ACTUALLY_INSTALLED";
private UpdatableAppsFragment fragment;
private UpdatableAppsFragment updatableAppsFragment;
public UpdateAllReceiver(UpdatableAppsFragment fragment) {
this.fragment = fragment;
public UpdateAllReceiver(UpdatableAppsFragment updatableAppsFragment) {
this.updatableAppsFragment = updatableAppsFragment;
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_ALL_UPDATES_COMPLETE);
filter.addAction(ACTION_APP_UPDATE_COMPLETE);
fragment.getActivity().registerReceiver(this, filter);
if (!((AuroraApplication) fragment.getActivity().getApplication()).isBackgroundUpdating()) {
updatableAppsFragment.getContext().registerReceiver(this, filter);
if (!((AuroraApplication) updatableAppsFragment.getActivity().getApplication()).isBackgroundUpdating()) {
enableButton();
}
fragment.getActivity().unregisterReceiver(this);
updatableAppsFragment.getActivity().unregisterReceiver(this);
}
@Override
public void onReceive(Context context, Intent intent) {
if (!ContextUtil.isAlive(fragment.getActivity()) || TextUtils.isEmpty(intent.getAction())) {
if (!ContextUtil.isAlive(updatableAppsFragment.getActivity()) || TextUtils.isEmpty(intent.getAction())) {
return;
}
if (intent.getAction().equals(ACTION_ALL_UPDATES_COMPLETE)) {
((AuroraApplication) fragment.getActivity().getApplication()).setBackgroundUpdating(false);
((AuroraApplication) updatableAppsFragment.getActivity().getApplication()).setBackgroundUpdating(false);
enableButton();
} else if (intent.getAction().equals(ACTION_APP_UPDATE_COMPLETE)) {
processAppUpdate(
@@ -49,19 +49,16 @@ public class UpdateAllReceiver extends BroadcastReceiver {
}
private void enableButton() {
Button button = (Button) fragment.getActivity().findViewById(R.id.update_all);
TextView textView = (TextView) fragment.getActivity().findViewById(R.id.updates_txt);
Button button = updatableAppsFragment.getView().findViewById(R.id.update_all);
if (null != button) {
button.setEnabled(true);
textView.setEnabled(true);
button.setText(R.string.list_update_all);
textView.setText(R.string.list_update_chk_txt);
}
}
private void processAppUpdate(String packageName, boolean installedUpdate) {
if (installedUpdate) {
fragment.removeApp(packageName);
updatableAppsFragment.updatableAppsAdapter.remove(packageName);
}
}
}

View File

@@ -4,7 +4,11 @@ import android.content.Context;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import com.dragons.aurora.downloader.DownloadState;
import com.dragons.aurora.model.App;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
@@ -119,4 +123,24 @@ public class Util {
}
return tempValue + diPrefixes.get(order);
}
public static boolean isAlreadyDownloaded(Context context, App app) {
return Paths.getApkPath(context, app.getPackageName(), app.getVersionCode()).exists()
&& DownloadState.get(app.getPackageName()).isEverythingSuccessful();
}
public static boolean shouldDownload(Context context, App app) {
File apk = Paths.getApkPath(context, app.getPackageName(), app.getVersionCode());
return (!apk.exists() || apk.length() != app.getSize() || !DownloadState.get(app.getPackageName()).isEverythingSuccessful())
&& (app.isInPlayStore() || app.getPackageName().equals(BuildConfig.APPLICATION_ID));
}
public static boolean isAlreadyQueued(App app) {
DownloadState state = DownloadState.get(app.getPackageName());
if (state != null && !state.isEverythingFinished())
return true;
else
return false;
}
}

View File

@@ -11,7 +11,6 @@ import android.widget.EditText;
import android.widget.TextView;
import com.dragons.aurora.R;
import com.dragons.aurora.fragment.DetailsFragment;
import com.dragons.aurora.fragment.details.DownloadOrInstall;
import com.dragons.aurora.model.App;
import com.dragons.aurora.task.playstore.PurchaseCheckTask;
@@ -22,6 +21,7 @@ import java.util.TimerTask;
public class ManualDownloadActivity extends DetailsActivity {
public static App app;
private int latestVersionCode;
@Override
@@ -34,19 +34,19 @@ public class ManualDownloadActivity extends DetailsActivity {
@Override
protected void onNewIntent(Intent intent) {
if (null == DetailsFragment.app) {
if (null == app) {
Log.e(getClass().getSimpleName(), "No app stored");
finish();
return;
}
latestVersionCode = DetailsFragment.app.getVersionCode();
draw(DetailsFragment.app);
latestVersionCode = app.getVersionCode();
draw(app);
}
@Override
protected void onPause() {
super.onPause();
DetailsFragment.app.setVersionCode(latestVersionCode);
app.setVersionCode(latestVersionCode);
}
private void draw(App app) {

View File

@@ -53,6 +53,7 @@ public class InstalledAppsAdapter extends RecyclerView.Adapter<InstalledAppsAdap
public void onBindViewHolder(@NonNull InstalledAppsAdapter.ViewHolder holder, int position) {
final App app = appsToAdd.get(position);
final InstalledAppBadge installedAppBadge = new InstalledAppBadge();
installedAppBadge.setApp(app);
installedAppBadge.setView(holder.view);
installedAppBadge.draw();
@@ -68,6 +69,7 @@ public class InstalledAppsAdapter extends RecyclerView.Adapter<InstalledAppsAdap
new DownloadOptions((AuroraActivity) context, app).inflate(popup.getMenu());
popup.getMenu().findItem(R.id.action_download).setVisible(new ButtonDownload((AuroraActivity) context, app).shouldBeVisible());
popup.getMenu().findItem(R.id.action_uninstall).setVisible(app.isInstalled());
popup.getMenu().findItem(R.id.action_manual).setVisible(app.isInstalled());
popup.setOnMenuItemClickListener(item -> {
switch (item.getItemId()) {
case R.id.action_ignore:
@@ -85,6 +87,7 @@ public class InstalledAppsAdapter extends RecyclerView.Adapter<InstalledAppsAdap
new ButtonUninstall((AuroraActivity) context, app).uninstall();
remove(position);
break;
case R.id.action_manual:
default:
return new DownloadOptions((AuroraActivity) context, app).onContextItemSelected(item);
}

View File

@@ -9,7 +9,6 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import com.dragons.aurora.R;
import com.dragons.aurora.activities.DetailsActivity;
import com.dragons.aurora.model.App;
import com.dragons.aurora.view.UpdatableAppBadge;
@@ -34,6 +33,17 @@ public class UpdatableAppsAdapter extends RecyclerView.Adapter<UpdatableAppsAdap
notifyItemRemoved(position);
}
public void remove(String packageName) {
int i = 0;
for (App app : appsToAdd) {
if (app.getPackageName().equals(packageName)) {
remove(i);
break;
}
i++;
}
}
@NonNull
@Override
public UpdatableAppsAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@@ -50,13 +60,9 @@ public class UpdatableAppsAdapter extends RecyclerView.Adapter<UpdatableAppsAdap
updatableAppBadge.setApp(app);
updatableAppBadge.setView(holder.view);
updatableAppBadge.draw();
updatableAppBadge.drawButtons();
holder.app = app;
holder.list_container.setOnClickListener(v -> {
Context context = holder.view.getContext();
context.startActivity(DetailsActivity.getDetailsIntent(context, app.getPackageName()));
});
}
@Override
@@ -68,14 +74,11 @@ public class UpdatableAppsAdapter extends RecyclerView.Adapter<UpdatableAppsAdap
public LinearLayout viewForeground;
public App app;
private View view;
private LinearLayout list_container;
public ViewHolder(View view) {
super(view);
this.view = view;
list_container = view.findViewById(R.id.list_container);
viewForeground = view.findViewById(R.id.view_foreground);
}
}

View File

@@ -53,32 +53,23 @@ public class FlagDialogBuilder {
.setTitle(R.string.flag_page_description)
.setNegativeButton(
android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}
(dialog, which) -> dialog.dismiss()
)
.setAdapter(
new ArrayAdapter<>(activity, android.R.layout.select_dialog_item, reasonLabels),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
FlagTask task = new FlagTask();
task.setContext(activity);
task.setApp(app);
GooglePlayAPI.ABUSE reason = reasonIds[which];
task.setReason(reason);
if (reason == GooglePlayAPI.ABUSE.HARMFUL_TO_DEVICE_OR_DATA || reason == GooglePlayAPI.ABUSE.OTHER) {
new ExplanationDialogBuilder().setContext(activity).setTask(task).setReason(reason).build().show();
} else {
task.execute();
}
dialog.dismiss();
.setAdapter(new ArrayAdapter<>(activity, android.R.layout.select_dialog_singlechoice, reasonLabels),
(dialog, which) -> {
FlagTask task = new FlagTask();
task.setContext(activity);
task.setApp(app);
GooglePlayAPI.ABUSE reason = reasonIds[which];
task.setReason(reason);
if (reason == GooglePlayAPI.ABUSE.HARMFUL_TO_DEVICE_OR_DATA || reason == GooglePlayAPI.ABUSE.OTHER) {
new ExplanationDialogBuilder().setContext(activity).setTask(task).setReason(reason).build().show();
} else {
task.execute();
}
dialog.dismiss();
}
)
.create()
;
).create();
}
private static class ExplanationDialogBuilder {
@@ -112,25 +103,16 @@ public class FlagDialogBuilder {
.setView(editText)
.setNegativeButton(
android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}
(dialog, which) -> dialog.dismiss()
)
.setPositiveButton(
android.R.string.yes,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
task.setExplanation(editText.getText().toString());
task.execute();
dialog.dismiss();
}
(dialog, which) -> {
task.setExplanation(editText.getText().toString());
task.execute();
dialog.dismiss();
}
)
.create()
;
).create();
}
}
}

View File

@@ -0,0 +1,76 @@
package com.dragons.aurora.downloader;
import android.content.Context;
import android.util.Pair;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.dragons.aurora.Util;
import com.dragons.aurora.task.RepeatingTask;
import com.dragons.aurora.view.UpdatableAppBadge;
public class DownloadProgressBarUpdaterList extends RepeatingTask {
private Context context;
private String packageName;
private UpdatableAppBadge updatableAppBadge;
public DownloadProgressBarUpdaterList(Context context, UpdatableAppBadge updatableAppBadge) {
this.context = context;
this.packageName = updatableAppBadge.getApp().getPackageName();
this.updatableAppBadge = updatableAppBadge;
}
@Override
protected boolean shouldRunAgain() {
DownloadState state = DownloadState.get(packageName);
return null != state && !state.isEverythingFinished();
}
@Override
protected void payload() {
ProgressBar progressBar = updatableAppBadge.progressBar;
TextView progressCents = updatableAppBadge.progressCents;
if (null == progressBar) {
return;
}
DownloadState state = DownloadState.get(packageName);
if (null == state || state.isEverythingFinished()) {
progressBar.setVisibility(View.GONE);
progressCents.setVisibility(View.GONE);
progressBar.setIndeterminate(true);
if (Util.isAlreadyDownloaded(context, updatableAppBadge.getApp())) {
updatableAppBadge.install.setVisibility(View.VISIBLE);
updatableAppBadge.cancel.setVisibility(View.GONE);
} else if (Util.shouldDownload(context, updatableAppBadge.getApp())
&& !updatableAppBadge.isDownloading) {
updatableAppBadge.update.setVisibility(View.VISIBLE);
updatableAppBadge.cancel.setVisibility(View.GONE);
}
return;
}
Pair<Float, Float> progress = state.getProgress();
progressBar.setVisibility(View.VISIBLE);
progressCents.setVisibility(View.VISIBLE);
progressBar.setIndeterminate(false);
progressBar.setMax(100);
progressBar.setProgress(getPercentage(progress.first, progress.second));
progressCents.setText(String.valueOf(progressBar.getProgress()) + "%");
}
private int getPercentage(float cur, float total) {
if (total != 0)
return (int) ((cur * 100) / total);
else
return 0;
}
}

View File

@@ -1,94 +1,12 @@
package com.dragons.aurora.fragment;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import com.dragons.aurora.R;
import com.dragons.aurora.activities.AuroraActivity;
import com.dragons.aurora.activities.DetailsActivity;
import com.dragons.aurora.fragment.details.ButtonDownload;
import com.dragons.aurora.fragment.details.ButtonUninstall;
import com.dragons.aurora.fragment.details.DownloadOptions;
import com.dragons.aurora.model.App;
import com.dragons.aurora.task.AppListValidityCheckTask;
import com.dragons.aurora.view.AppBadge;
import com.dragons.aurora.view.ListItem;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
abstract public class AppListFragment extends UtilFragment {
protected ListView listView;
protected Map<String, ListItem> listItems = new HashMap<>();
protected View v;
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
DetailsActivity.app = getAppByListPosition(info.position);
new DownloadOptions((AuroraActivity) this.getActivity(), DetailsActivity.app).inflate(menu);
menu.findItem(R.id.action_download).setVisible(new ButtonDownload((AuroraActivity) this.getActivity(), DetailsActivity.app).shouldBeVisible());
menu.findItem(R.id.action_uninstall).setVisible(DetailsActivity.app.isInstalled());
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
DetailsActivity.app = getAppByListPosition(info.position);
switch (item.getItemId()) {
case R.id.action_ignore:
case R.id.action_whitelist:
case R.id.action_unignore:
case R.id.action_unwhitelist:
new DownloadOptions((AuroraActivity) this.getActivity(), DetailsActivity.app).onContextItemSelected(item);
((ListItem) getListView().getItemAtPosition(info.position)).draw();
break;
case R.id.action_download:
new ButtonDownload((AuroraActivity) this.getActivity(), DetailsActivity.app).checkAndDownload();
break;
case R.id.action_uninstall:
new ButtonUninstall((AuroraActivity) this.getActivity(), DetailsActivity.app).uninstall();
break;
default:
return new DownloadOptions((AuroraActivity) this.getActivity(), DetailsActivity.app).onContextItemSelected(item);
}
return true;
}
protected App getAppByListPosition(int position) {
ListItem listItem = (ListItem) getListView().getItemAtPosition(position);
if (null == listItem || !(listItem instanceof AppBadge)) {
return null;
}
return ((AppBadge) listItem).getApp();
}
public void removeApp(String packageName) {
listItems.remove(packageName);
}
protected void clearApps() {
listItems.clear();
}
protected ListView getListView() {
return listView;
}
public Set<String> getListedPackageNames() {
return listItems.keySet();
}
protected void checkAppListValidity() {
AppListValidityCheckTask task = new AppListValidityCheckTask(this);
task.setRespectUpdateBlacklist(true);
task.setIncludeSystemApps(true);
task.execute();
}
}

View File

@@ -29,10 +29,10 @@ import io.reactivex.schedulers.Schedulers;
public class InstalledAppsFragment extends ForegroundUpdatableAppsTaskHelper {
private View v;
private View view;
private Disposable loadApps;
private SwipeRefreshLayout swipeRefreshLayout;
private RecyclerView recyclerView;
private List<App> installedApps = new ArrayList<>(new HashSet<>());
public static InstalledAppsFragment newInstance() {
return new InstalledAppsFragment();
@@ -49,15 +49,15 @@ public class InstalledAppsFragment extends ForegroundUpdatableAppsTaskHelper {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (v != null) {
if ((ViewGroup) v.getParent() != null)
((ViewGroup) v.getParent()).removeView(v);
return v;
if (view != null) {
if ((ViewGroup) view.getParent() != null)
((ViewGroup) view.getParent()).removeView(view);
return view;
}
v = inflater.inflate(R.layout.app_installed_inc, container, false);
view = inflater.inflate(R.layout.app_installed_inc, container, false);
swipeRefreshLayout = ViewUtils.findViewById(v, R.id.swipe_refresh_layout);
swipeRefreshLayout = ViewUtils.findViewById(view, R.id.swipe_refresh_layout);
swipeRefreshLayout.setOnRefreshListener(() -> {
if (isLoggedIn())
loadMarketApps();
@@ -65,20 +65,14 @@ public class InstalledAppsFragment extends ForegroundUpdatableAppsTaskHelper {
swipeRefreshLayout.setRefreshing(false);
});
recyclerView = v.findViewById(R.id.installed_apps_list);
registerForContextMenu(recyclerView);
return v;
return view;
}
@Override
public void onResume() {
super.onResume();
if (isLoggedIn() && allMarketApps.isEmpty())
if (isLoggedIn() && installedApps.isEmpty())
loadMarketApps();
else {
checkAppListValidity();
}
}
@Override
@@ -88,10 +82,10 @@ public class InstalledAppsFragment extends ForegroundUpdatableAppsTaskHelper {
}
protected void setupListView(List<App> appsToAdd) {
RecyclerView recyclerView = view.findViewById(R.id.installed_apps_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(this.getActivity());
InstalledAppsAdapter installedAppsAdapter = new InstalledAppsAdapter(getActivity(), appsToAdd);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), layoutManager.getOrientation());
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addItemDecoration(dividerItemDecoration);
@@ -106,11 +100,10 @@ public class InstalledAppsFragment extends ForegroundUpdatableAppsTaskHelper {
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe((appList) -> {
if (v != null) {
clearApps();
appList = new ArrayList<>(new HashSet<>(appList));
Collections.sort(appList);
setupListView(appList);
if (view != null) {
installedApps = new ArrayList<>(new HashSet<>(appList));
Collections.sort(installedApps);
setupListView(installedApps);
swipeRefreshLayout.setRefreshing(false);
}
}, this::processException);

View File

@@ -1,8 +1,8 @@
package com.dragons.aurora.fragment;
import android.app.DownloadManager;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
@@ -26,6 +26,7 @@ import com.dragons.aurora.UpdateAllReceiver;
import com.dragons.aurora.UpdateChecker;
import com.dragons.aurora.adapters.UpdatableAppsAdapter;
import com.dragons.aurora.model.App;
import com.dragons.aurora.notification.CancelDownloadService;
import com.dragons.aurora.task.playstore.ForegroundUpdatableAppsTaskHelper;
import com.percolate.caffeine.ToastUtils;
import com.percolate.caffeine.ViewUtils;
@@ -40,18 +41,22 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import static android.content.Context.DOWNLOAD_SERVICE;
public class UpdatableAppsFragment extends ForegroundUpdatableAppsTaskHelper implements UpdatableRecyclerItemTouchHelper.UpdatableRecyclerItemTouchListener {
public static int updates = 0;
public static boolean recheck = false;
public UpdatableAppsAdapter updatableAppsAdapter;
Button recheck_update;
private DownloadManager.Query query;
private DownloadManager dm;
private View v;
private View view;
private Disposable loadApps;
private SwipeRefreshLayout swipeRefreshLayout;
private UpdateAllReceiver updateAllReceiver;
private UpdatableAppsAdapter updatableAppsAdapter;
private Button update;
private Button cancel;
private TextView txt;
private List<App> updatableApps = new ArrayList<>(new HashSet<>());
public static UpdatableAppsFragment newInstance() {
return new UpdatableAppsFragment();
@@ -68,46 +73,68 @@ public class UpdatableAppsFragment extends ForegroundUpdatableAppsTaskHelper imp
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (v != null) {
if ((ViewGroup) v.getParent() != null)
((ViewGroup) v.getParent()).removeView(v);
return v;
if (view != null) {
if ((ViewGroup) view.getParent() != null)
((ViewGroup) view.getParent()).removeView(view);
return view;
}
v = inflater.inflate(R.layout.app_updatable_inc, container, false);
view = inflater.inflate(R.layout.app_updatable_inc, container, false);
initViews();
swipeRefreshLayout = ViewUtils.findViewById(v, R.id.swipe_refresh_layout);
swipeRefreshLayout.setOnRefreshListener(() -> {
if (isLoggedIn())
if (isLoggedIn() && isConnected(getContext()))
loadUpdatableApps();
else
swipeRefreshLayout.setRefreshing(false);
});
recheck_update.setOnClickListener(click -> {
if (isLoggedIn() && isConnected(getContext())) {
hide(view, R.id.unicorn);
swipeRefreshLayout.setRefreshing(true);
loadUpdatableApps();
}
});
setupDelta();
updateInteger();
return v;
return view;
}
private void initViews() {
recheck_update = ViewUtils.findViewById(view, R.id.recheck_updates);
update = ViewUtils.findViewById(view, R.id.update_all);
cancel = ViewUtils.findViewById(view, R.id.update_cancel);
txt = ViewUtils.findViewById(view, R.id.updates_txt);
swipeRefreshLayout = ViewUtils.findViewById(view, R.id.swipe_refresh_layout);
}
@Override
public void onResume() {
super.onResume();
updateAllReceiver = new UpdateAllReceiver(this);
if (isLoggedIn() && updatableApps.isEmpty())
if (isLoggedIn() && updatableApps.isEmpty() || recheck) {
recheck = false;
loadUpdatableApps();
else if (!updatableApps.isEmpty())
setText(v, R.id.updates_txt, R.string.list_update_all_txt, updatableApps.size());
} else if (updatableApps.size() > 0)
setText(view, R.id.updates_txt, R.string.list_update_all_txt, updatableApps.size());
else if (!isLoggedIn())
ToastUtils.quickToast(getActivity(), "You need to Login First", true);
else {
new UpdateAllReceiver(this);
checkAppListValidity();
}
updateInteger();
updateAllReceiver = new UpdateAllReceiver(this);
}
@Override
public void onStop() {
super.onStop();
(getActivity()).unregisterReceiver(updateAllReceiver);
swipeRefreshLayout.setRefreshing(false);
}
protected void setupListView(List<App> appsToAdd) {
RecyclerView recyclerView = v.findViewById(R.id.updatable_apps_list);
RecyclerView recyclerView = view.findViewById(R.id.updatable_apps_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(this.getActivity());
updatableAppsAdapter = new UpdatableAppsAdapter(getActivity(), appsToAdd);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), layoutManager.getOrientation());
@@ -122,27 +149,15 @@ public class UpdatableAppsFragment extends ForegroundUpdatableAppsTaskHelper imp
.attachToRecyclerView(recyclerView);
}
@Override
public void onStop() {
super.onStop();
(getActivity()).unregisterReceiver(updateAllReceiver);
swipeRefreshLayout.setRefreshing(false);
}
public void launchUpdateAll() {
((AuroraApplication) getActivity().getApplicationContext()).setBackgroundUpdating(true);
new UpdateChecker().onReceive(UpdatableAppsFragment.this.getActivity(), getActivity().getIntent());
hide(v, R.id.update_all);
show(v, R.id.update_cancel);
hide(view, R.id.update_all);
show(view, R.id.update_cancel);
}
public void setupButtons() {
Button update = ViewUtils.findViewById(v, R.id.update_all);
Button cancel = ViewUtils.findViewById(v, R.id.update_cancel);
TextView txt = ViewUtils.findViewById(v, R.id.updates_txt);
update.setVisibility(View.VISIBLE);
update.setOnClickListener(v -> {
launchUpdateAll();
update.setVisibility(View.GONE);
@@ -151,31 +166,32 @@ public class UpdatableAppsFragment extends ForegroundUpdatableAppsTaskHelper imp
});
cancel.setOnClickListener(v -> {
query = new DownloadManager.Query();
query.setFilterByStatus(DownloadManager.STATUS_PENDING | DownloadManager.STATUS_RUNNING);
dm = (DownloadManager) this.getActivity().getSystemService(DOWNLOAD_SERVICE);
Cursor c = dm.query(query);
while (c.moveToNext()) {
dm.remove(c.getLong(c.getColumnIndex(DownloadManager.COLUMN_ID)));
for (App app : updatableApps) {
getContext().startService(new Intent(getContext().getApplicationContext(), CancelDownloadService.class)
.putExtra(CancelDownloadService.PACKAGE_NAME, app.getPackageName()));
}
update.setVisibility(View.VISIBLE);
cancel.setVisibility(View.GONE);
setText(v, R.id.updates_txt, R.string.list_update_all_txt, updatableApps.size());
setText(view, R.id.updates_txt, R.string.list_update_all_txt, updatableApps.size());
});
}
public void removeButtons() {
update.setVisibility(View.GONE);
cancel.setVisibility(View.GONE);
}
public void setupDelta() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
TextView delta = ViewUtils.findViewById(v, R.id.updates_setting);
TextView delta = ViewUtils.findViewById(view, R.id.updates_setting);
delta.setText(sharedPreferences.getBoolean("PREFERENCE_DOWNLOAD_DELTAS", true) ? R.string.delta_enabled : R.string.delta_disabled);
delta.setVisibility(View.VISIBLE);
}
public void updateInteger() {
updates = updatableApps.size();
if (updatableApps.size() >= 99) {
public void updateInteger(int count) {
if (count >= 99) {
updates = 99;
}
} else updates = count;
}
public void loadUpdatableApps() {
@@ -184,19 +200,20 @@ public class UpdatableAppsFragment extends ForegroundUpdatableAppsTaskHelper imp
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe((appList) -> {
if (v != null) {
clearApps();
appList = new ArrayList<>(new HashSet<>(appList));
Collections.sort(appList);
setupListView(appList);
if (view != null) {
updatableApps = new ArrayList<>(new HashSet<>(appList));
Collections.sort(updatableApps);
setupListView(updatableApps);
updateInteger(updatableApps.size());
swipeRefreshLayout.setRefreshing(false);
if (success() && appList.isEmpty()) {
show(v, R.id.unicorn);
if (success() && updatableApps.isEmpty()) {
show(view, R.id.unicorn);
setText(view, R.id.updates_txt, R.string.list_update_all_txt, updatableApps.size());
removeButtons();
} else {
hide(v, R.id.unicorn);
setText(v, R.id.updates_txt, R.string.list_update_all_txt, appList.size());
hide(view, R.id.unicorn);
setText(view, R.id.updates_txt, R.string.list_update_all_txt, updatableApps.size());
setupButtons();
}
}
@@ -211,10 +228,13 @@ public class UpdatableAppsFragment extends ForegroundUpdatableAppsTaskHelper imp
updatableAppsAdapter.remove(position);
if (updatableAppsAdapter.getItemCount() == 0)
v.findViewById(R.id.unicorn).setVisibility(View.VISIBLE);
else
v.findViewById(R.id.unicorn).setVisibility(View.GONE);
if (updatableAppsAdapter.getItemCount() == 0) {
view.findViewById(R.id.unicorn).setVisibility(View.VISIBLE);
setText(view, R.id.updates_txt, R.string.list_update_all_txt, 0);
updateInteger(0);
removeButtons();
} else
view.findViewById(R.id.unicorn).setVisibility(View.GONE);
}
}
}

View File

@@ -2,6 +2,7 @@ package com.dragons.aurora.fragment;
import android.content.Context;
import android.content.Intent;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.TextView;

View File

@@ -1,10 +1,7 @@
package com.dragons.aurora.fragment.details;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.dragons.aurora.R;
import com.dragons.aurora.activities.AuroraActivity;
import com.dragons.aurora.model.App;
@@ -29,30 +26,4 @@ public abstract class Abstract {
protected void setText(int viewId, int stringId, Object... text) {
setText(viewId, activity.getString(stringId, text));
}
protected void initExpandableGroup(int viewIdHeader, int viewIdContainer, final View.OnClickListener l) {
TextView viewHeader = (TextView) activity.findViewById(viewIdHeader);
viewHeader.setVisibility(View.VISIBLE);
final LinearLayout viewContainer = (LinearLayout) activity.findViewById(viewIdContainer);
viewHeader.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean isExpanded = viewContainer.getVisibility() == View.VISIBLE;
if (isExpanded) {
viewContainer.setVisibility(View.GONE);
((TextView) v).setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_expand_more, 0);
} else {
if (null != l) {
l.onClick(v);
}
viewContainer.setVisibility(View.VISIBLE);
((TextView) v).setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_expand_less, 0);
}
}
});
}
protected void initExpandableGroup(int viewIdHeader, int viewIdContainer) {
initExpandableGroup(viewIdHeader, viewIdContainer, null);
}
}

View File

@@ -59,13 +59,9 @@ public class ButtonDownload extends Button {
@Override
public boolean shouldBeVisible() {
File apk = Paths.getApkPath(activity, app.getPackageName(), app.getVersionCode());
return (!apk.exists()
|| apk.length() != app.getSize()
|| !DownloadState.get(app.getPackageName()).isEverythingSuccessful()
)
return (!apk.exists() || apk.length() != app.getSize() || !DownloadState.get(app.getPackageName()).isEverythingSuccessful())
&& (app.isInPlayStore() || app.getPackageName().equals(BuildConfig.APPLICATION_ID))
&& (getInstalledVersionCode() != app.getVersionCode() || activity instanceof ManualDownloadActivity)
;
&& (getInstalledVersionCode() != app.getVersionCode() || activity instanceof ManualDownloadActivity);
}
@Override

View File

@@ -14,7 +14,7 @@ import com.dragons.aurora.model.App;
public class ButtonInstall extends Button {
ButtonInstall(AuroraActivity activity, App app) {
public ButtonInstall(AuroraActivity activity, App app) {
super(activity, app);
}

View File

@@ -8,18 +8,15 @@ import android.os.AsyncTask;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ImageView;
import com.percolate.caffeine.ViewUtils;
import com.dragons.aurora.BlackWhiteListManager;
import com.dragons.aurora.BuildConfig;
import com.dragons.aurora.ContextUtil;
import com.dragons.aurora.builders.FlagDialogBuilder;
import com.dragons.aurora.activities.AuroraActivity;
import com.dragons.aurora.InstalledApkCopier;
import com.dragons.aurora.activities.ManualDownloadActivity;
import com.dragons.aurora.R;
import com.dragons.aurora.activities.AuroraActivity;
import com.dragons.aurora.activities.ManualDownloadActivity;
import com.dragons.aurora.builders.FlagDialogBuilder;
import com.dragons.aurora.model.App;
import com.dragons.aurora.task.CheckShellTask;
import com.dragons.aurora.task.ConvertToNormalTask;
@@ -34,12 +31,6 @@ public class DownloadOptions extends Abstract {
@Override
public void draw() {
final ImageView more = ViewUtils.findViewById(activity, R.id.icon);
if (null == more) {
return;
}
activity.registerForContextMenu(more);
more.setOnClickListener(v -> more.showContextMenu());
}
public void inflate(Menu menu) {
@@ -78,6 +69,7 @@ public class DownloadOptions extends Abstract {
draw();
return true;
case R.id.action_manual:
ManualDownloadActivity.app = app;
activity.startActivity(new Intent(activity, ManualDownloadActivity.class));
return true;
case R.id.action_get_local_apk:

View File

@@ -34,7 +34,7 @@ public class AppListValidityCheckTask extends AsyncTask<String, Void, Set<String
protected void onPostExecute(Set<String> installedPackageNames) {
super.onPostExecute(installedPackageNames);
Set<String> newPackageNames = new HashSet<>(installedPackageNames);
newPackageNames.removeAll(fragment.getListedPackageNames());
/*newPackageNames.removeAll(fragment.getListedPackageNames());
if (!respectUpdateBlacklist && newPackageNames.size() > 0) {
//activity.loadInstalledApps();
return;
@@ -43,7 +43,7 @@ public class AppListValidityCheckTask extends AsyncTask<String, Void, Set<String
removedPackageNames.removeAll(installedPackageNames);
for (String packageName : removedPackageNames) {
fragment.removeApp(packageName);
}
}*/
}
@Override

View File

@@ -7,8 +7,8 @@ import com.dragons.aurora.ContextUtil;
import com.dragons.aurora.CredentialsEmptyException;
import com.dragons.aurora.PlayStoreApiAuthenticator;
import com.dragons.aurora.R;
import com.dragons.aurora.fragment.AppListFragment;
import com.dragons.aurora.fragment.PreferenceFragment;
import com.dragons.aurora.fragment.UtilFragment;
import com.dragons.aurora.playstoreapiv2.AuthException;
import com.percolate.caffeine.ToastUtils;
@@ -20,7 +20,7 @@ import java.net.UnknownHostException;
import javax.net.ssl.SSLHandshakeException;
public abstract class ExceptionTaskHelper extends AppListFragment {
public abstract class ExceptionTaskHelper extends UtilFragment {
protected Throwable exception;

View File

@@ -2,7 +2,6 @@ package com.dragons.aurora.task.playstore;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.view.View;
import com.dragons.aurora.BlackWhiteListManager;
import com.dragons.aurora.BuildConfig;
@@ -26,13 +25,9 @@ import java.util.Set;
public abstract class ForegroundUpdatableAppsTaskHelper extends ExceptionTaskHelper {
protected View view;
protected List<App> updatableApps = new ArrayList<>();
protected List<App> allMarketApps = new ArrayList<>();
protected List<App> getInstalledApps(GooglePlayAPI api) throws IOException {
api.toc();
List<App> allMarketApps = new ArrayList<>();
allMarketApps.clear();
Map<String, App> installedApps = getInstalledApps();
for (App appFromMarket : getAppsFromPlayStore(api, installedApps.keySet())) {
@@ -50,6 +45,7 @@ public abstract class ForegroundUpdatableAppsTaskHelper extends ExceptionTaskHel
protected List<App> getUpdatableApps(GooglePlayAPI api) throws IOException {
api.toc();
List<App> updatableApps = new ArrayList<>();
updatableApps.clear();
Map<String, App> installedApps = getInstalledApps();
for (App appFromMarket : getAppsFromPlayStore(api, filterBlacklistedApps(installedApps).keySet())) {

View File

@@ -1,22 +1,28 @@
package com.dragons.aurora.view;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.dragons.aurora.BuildConfig;
import com.dragons.aurora.NetworkState;
import com.dragons.aurora.Paths;
import com.dragons.aurora.R;
import com.dragons.aurora.downloader.DownloadState;
import com.dragons.aurora.fragment.PreferenceFragment;
import com.dragons.aurora.model.App;
import com.dragons.aurora.model.ImageSource;
import com.squareup.picasso.Picasso;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public abstract class AppBadge extends ListItem {
protected Context context;
protected App app;
protected List<String> line2 = new ArrayList<>();
protected List<String> line3 = new ArrayList<>();
@@ -38,8 +44,6 @@ public abstract class AppBadge extends ListItem {
setText(R.id.text2, TextUtils.join("", line2));
setText(R.id.text3, TextUtils.join("", line3));
drawIcon((ImageView) view.findViewById(R.id.icon));
if (app.isTestingProgramOptedIn())
view.findViewById(R.id.beta_user).setVisibility(View.VISIBLE);
if (app.isTestingProgramAvailable())
@@ -48,7 +52,7 @@ public abstract class AppBadge extends ListItem {
view.findViewById(R.id.early_access).setVisibility(View.VISIBLE);
}
private void drawIcon(ImageView imageView) {
protected void drawIcon(ImageView imageView) {
ImageSource imageSource = app.getIconInfo();
if (null != imageSource.getApplicationInfo() && !noImages()) {
imageView.setImageDrawable(imageView.getContext().getPackageManager().getApplicationIcon(imageSource.getApplicationInfo()));
@@ -74,4 +78,14 @@ public abstract class AppBadge extends ListItem {
private boolean noImages() {
return NetworkState.isMetered(view.getContext()) && PreferenceFragment.getBoolean(view.getContext(), PreferenceFragment.PREFERENCE_NO_IMAGES);
}
protected void hide(View view) {
if (view != null)
view.setVisibility(View.GONE);
}
protected void show(View view) {
if (view != null)
view.setVisibility(View.VISIBLE);
}
}

View File

@@ -1,6 +1,7 @@
package com.dragons.aurora.view;
import android.content.Context;
import android.widget.ImageView;
import com.dragons.aurora.BlackWhiteListManager;
import com.dragons.aurora.R;
@@ -21,6 +22,7 @@ public class InstalledAppBadge extends AppBadge {
if (manager.contains(app.getPackageName())) {
line3.add(c.getString(manager.isBlack() ? R.string.list_app_blacklisted : R.string.list_app_whitelisted));
}
drawIcon((ImageView) view.findViewById(R.id.icon));
super.draw();
}
}

View File

@@ -1,13 +1,19 @@
package com.dragons.aurora.view;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.dragons.aurora.R;
public abstract class ListItem {
protected View view;
@@ -30,9 +36,19 @@ public abstract class ListItem {
return bmp;
}
protected void paintTextView(int color, int textViewId) {
TextView textView = view.findViewById(textViewId);
protected void paintTextView(int color, TextView textView) {
if (textView != null)
textView.setTextColor(color);
}
protected void paintButton(int color, Button button) {
if (button != null)
ViewCompat.setBackgroundTintList(button, ColorStateList.valueOf(color));
}
protected void paintLayout(int color, int viewID) {
RelativeLayout layout = view.findViewById(viewID);
if (layout != null)
ViewCompat.setBackgroundTintList(layout, ColorStateList.valueOf(color));
}
}

View File

@@ -1,6 +1,7 @@
package com.dragons.aurora.view;
import android.content.Context;
import android.widget.ImageView;
import com.dragons.aurora.R;
import com.dragons.aurora.Util;
@@ -18,6 +19,7 @@ public class SearchResultAppBadge extends AppBadge {
line3.add(app.getPrice());
line3.add(c.getString(app.containsAds() ? R.string.list_app_has_ads : R.string.list_app_no_ads));
line3.add(c.getString(app.getDependencies().isEmpty() ? R.string.list_app_independent_from_gsf : R.string.list_app_depends_on_gsf));
drawIcon((ImageView) view.findViewById(R.id.icon));
super.draw();
}
}

View File

@@ -1,67 +1,204 @@
package com.dragons.aurora.view;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.support.v7.graphics.Palette;
import android.text.Html;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.dragons.aurora.InstallerFactory;
import com.dragons.aurora.R;
import com.dragons.aurora.Util;
import com.dragons.aurora.activities.AuroraActivity;
import com.dragons.aurora.activities.DetailsActivity;
import com.dragons.aurora.activities.ManualDownloadActivity;
import com.dragons.aurora.downloader.DownloadProgressBarUpdaterList;
import com.dragons.aurora.downloader.DownloadState;
import com.dragons.aurora.fragment.UpdatableAppsFragment;
import com.dragons.aurora.fragment.details.ButtonDownload;
import com.dragons.aurora.fragment.details.ButtonUninstall;
import com.dragons.aurora.notification.CancelDownloadService;
import com.dragons.aurora.task.playstore.PurchaseTask;
import java.util.Timer;
import java.util.TimerTask;
import static com.dragons.aurora.Util.isAlreadyQueued;
public class UpdatableAppBadge extends AppBadge {
private ImageView viewChanges, icon;
public boolean isDownloading = false;
public Button cancel;
public Button install;
public Button update;
public ProgressBar progressBar;
public TextView progressCents;
private TextView changes;
private ImageView viewChanges;
private Button uninstall;
private Button manual;
private LinearLayout listContainer;
private LinearLayout changesContainer;
private LinearLayout progressContainer;
private LinearLayout singleButtons;
@Override
public void draw() {
icon = view.findViewById(R.id.icon);
initViews();
super.context = view.getContext();
line2.clear();
line3.clear();
Context c = view.getContext();
String updated = app.getUpdated();
if (!TextUtils.isEmpty(updated)) {
line2.add(Formatter.formatShortFileSize(c, app.getSize()));
line3.add(c.getString(R.string.list_line_2_updatable, updated));
if (!TextUtils.isEmpty(app.getUpdated())) {
line2.add(Formatter.formatShortFileSize(context, app.getSize()));
line3.add(context.getString(R.string.list_line_2_updatable, app.getUpdated()));
}
if (app.isSystem()) {
line3.add(c.getString(R.string.list_app_system));
line3.add(context.getString(R.string.list_app_system));
}
drawIcon((ImageView) view.findViewById(R.id.icon));
drawMore();
super.draw();
}
public void drawMore() {
@Override
protected void drawIcon(ImageView icon) {
super.drawIcon(icon);
Bitmap bitmap = getBitmapFromDrawable(icon.getDrawable());
getPalette(bitmap);
}
private void initViews() {
listContainer = view.findViewById(R.id.list_container);
changesContainer = view.findViewById(R.id.changes_container);
progressContainer = view.findViewById(R.id.progress_container);
singleButtons = view.findViewById(R.id.single_buttons);
viewChanges = view.findViewById(R.id.viewChanges);
manual = view.findViewById(R.id.single_manual);
uninstall = view.findViewById(R.id.single_uninstall);
cancel = view.findViewById(R.id.single_cancel);
update = view.findViewById(R.id.single_update);
install = view.findViewById(R.id.single_install);
progressBar = view.findViewById(R.id.progress_bar_list);
progressCents = view.findViewById(R.id.progress_txt_list);
changes = view.findViewById(R.id.changes_upper);
}
private void drawMore() {
viewChanges.setOnClickListener(v -> {
expandMore();
if (changesContainer.getVisibility() == View.GONE) {
drawChanges();
if (isAlreadyQueued(app)) {
new DownloadProgressBarUpdaterList(context, this)
.execute(PurchaseTask.UPDATE_INTERVAL);
hide(update);
show(cancel);
}
} else removeChanges();
});
}
private void expandMore() {
changesContainer = view.findViewById(R.id.changes_container);
if (changesContainer.getVisibility() == View.GONE) drawChanges();
else removeChanges();
public void drawButtons() {
init();
listContainer.setOnClickListener(click ->
context.startActivity(DetailsActivity.getDetailsIntent(context, app.getPackageName())));
manual.setOnClickListener(click -> {
ManualDownloadActivity.app = app;
context.startActivity(new Intent(context, ManualDownloadActivity.class));
});
uninstall.setOnClickListener(click -> {
new ButtonUninstall((AuroraActivity) context, app).uninstall();
UpdatableAppsFragment.recheck = true;
});
cancel.setOnClickListener(click -> {
context.startService(
new Intent(context.getApplicationContext(), CancelDownloadService.class)
.putExtra(CancelDownloadService.PACKAGE_NAME, app.getPackageName()));
hide(cancel);
show(update);
isDownloading = false;
});
update.setOnClickListener(click -> {
UpdatableAppBadge updatableAppBadge = this;
isDownloading = true;
new ButtonDownload((AuroraActivity) context, app).checkAndDownload();
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
DownloadState state = DownloadState.get(app.getPackageName());
if (state != null && !state.isEverythingSuccessful()) {
new DownloadProgressBarUpdaterList(context, updatableAppBadge).execute(PurchaseTask.UPDATE_INTERVAL);
this.cancel();
}
}
}, 0, 1000);
hide(update);
show(cancel);
});
install.setOnClickListener(v -> {
((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE))
.cancel(app.getDisplayName().hashCode());
InstallerFactory.get(context).verifyAndInstall(app);
UpdatableAppsFragment.recheck = true;
});
}
private void init() {
if (Util.shouldDownload(context, app)) {
show(update);
hide(cancel);
}
if (Util.isAlreadyDownloaded(context, app)) {
show(install);
hide(cancel);
hide(update);
}
}
private void drawChanges() {
String changelog = app.getChanges();
TextView changes = view.findViewById(R.id.changes_upper);
if (changelog.isEmpty())
viewChanges.setImageResource(R.drawable.ic_expand_less_24);
if (app.getChanges().isEmpty())
changes.setText(R.string.details_changelog_empty);
else
changes.setText(Html.fromHtml(app.getChanges()).toString());
changesContainer.setVisibility(View.VISIBLE);
viewChanges.setImageResource(R.drawable.ic_expand_less_24);
show(changesContainer);
show(singleButtons);
show(progressContainer);
}
private void removeChanges() {
changesContainer.setVisibility(View.GONE);
hide(changesContainer);
hide(singleButtons);
hide(progressContainer);
viewChanges.setImageResource(R.drawable.ic_expand_more_24);
}
private void getPalette(Bitmap bitmap) {
Palette.from(bitmap)
.generate(palette -> {
paintTextView(palette.getDarkVibrantColor(Color.DKGRAY), changes);
paintButton(palette.getDarkVibrantColor(Color.DKGRAY), update);
paintButton(palette.getDarkVibrantColor(Color.DKGRAY), install);
paintLayout(palette.getDarkVibrantColor(Color.DKGRAY), R.id.view_background);
});
}
}

View File

@@ -1,5 +1,4 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -11,6 +10,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:animateLayoutChanges="true"
android:baselineAligned="false"
android:padding="5dp"
android:weightSum="3">
@@ -61,7 +61,7 @@
android:text="@string/list_update_all"
android:textColor="@color/white"
android:textSize="12sp"
android:visibility="visible" />
android:visibility="gone" />
<Button
android:id="@+id/update_cancel"
@@ -81,8 +81,7 @@
</LinearLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/updatable_header"
@@ -90,32 +89,48 @@
android:layout_marginEnd="5dp"
android:layout_marginStart="5dp"
android:layout_marginTop="10dp"
android:animateLayoutChanges="true"
android:background="@drawable/outline_bg"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
android:orientation="vertical">
<LinearLayout
<RelativeLayout
android:id="@+id/unicorn"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
android:visibility="gone">
<!-- Unicorn -->
<LinearLayout
android:id="@+id/unicorn"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:id="@+id/no_app_available"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_marginTop="10dp"
android:fontFamily="@font/google_sans_bold"
android:text="@string/list_empty_updates"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:fontFamily="@font/google_sans_bold"
android:text="@string/list_empty_updates"
android:textSize="18sp" />
</LinearLayout>
<Button
android:id="@+id/recheck_updates"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:layout_below="@+id/no_app_available"
android:layout_centerHorizontal="true"
android:layout_marginTop="25dp"
android:background="@drawable/button_positive"
android:fontFamily="@font/google_sans"
android:maxLines="1"
android:padding="5dp"
android:text="@string/list_update_recheck"
android:textColor="@color/white"
android:textSize="12sp" />
</RelativeLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/updatable_apps_list"
@@ -123,16 +138,8 @@
android:layout_height="match_parent"
android:padding="5dp"
android:scrollbars="vertical" />
</android.support.v4.widget.SwipeRefreshLayout>
<!--Empty TextView-->
<TextView
android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
</RelativeLayout>

View File

@@ -14,14 +14,14 @@
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@drawable/outline_bg"
android:padding="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dip">
@@ -57,18 +57,6 @@
android:hint="@string/manual_download_hint_version_code"
android:inputType="number" />
<ProgressBar
android:id="@+id/download_progress"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="2dp"
android:indeterminate="false"
android:paddingEnd="4dp"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingStart="4dp"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -115,6 +103,38 @@
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:animateLayoutChanges="true"
android:gravity="center"
android:orientation="horizontal"
android:weightSum="6">
<ProgressBar
android:id="@+id/download_progress"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="2dp"
android:layout_weight="5.3"
android:indeterminate="false"
android:progressBackgroundTint="@color/gray"
android:visibility="gone" />
<TextView
android:id="@+id/progressCents"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".7"
android:fontFamily="@font/google_sans"
android:gravity="end"
android:paddingEnd="3dp"
android:paddingStart="3dp"
android:textSize="12sp"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@@ -66,7 +66,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="8"
android:layout_weight="7"
android:orientation="vertical">
<TextView
@@ -107,7 +107,9 @@
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/text3">
android:layout_below="@id/text3"
android:layout_marginBottom="10dp"
android:layout_marginTop="5dp">
<ImageView
android:id="@+id/beta_user"
@@ -137,31 +139,146 @@
android:src="@drawable/ic_dot"
android:tint="@color/colorRed"
android:visibility="gone" />
<ImageView
android:id="@+id/viewChanges"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_gravity="end"
android:layout_marginEnd="10dp"
android:src="@drawable/ic_expand_more_24" />
</RelativeLayout>
</RelativeLayout>
<ImageView
android:id="@+id/viewChanges"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="?android:selectableItemBackgroundBorderless"
android:src="@drawable/ic_expand_more_24" />
</LinearLayout>
<!-- Action Buttons -->
<LinearLayout
android:id="@+id/single_buttons"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:background="?android:selectableItemBackgroundBorderless"
android:gravity="end"
android:visibility="gone">
<Button
android:id="@+id/single_manual"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:background="@drawable/button_positive"
android:fontFamily="@font/google_sans"
android:maxLines="1"
android:padding="5dp"
android:text="@string/details_manual"
android:textColor="@color/white"
android:textSize="12sp" />
<Button
android:id="@+id/single_uninstall"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:background="@drawable/button_negative"
android:fontFamily="@font/google_sans"
android:maxLines="1"
android:padding="5dp"
android:text="@string/details_uninstall"
android:textColor="@color/white"
android:textSize="12sp" />
<Button
android:id="@+id/single_cancel"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:background="@drawable/button_negative"
android:fontFamily="@font/google_sans"
android:maxLines="1"
android:padding="5dp"
android:text="@string/details_cancel"
android:textColor="@color/white"
android:textSize="12sp"
android:visibility="gone" />
<Button
android:id="@+id/single_update"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:background="@drawable/button_positive"
android:fontFamily="@font/google_sans"
android:maxLines="1"
android:padding="5dp"
android:text="@string/details_update"
android:textColor="@color/white"
android:textSize="12sp"
android:visibility="gone" />
<Button
android:id="@+id/single_install"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:background="@drawable/button_positive"
android:fontFamily="@font/google_sans"
android:maxLines="1"
android:padding="5dp"
android:text="@string/details_install"
android:textColor="@color/white"
android:textSize="12sp"
android:visibility="gone" />
</LinearLayout>
<!-- Progressbar -->
<LinearLayout
android:id="@+id/progress_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="10dp"
android:animateLayoutChanges="true"
android:gravity="center"
android:orientation="horizontal"
android:weightSum="6">
<ProgressBar
android:id="@+id/progress_bar_list"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="2dp"
android:layout_weight="5.3"
android:indeterminate="false"
android:progressBackgroundTint="@color/gray"
android:visibility="gone" />
<TextView
android:id="@+id/progress_txt_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".7"
android:fontFamily="@font/google_sans"
android:gravity="end"
android:paddingEnd="3dp"
android:paddingStart="3dp"
android:textSize="12sp"
android:visibility="gone" />
</LinearLayout>
<!-- Changelog -->
<LinearLayout
android:id="@+id/changes_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:layout_margin="10dp"
android:background="@drawable/outline_bg"
android:orientation="vertical"
android:visibility="gone">
@@ -170,9 +287,9 @@
android:id="@+id/changes_upper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:autoLink="web|email"
android:fontFamily="@font/google_sans"
android:padding="10dp"
android:textColor="?android:attr/textColorSecondary"
android:textIsSelectable="true"
android:visibility="visible" />

View File

@@ -26,7 +26,8 @@
android:visible="false" />
<item
android:id="@+id/action_manual"
android:title="@string/action_manual" />
android:title="@string/action_manual"
android:visible="false" />
<item
android:id="@+id/action_get_local_apk"
android:title="@string/action_get_local_apk"

View File

@@ -83,6 +83,7 @@
<string name="details_category">"%1$s"</string>
<string name="details_contains_ads">Contains ads</string>
<string name="details_could_not_copy_apk">Could not copy apk</string>
<string name="details_changelog">Changelog</string>
<string name="details_changelog_empty">No changelog available</string>
<string name="details_description">Read more</string>
<string name="details_developer">"%1$s"</string>
@@ -93,6 +94,7 @@
<string name="details_installed">"Installed successfully"</string>
<string name="details_installing">Installing</string>
<string name="details_install_failure">"Could not install"</string>
<string name="details_manual">Manual</string>
<string name="details_more">More</string>
<string name="details_not_available_on_play_store">Not available on Play Store</string>
<string name="details_no_ads">No ads</string>
@@ -211,6 +213,7 @@
<string name="list_update_all">Update All</string>
<string name="list_update_all_txt">Update(s) available : %1$s"</string>
<string name="list_update_chk_txt">Checking for updates..</string>
<string name="list_update_recheck">Recheck</string>
<string name="list_updating">Updating…</string>
<string name="manual_download_compatible">Version code field has been pre-filled with this app\'s latest compatible version code. If you want the previous version, simply input a number smaller than the current. If the developer has not deleted the apk of the previous version from Play Store, you might be able to start the download.</string>
<string name="manual_download_hint_version_code">version code here</string>