Show "preparing local repo" stuff in activity, not dialog.

Use the same view as when downloading a swap index. This means
no more progress dialogs, and no more Toasts when finished, which
is good.
This commit is contained in:
Peter Serwylo 2015-08-16 23:32:37 +10:00
parent 1ea35f6977
commit e53a56f7b2
3 changed files with 140 additions and 95 deletions

View File

@ -62,7 +62,7 @@ import java.util.TimerTask;
* the future.
*
* TODO: Show "Waiting for other device to finish setting up swap" when only F-Droid shown in swap
* TODO: Handle not connected to wifi more gracefully. For example, Bonjour discovery falls over.
* TODO: Handle "not connected to wifi" more gracefully. For example, Bonjour discovery falls over.
* TODO: Remove peers from list of peers when no longer "visible".
* TODO: Feedback for "Setting up (wifi|bluetooth)" in start swap view is not as immediate as I had hoped.
* TODO: Turn off bluetooth after cancelling/timing out if we turned it on.
@ -162,6 +162,13 @@ public class SwapService extends Service {
}
}
public void connectToPeer() {
if (getPeer() == null) {
throw new IllegalStateException("Cannot connect to peer, no peer has been selected.");
}
connectTo(getPeer(), getPeer().shouldPromptForSwapBack());
}
public void connectTo(@NonNull Peer peer, boolean requestSwapBack) {
if (peer != this.peer) {
Log.e(TAG, "Oops, got a different peer to swap with than initially planned.");

View File

@ -49,26 +49,11 @@ public class SwapConnecting extends LinearLayout implements SwapWorkflowActivity
return (SwapWorkflowActivity)getContext();
}
private SwapService getManager() {
return getActivity().getState();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
Peer peer = getManager().getPeer();
if (peer == null) {
Log.e(TAG, "Cannot find the peer to connect to.");
// TODO: Don't go to the selected apps, rather show a Toast message and then go to the intro screen.
getActivity().showSelectApps();
return;
}
String heading = getContext().getString(R.string.status_connecting_to_repo, peer.getName());
((TextView) findViewById(R.id.heading)).setText(heading);
((TextView) findViewById(R.id.heading)).setText(R.string.swap_connecting);
findViewById(R.id.back).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@ -77,56 +62,119 @@ public class SwapConnecting extends LinearLayout implements SwapWorkflowActivity
});
// TODO: Unregister correctly, not just when being notified of completion or errors.
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(repoUpdateReceiver, new IntentFilter(UpdateService.LOCAL_ACTION_STATUS));
getManager().connectTo(peer, peer.shouldPromptForSwapBack());
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
repoUpdateReceiver, new IntentFilter(UpdateService.LOCAL_ACTION_STATUS));
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
prepareSwapReceiver, new IntentFilter(SwapWorkflowActivity.PrepareSwapRepo.ACTION));
}
private BroadcastReceiver repoUpdateReceiver = new ConnectSwapReceiver();
private BroadcastReceiver prepareSwapReceiver = new PrepareSwapReceiver();
/**
* Listens for feedback about a local repository being prepared:
* * Apk files copied to the LocalHTTPD webroot
* * index.html file prepared
* * Icons will be copied to the webroot in the background and so are not part of this process.
*/
class PrepareSwapReceiver extends Receiver {
@Override
protected String getMessageExtra() {
return SwapWorkflowActivity.PrepareSwapRepo.EXTRA_MESSAGE;
}
protected int getType(Intent intent) {
return intent.getIntExtra(SwapWorkflowActivity.PrepareSwapRepo.EXTRA_TYPE, -1);
}
@Override
protected boolean isComplete(Intent intent) {
return getType(intent) == SwapWorkflowActivity.PrepareSwapRepo.TYPE_COMPLETE;
}
@Override
protected boolean isError(Intent intent) {
return getType(intent) == SwapWorkflowActivity.PrepareSwapRepo.TYPE_ERROR;
}
@Override
protected void onComplete() {
getActivity().onLocalRepoPrepared();
}
}
/**
* Listens for feedback about a repo update process taking place.
* * Tracks an index.jar download and show the progress messages
*/
class ConnectSwapReceiver extends Receiver {
@Override
protected String getMessageExtra() {
return UpdateService.EXTRA_MESSAGE;
}
protected int getStatusCode(Intent intent) {
return intent.getIntExtra(UpdateService.EXTRA_STATUS_CODE, -1);
}
@Override
protected boolean isComplete(Intent intent) {
int status = getStatusCode(intent);
return status == UpdateService.STATUS_COMPLETE_AND_SAME ||
status == UpdateService.STATUS_COMPLETE_WITH_CHANGES;
}
@Override
protected boolean isError(Intent intent) {
int status = getStatusCode(intent);
return status == UpdateService.STATUS_ERROR_GLOBAL ||
status == UpdateService.STATUS_ERROR_LOCAL ||
status == UpdateService.STATUS_ERROR_LOCAL_SMALL;
}
@Override
protected void onComplete() {
getActivity().showSwapConnected();
}
}
private BroadcastReceiver repoUpdateReceiver = new BroadcastReceiver() {
abstract class Receiver extends BroadcastReceiver {
protected abstract String getMessageExtra();
protected abstract boolean isComplete(Intent intent);
protected abstract boolean isError(Intent intent);
protected abstract void onComplete();
@Override
public void onReceive(Context context, Intent intent) {
int statusCode = intent.getIntExtra(UpdateService.EXTRA_STATUS_CODE, -1);
TextView progressText = ((TextView) findViewById(R.id.heading));
TextView errorText = ((TextView) findViewById(R.id.error));
Button backButton = ((Button) findViewById(R.id.back));
if (intent.hasExtra(UpdateService.EXTRA_MESSAGE)) {
progressText.setText(intent.getStringExtra(UpdateService.EXTRA_MESSAGE));
String message = null;
if (intent.hasExtra(getMessageExtra())) {
message = intent.getStringExtra(getMessageExtra());
if (message != null) {
progressText.setText(message);
}
}
boolean finished = false;
boolean error = false;
progressText.setVisibility(View.VISIBLE);
errorText.setVisibility(View.GONE);
backButton.setVisibility(View.GONE);
switch (statusCode) {
case UpdateService.STATUS_ERROR_GLOBAL:
finished = true;
error = true;
break;
case UpdateService.STATUS_COMPLETE_WITH_CHANGES:
finished = true;
break;
case UpdateService.STATUS_COMPLETE_AND_SAME:
finished = true;
break;
case UpdateService.STATUS_INFO:
break;
}
if (finished) {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(repoUpdateReceiver);
if (error) {
if (isError(intent)) {
progressText.setVisibility(View.GONE);
errorText.setVisibility(View.VISIBLE);
backButton.setVisibility(View.VISIBLE);
} else {
getActivity().showSwapConnected();
return;
}
if (isComplete(intent)) {
onComplete();
}
}
};

View File

@ -16,6 +16,7 @@ import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NavUtils;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
@ -261,7 +262,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
showSwapConnected();
break;
case SwapService.STEP_CONNECTING:
// TODO: Properly decide what to do here...
// TODO: Properly decide what to do here (i.e. returning to the activity after it was connecting)...
inflateInnerView(R.layout.swap_blank);
break;
}
@ -345,8 +346,10 @@ public class SwapWorkflowActivity extends AppCompatActivity {
// Otherwise, probably will need to scan the file system.
public void onAppsSelected() {
if (updateSwappableAppsTask == null && !hasPreparedLocalRepo) {
updateSwappableAppsTask = new PrepareFullSwapRepo(getService().getAppsToSwap());
updateSwappableAppsTask = new PrepareSwapRepo(getService().getAppsToSwap());
updateSwappableAppsTask.execute();
getService().setStep(SwapService.STEP_CONNECTING);
inflateInnerView(R.layout.swap_connecting);
} else {
onLocalRepoPrepared();
}
@ -370,7 +373,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
* * Alternatively, if we didn't have a person to connect to, and instead clicked "Scan QR Code",
* then we want to show a QR code or NFC dialog.
*/
private void onLocalRepoPrepared() {
public void onLocalRepoPrepared() {
updateSwappableAppsTask = null;
hasPreparedLocalRepo = true;
if (getService().isConnectingWithPeer()) {
@ -381,6 +384,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
}
private void startSwappingWithPeer() {
getService().connectToPeer();
inflateInnerView(R.layout.swap_connecting);
}
@ -542,39 +546,14 @@ public class SwapWorkflowActivity extends AppCompatActivity {
}
}
class PrepareFullSwapRepo extends PrepareSwapRepo {
class PrepareSwapRepo extends AsyncTask<Void, Void, Void> {
@NonNull
private final ProgressDialog progressDialog;
public PrepareFullSwapRepo(@NonNull Set<String> apps) {
super(apps);
progressDialog = new ProgressDialog(context);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setTitle(R.string.updating);
}
@Override
protected void onPreExecute() {
progressDialog.show();
}
@Override
protected void onProgressUpdate(String... progress) {
super.onProgressUpdate(progress);
progressDialog.setMessage(progress[0]);
}
@Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
Toast.makeText(context, R.string.updated_local_repo, Toast.LENGTH_SHORT).show();
onLocalRepoPrepared();
}
}
abstract class PrepareSwapRepo extends AsyncTask<Void, String, Void> {
public static final String ACTION = "PrepareSwapRepo.Action";
public static final String EXTRA_MESSAGE = "PrepareSwapRepo.Status.Message";
public static final String EXTRA_TYPE = "PrepareSwapRepo.Action.Type";
public static final int TYPE_STATUS = 0;
public static final int TYPE_COMPLETE = 1;
public static final int TYPE_ERROR = 2;
@SuppressWarnings("UnusedDeclaration")
private static final String TAG = "UpdateAsyncTask";
@ -594,22 +573,36 @@ public class SwapWorkflowActivity extends AppCompatActivity {
sharingUri = Utils.getSharingUri(FDroidApp.repo);
}
private void broadcast(int type) {
broadcast(type, null);
}
private void broadcast(int type, String message) {
Intent intent = new Intent(ACTION);
intent.putExtra(EXTRA_TYPE, type);
if (message != null) {
Log.d(TAG, "Preparing swap: " + message);
intent.putExtra(EXTRA_MESSAGE, message);
}
LocalBroadcastManager.getInstance(SwapWorkflowActivity.this).sendBroadcast(intent);
}
@Override
protected Void doInBackground(Void... params) {
try {
final LocalRepoManager lrm = LocalRepoManager.get(context);
publishProgress(getString(R.string.deleting_repo));
broadcast(TYPE_STATUS, getString(R.string.deleting_repo));
lrm.deleteRepo();
for (String app : selectedApps) {
publishProgress(String.format(getString(R.string.adding_apks_format), app));
broadcast(TYPE_STATUS, String.format(getString(R.string.adding_apks_format), app));
lrm.addApp(context, app);
}
lrm.writeIndexPage(sharingUri.toString());
publishProgress(getString(R.string.writing_index_jar));
broadcast(TYPE_STATUS, getString(R.string.writing_index_jar));
lrm.writeIndexJar();
publishProgress(getString(R.string.linking_apks));
broadcast(TYPE_STATUS, getString(R.string.linking_apks));
lrm.copyApksToRepo();
publishProgress(getString(R.string.copying_icons));
broadcast(TYPE_STATUS, getString(R.string.copying_icons));
// run the icon copy without progress, its not a blocker
// TODO: Fix lint error about this being run from a worker thread, says it should be
// run on a main thread.
@ -621,17 +614,14 @@ public class SwapWorkflowActivity extends AppCompatActivity {
return null;
}
}.execute();
broadcast(TYPE_COMPLETE);
} catch (Exception e) {
broadcast(TYPE_ERROR);
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(String... progress) {
super.onProgressUpdate(progress);
Log.d(TAG, progress[0]);
}
}
/**