diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapState.java b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapState.java new file mode 100644 index 000000000..1783eb000 --- /dev/null +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapState.java @@ -0,0 +1,73 @@ +package org.fdroid.fdroid.localrepo; + +import android.content.Context; +import android.content.SharedPreferences; +import android.support.annotation.IntDef; +import android.support.annotation.NonNull; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +public class SwapState { + + private static final String SHARED_PREFERENCES = "swap-state"; + + public static final int STEP_INTRO = 1; + public static final int STEP_SELECT_APPS = 2; + public static final int STEP_JOIN_WIFI = 3; + public static final int STEP_SHOW_NFC = 4; + public static final int STEP_WIFI_QR = 5; + + private int step; + + @NonNull + private final Context context; + + private SwapState(@NonNull Context context) { + this.context = context; + } + + /** + * Current screen that the swap process is up to. + * Will be one of the SwapState.STEP_* values. + */ + @SwapStep + public int getStep() { + return step; + } + + public SwapState setStep(@SwapStep int step) { + this.step = step; + persist(); + return this; + } + + private static final String KEY_STEP = "step"; + + @NonNull + public static SwapState load(@NonNull Context context) { + SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE); + + @SwapStep int step = preferences.getInt(KEY_STEP, STEP_INTRO); + + return new SwapState(context) + .setStep(step); + } + + private void persist() { + SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_APPEND); + preferences.edit() + .putInt(KEY_STEP, step) + .commit(); + } + + /** + * Ensure that we don't get put into an incorrect state, by forcing people to pass valid + * states to setStep. Ideally this would be done by requiring an enum or something to + * be passed rather than in integer, however that is harder to persist on disk than an int. + * This is the same as, e.g. {@link Context#getSystemService(String)} + */ + @IntDef({STEP_INTRO, STEP_SELECT_APPS, STEP_JOIN_WIFI, STEP_SHOW_NFC, STEP_WIFI_QR}) + @Retention(RetentionPolicy.SOURCE) + public @interface SwapStep {} +} diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java index f8fc37ace..72e8e4b37 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java @@ -28,6 +28,7 @@ import org.fdroid.fdroid.R; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.data.NewRepoConfig; import org.fdroid.fdroid.localrepo.LocalRepoManager; +import org.fdroid.fdroid.localrepo.SwapState; import java.util.Set; import java.util.Timer; @@ -37,18 +38,20 @@ public class SwapWorkflowActivity extends FragmentActivity { private ViewGroup container; - private enum State { - INTRO, SELECT_APPS, JOIN_WIFI - } - public interface InnerView { /** @return True if the menu should be shown. */ boolean buildMenu(Menu menu, @NonNull MenuInflater inflater); + + /** @return The step that this view represents. */ + @SwapState.SwapStep int getStep(); + + // TODO: Handle back presses with a method like this: + // @SwapState.SwapStep int getPreviousStep(); } private static final int CONNECT_TO_SWAP = 1; - private State currentState = State.INTRO; + private SwapState state; private InnerView currentView; private boolean hasPreparedLocalRepo = false; private UpdateAsyncTask updateSwappableAppsTask = null; @@ -57,8 +60,10 @@ public class SwapWorkflowActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + state = SwapState.load(this); setContentView(R.layout.swap_activity); container = (ViewGroup) findViewById(R.id.fragment_container); + showRelevantView(); } @Override @@ -72,12 +77,37 @@ public class SwapWorkflowActivity extends FragmentActivity { @Override protected void onResume() { super.onResume(); - showView(); + showRelevantView(); } - private void showView() { - if (currentState == State.INTRO) { - showIntro(); + private void showRelevantView() { + if (currentView != null && currentView.getStep() == state.getStep()) { + // Already showing the currect step, so don't bother changing anything. + return; + } + + switch(state.getStep()) { + case SwapState.STEP_INTRO: + showIntro(); + break; + case SwapState.STEP_SELECT_APPS: + showSelectApps(); + break; + case SwapState.STEP_SHOW_NFC: + showNfc(); + break; + case SwapState.STEP_JOIN_WIFI: + showJoinWifi(); + break; + case SwapState.STEP_WIFI_QR: + showWifiQr(); + break; + } + } + + private void showNfc() { + if (!attemptToShowNfc()) { + showWifiQr(); } } @@ -85,6 +115,7 @@ public class SwapWorkflowActivity extends FragmentActivity { container.removeAllViews(); View view = ((LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(viewRes, container, false); currentView = (InnerView)view; + state.setStep(currentView.getStep()); container.addView(view); supportInvalidateOptionsMenu(); } diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/views/JoinWifiView.java b/F-Droid/src/org/fdroid/fdroid/views/swap/views/JoinWifiView.java index 653db430b..e77d0b9a6 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/views/JoinWifiView.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/views/JoinWifiView.java @@ -22,6 +22,7 @@ import android.widget.TextView; import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.R; +import org.fdroid.fdroid.localrepo.SwapState; import org.fdroid.fdroid.net.WifiStateChangeService; import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; @@ -117,4 +118,9 @@ public class JoinWifiView extends RelativeLayout implements SwapWorkflowActivity }); return true; } + + @Override + public int getStep() { + return SwapState.STEP_JOIN_WIFI; + } } diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/views/NfcView.java b/F-Droid/src/org/fdroid/fdroid/views/swap/views/NfcView.java index 63ce23c61..b3a566203 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/views/NfcView.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/views/NfcView.java @@ -15,6 +15,7 @@ import android.widget.RelativeLayout; import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.R; +import org.fdroid.fdroid.localrepo.SwapState; import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; public class NfcView extends RelativeLayout implements SwapWorkflowActivity.InnerView { @@ -67,4 +68,9 @@ public class NfcView extends RelativeLayout implements SwapWorkflowActivity.Inne }); return true; } + + @Override + public int getStep() { + return SwapState.STEP_SHOW_NFC; + } } diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/views/SelectAppsView.java b/F-Droid/src/org/fdroid/fdroid/views/swap/views/SelectAppsView.java index 7a17788da..2917e8c02 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/views/SelectAppsView.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/views/SelectAppsView.java @@ -36,6 +36,7 @@ import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.R; import org.fdroid.fdroid.data.InstalledAppProvider; import org.fdroid.fdroid.localrepo.LocalRepoManager; +import org.fdroid.fdroid.localrepo.SwapState; import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; import java.util.HashSet; @@ -142,6 +143,11 @@ public class SelectAppsView extends ListView implements return true; } + @Override + public int getStep() { + return SwapState.STEP_SELECT_APPS; + } + private void toggleAppSelected(int position) { Cursor c = (Cursor) adapter.getItem(position - 1); String packageName = c.getString(c.getColumnIndex(InstalledAppProvider.DataColumns.APP_ID)); diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/views/StartSwapView.java b/F-Droid/src/org/fdroid/fdroid/views/swap/views/StartSwapView.java index 72560f92d..a681f3de7 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/views/StartSwapView.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/views/StartSwapView.java @@ -12,6 +12,7 @@ import android.view.View; import android.widget.LinearLayout; import org.fdroid.fdroid.R; +import org.fdroid.fdroid.localrepo.SwapState; import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; public class StartSwapView extends LinearLayout implements SwapWorkflowActivity.InnerView { @@ -34,8 +35,6 @@ public class StartSwapView extends LinearLayout implements SwapWorkflowActivity. super(context, attrs, defStyleAttr, defStyleRes); } - - private SwapWorkflowActivity getActivity() { // TODO: Try and find a better way to get to the SwapActivity, which makes less asumptions. return (SwapWorkflowActivity)getContext(); @@ -58,4 +57,9 @@ public class StartSwapView extends LinearLayout implements SwapWorkflowActivity. public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) { return false; } + + @Override + public int getStep() { + return SwapState.STEP_INTRO; + } } diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/views/WifiQrView.java b/F-Droid/src/org/fdroid/fdroid/views/swap/views/WifiQrView.java index 09b5d66c6..47120a492 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/views/WifiQrView.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/views/WifiQrView.java @@ -30,6 +30,7 @@ import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.QrGenAsyncTask; import org.fdroid.fdroid.R; import org.fdroid.fdroid.Utils; +import org.fdroid.fdroid.localrepo.SwapState; import org.fdroid.fdroid.net.WifiStateChangeService; import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; @@ -106,6 +107,11 @@ public class WifiQrView extends ScrollView implements SwapWorkflowActivity.Inner return false; } + @Override + public int getStep() { + return SwapState.STEP_WIFI_QR; + } + private void setUIFromWifi() { if (TextUtils.isEmpty(FDroidApp.repo.address))