Merge branch 'move-swap-views-towards-mvc' into 'master'

Move swap views towards MVC

See merge request fdroid/fdroidclient!822
This commit is contained in:
Hans-Christoph Steiner 2019-05-14 11:56:01 +00:00
commit 200548d6ba
33 changed files with 892 additions and 1216 deletions

View File

@ -79,7 +79,8 @@ errorprone:
unzip -qq -d $ANDROID_HOME emulator-linux-5264690.zip; unzip -qq -d $ANDROID_HOME emulator-linux-5264690.zip;
set +x; set +x;
fi fi
- grep Revision $ANDROID_HOME/emulator/source.properties - grep -v '^License' $ANDROID_HOME/tools/source.properties
$ANDROID_HOME/emulator/source.properties
- alias sdkmanager - alias sdkmanager
- echo y | sdkmanager "platforms;android-$AVD_SDK" > /dev/null - echo y | sdkmanager "platforms;android-$AVD_SDK" > /dev/null

View File

@ -15,7 +15,7 @@ import android.net.Uri;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.IBinder; import android.os.IBinder;
import android.support.annotation.IntDef; import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
@ -46,8 +46,6 @@ import rx.schedulers.Schedulers;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.util.Collections; import java.util.Collections;
@ -129,43 +127,21 @@ public class SwapService extends Service {
return peerFinder; return peerFinder;
} }
// ==========================================================
// Manage the current step
// ("Step" refers to the current view being shown in the UI)
// ==========================================================
public static final int STEP_INTRO = 1; 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;
public static final int STEP_CONNECTING = 6;
public static final int STEP_SUCCESS = 7;
public static final int STEP_CONFIRM_SWAP = 8;
/** @LayoutRes
* Special view, that we don't really want to actually store against the private int currentView = STEP_INTRO;
* {@link SwapService#step}. Rather, we use it for the purpose of specifying
* we are in the state waiting for the {@link SwapService} to get started and
* bound to the {@link SwapWorkflowActivity}.
*/
public static final int STEP_INITIAL_LOADING = 9;
@SwapStep
private int step = STEP_INTRO;
/** /**
* Current screen that the swap process is up to. * Current screen that the swap process is up to.
* Will be one of the SwapState.STEP_* values.
*/ */
@SwapStep @LayoutRes
public int getStep() { public int getCurrentView() {
return step; return currentView;
} }
public SwapService setStep(@SwapStep int step) { public void setCurrentView(@LayoutRes int currentView) {
this.step = step; this.currentView = currentView;
return this;
} }
@NonNull @NonNull
@ -269,18 +245,6 @@ public class SwapService extends Service {
return peerRepo; return peerRepo;
} }
/**
* 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,
STEP_CONNECTING, STEP_SUCCESS, STEP_CONFIRM_SWAP, STEP_INITIAL_LOADING})
@Retention(RetentionPolicy.SOURCE)
public @interface SwapStep {
}
// ================================================= // =================================================
// Have selected a specific peer to swap with // Have selected a specific peer to swap with
// (Rather than showing a generic QR code to scan) // (Rather than showing a generic QR code to scan)

View File

@ -0,0 +1,80 @@
package org.fdroid.fdroid.localrepo;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.ColorInt;
import android.support.annotation.LayoutRes;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.views.swap.SwapWorkflowActivity;
/**
* A {@link android.view.View} that registers to handle the swap events from
* {@link SwapService}.
*/
public class SwapView extends RelativeLayout {
public static final String TAG = "SwapView";
@ColorInt
public final int toolbarColor;
public final String toolbarTitle;
private int layoutResId;
protected String currentFilterString;
public SwapView(Context context) {
this(context, null);
}
public SwapView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SwapView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
@TargetApi(21)
public SwapView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.SwapView, 0, 0);
toolbarColor = a.getColor(R.styleable.SwapView_toolbarColor,
getResources().getColor(R.color.swap_blue));
toolbarTitle = a.getString(R.styleable.SwapView_toolbarTitle);
a.recycle();
}
@LayoutRes
public int getLayoutResId() {
return layoutResId;
}
public void setLayoutResId(@LayoutRes int layoutResId) {
this.layoutResId = layoutResId;
}
public String getCurrentFilterString() {
return this.currentFilterString;
}
public void setCurrentFilterString(String currentFilterString) {
this.currentFilterString = currentFilterString;
}
public SwapWorkflowActivity getActivity() {
return (SwapWorkflowActivity) getContext();
}
@ColorInt
public int getToolbarColour() {
return toolbarColor;
}
public String getToolbarTitle() {
return toolbarTitle;
}
}

View File

@ -1,92 +0,0 @@
package org.fdroid.fdroid.views.swap;
import android.annotation.TargetApi;
import android.content.Context;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.data.NewRepoConfig;
import org.fdroid.fdroid.localrepo.SwapService;
public class ConfirmReceive extends RelativeLayout implements SwapWorkflowActivity.InnerView {
private NewRepoConfig config;
public ConfirmReceive(Context context) {
super(context);
}
public ConfirmReceive(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ConfirmReceive(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(21)
public ConfirmReceive(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private SwapWorkflowActivity getActivity() {
return (SwapWorkflowActivity) getContext();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
findViewById(R.id.no_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().denySwap();
}
});
findViewById(R.id.yes_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().swapWith(config);
}
});
}
@Override
public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) {
return true;
}
@Override
public int getStep() {
return SwapService.STEP_CONFIRM_SWAP;
}
@Override
public int getPreviousStep() {
return SwapService.STEP_INTRO;
}
@ColorRes
public int getToolbarColour() {
return R.color.swap_blue;
}
@Override
public String getToolbarTitle() {
return getResources().getString(R.string.swap_confirm);
}
public void setup(NewRepoConfig config) {
this.config = config;
TextView descriptionTextView = (TextView) findViewById(R.id.text_description);
descriptionTextView.setText(getResources().getString(R.string.swap_confirm_connect, config.getHost()));
}
}

View File

@ -0,0 +1,54 @@
package org.fdroid.fdroid.views.swap;
import android.annotation.TargetApi;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.data.NewRepoConfig;
import org.fdroid.fdroid.localrepo.SwapView;
public class ConfirmReceiveView extends SwapView {
private NewRepoConfig config;
public ConfirmReceiveView(Context context) {
super(context);
}
public ConfirmReceiveView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ConfirmReceiveView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(21)
public ConfirmReceiveView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
findViewById(R.id.no_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().denySwap();
}
});
findViewById(R.id.yes_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().swapWith(config);
}
});
}
public void setup(NewRepoConfig config) {
this.config = config;
}
}

View File

@ -5,49 +5,39 @@ 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.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.LinearLayout; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.UpdateService; import org.fdroid.fdroid.UpdateService;
import org.fdroid.fdroid.localrepo.SwapService; import org.fdroid.fdroid.localrepo.SwapView;
// TODO: Use this for the "Preparing local repo" dialog also. public class ConnectingView extends SwapView {
public class SwapConnecting extends LinearLayout implements SwapWorkflowActivity.InnerView {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final String TAG = "SwapConnecting"; private static final String TAG = "ConnectingView";
public SwapConnecting(Context context) { public ConnectingView(Context context) {
super(context); super(context);
} }
public SwapConnecting(Context context, AttributeSet attrs) { public ConnectingView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
} }
@TargetApi(11) @TargetApi(11)
public SwapConnecting(Context context, AttributeSet attrs, int defStyleAttr) { public ConnectingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
} }
@TargetApi(21) @TargetApi(21)
public SwapConnecting(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public ConnectingView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
} }
private SwapWorkflowActivity getActivity() {
return (SwapWorkflowActivity) getContext();
}
@Override @Override
protected void onFinishInflate() { protected void onFinishInflate() {
super.onFinishInflate(); super.onFinishInflate();
@ -83,9 +73,9 @@ public class SwapConnecting extends LinearLayout implements SwapWorkflowActivity
/** /**
* Listens for feedback about a local repository being prepared: * Listens for feedback about a local repository being prepared:
* * Apk files copied to the LocalHTTPD webroot * * Apk files copied to the LocalHTTPD webroot
* * index.html file prepared * * index.html file prepared
* * Icons will be copied to the webroot in the background and so are not part of this process. * * Icons will be copied to the webroot in the background and so are not part of this process.
*/ */
class PrepareSwapReceiver extends Receiver { class PrepareSwapReceiver extends Receiver {
@ -116,7 +106,7 @@ public class SwapConnecting extends LinearLayout implements SwapWorkflowActivity
/** /**
* Listens for feedback about a repo update process taking place. * Listens for feedback about a repo update process taking place.
* * Tracks an index.jar download and show the progress messages * Tracks an index.jar download and show the progress messages
*/ */
class ConnectSwapReceiver extends Receiver { class ConnectSwapReceiver extends Receiver {
@ -146,7 +136,7 @@ public class SwapConnecting extends LinearLayout implements SwapWorkflowActivity
@Override @Override
protected void onComplete() { protected void onComplete() {
getActivity().showSwapConnected(); getActivity().inflateSwapView(R.layout.swap_success);
} }
} }
@ -165,8 +155,9 @@ public class SwapConnecting extends LinearLayout implements SwapWorkflowActivity
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
TextView progressText = (TextView) findViewById(R.id.heading); TextView progressText = (TextView) findViewById(R.id.heading);
TextView errorText = (TextView) findViewById(R.id.error); ProgressBar progressBar = findViewById(R.id.progress_bar);
Button backButton = (Button) findViewById(R.id.back); TextView errorText = (TextView) findViewById(R.id.error);
Button backButton = (Button) findViewById(R.id.back);
String message; String message;
if (intent.hasExtra(getMessageExtra())) { if (intent.hasExtra(getMessageExtra())) {
@ -177,11 +168,13 @@ public class SwapConnecting extends LinearLayout implements SwapWorkflowActivity
} }
progressText.setVisibility(View.VISIBLE); progressText.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.VISIBLE);
errorText.setVisibility(View.GONE); errorText.setVisibility(View.GONE);
backButton.setVisibility(View.GONE); backButton.setVisibility(View.GONE);
if (isError(intent)) { if (isError(intent)) {
progressText.setVisibility(View.GONE); progressText.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
errorText.setVisibility(View.VISIBLE); errorText.setVisibility(View.VISIBLE);
backButton.setVisibility(View.VISIBLE); backButton.setVisibility(View.VISIBLE);
return; return;
@ -192,29 +185,4 @@ public class SwapConnecting extends LinearLayout implements SwapWorkflowActivity
} }
} }
} }
@Override
public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) {
return true;
}
@Override
public int getStep() {
return SwapService.STEP_CONNECTING;
}
@Override
public int getPreviousStep() {
return SwapService.STEP_SELECT_APPS;
}
@ColorRes
public int getToolbarColour() {
return R.color.swap_bright_blue;
}
@Override
public String getToolbarTitle() {
return getResources().getString(R.string.swap_connecting);
}
} }

View File

@ -1,58 +0,0 @@
package org.fdroid.fdroid.views.swap;
import android.annotation.TargetApi;
import android.content.Context;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.Menu;
import android.view.MenuInflater;
import android.widget.RelativeLayout;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.localrepo.SwapService;
public class InitialLoadingView extends RelativeLayout implements SwapWorkflowActivity.InnerView {
public InitialLoadingView(Context context) {
super(context);
}
public InitialLoadingView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public InitialLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(21)
public InitialLoadingView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) {
return true;
}
@Override
public int getStep() {
return SwapService.STEP_INITIAL_LOADING;
}
@Override
public int getPreviousStep() {
return SwapService.STEP_JOIN_WIFI;
}
@ColorRes
public int getToolbarColour() {
return R.color.swap_blue;
}
@Override
public String getToolbarTitle() {
return getResources().getString(R.string.swap);
}
}

View File

@ -6,25 +6,18 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.MenuItemCompat;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.localrepo.SwapService; import org.fdroid.fdroid.localrepo.SwapView;
import org.fdroid.fdroid.net.WifiStateChangeService; import org.fdroid.fdroid.net.WifiStateChangeService;
public class JoinWifiView extends RelativeLayout implements SwapWorkflowActivity.InnerView { public class JoinWifiView extends SwapView {
public JoinWifiView(Context context) { public JoinWifiView(Context context) {
super(context); super(context);
@ -43,10 +36,6 @@ public class JoinWifiView extends RelativeLayout implements SwapWorkflowActivity
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
} }
private SwapWorkflowActivity getActivity() {
return (SwapWorkflowActivity) getContext();
}
@Override @Override
protected void onFinishInflate() { protected void onFinishInflate() {
super.onFinishInflate(); super.onFinishInflate();
@ -106,42 +95,6 @@ public class JoinWifiView extends RelativeLayout implements SwapWorkflowActivity
getActivity().startActivity(new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK)); getActivity().startActivity(new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK));
} }
@Override
public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.swap_next, menu);
MenuItem next = menu.findItem(R.id.action_next);
MenuItemCompat.setShowAsAction(next,
MenuItemCompat.SHOW_AS_ACTION_ALWAYS | MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT);
next.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
getActivity().showSelectApps();
return true;
}
});
return true;
}
@Override
public int getStep() {
return SwapService.STEP_JOIN_WIFI;
}
@Override
public int getPreviousStep() {
return SwapService.STEP_INTRO;
}
@ColorRes
public int getToolbarColour() {
return R.color.swap_blue;
}
@Override
public String getToolbarTitle() {
return getResources().getString(R.string.swap_join_same_wifi);
}
private final BroadcastReceiver onWifiStateChange = new BroadcastReceiver() { private final BroadcastReceiver onWifiStateChange = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {

View File

@ -2,21 +2,14 @@ package org.fdroid.fdroid.views.swap;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.v4.view.MenuItemCompat;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.RelativeLayout;
import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.localrepo.SwapService; import org.fdroid.fdroid.localrepo.SwapView;
public class NfcView extends RelativeLayout implements SwapWorkflowActivity.InnerView { public class NfcView extends SwapView {
public NfcView(Context context) { public NfcView(Context context) {
super(context); super(context);
@ -35,10 +28,6 @@ public class NfcView extends RelativeLayout implements SwapWorkflowActivity.Inne
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
} }
private SwapWorkflowActivity getActivity() {
return (SwapWorkflowActivity) getContext();
}
@Override @Override
protected void onFinishInflate() { protected void onFinishInflate() {
super.onFinishInflate(); super.onFinishInflate();
@ -50,40 +39,4 @@ public class NfcView extends RelativeLayout implements SwapWorkflowActivity.Inne
} }
}); });
} }
@Override
public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.swap_skip, menu);
MenuItem next = menu.findItem(R.id.action_next);
MenuItemCompat.setShowAsAction(next,
MenuItemCompat.SHOW_AS_ACTION_ALWAYS | MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT);
next.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
getActivity().showWifiQr();
return true;
}
});
return true;
}
@Override
public int getStep() {
return SwapService.STEP_SHOW_NFC;
}
@Override
public int getPreviousStep() {
return SwapService.STEP_JOIN_WIFI;
}
@ColorRes
public int getToolbarColour() {
return R.color.swap_blue;
}
@Override
public String getToolbarTitle() {
return getResources().getString(R.string.swap_nfc_title);
}
} }

View File

@ -8,22 +8,16 @@ import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader; import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader; import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.CursorAdapter; import android.support.v4.widget.CursorAdapter;
import android.support.v7.widget.SearchView;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.ContextThemeWrapper; import android.view.ContextThemeWrapper;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
@ -32,16 +26,13 @@ import android.widget.CompoundButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.data.InstalledAppProvider; import org.fdroid.fdroid.data.InstalledAppProvider;
import org.fdroid.fdroid.data.Schema.InstalledAppTable; import org.fdroid.fdroid.data.Schema.InstalledAppTable;
import org.fdroid.fdroid.localrepo.SwapService; import org.fdroid.fdroid.localrepo.SwapService;
import org.fdroid.fdroid.localrepo.SwapView;
public class SelectAppsView extends ListView implements public class SelectAppsView extends SwapView implements LoaderManager.LoaderCallbacks<Cursor> {
SwapWorkflowActivity.InnerView,
LoaderManager.LoaderCallbacks<Cursor>,
SearchView.OnQueryTextListener {
public SelectAppsView(Context context) { public SelectAppsView(Context context) {
super(context); super(context);
@ -60,86 +51,34 @@ public class SelectAppsView extends ListView implements
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
} }
private SwapWorkflowActivity getActivity() {
return (SwapWorkflowActivity) getContext();
}
private SwapService getState() { private SwapService getState() {
return getActivity().getState(); return getActivity().getState();
} }
private static final int LOADER_INSTALLED_APPS = 253341534; private ListView listView;
private AppListAdapter adapter; private AppListAdapter adapter;
private String currentFilterString;
@Override @Override
protected void onFinishInflate() { protected void onFinishInflate() {
super.onFinishInflate(); super.onFinishInflate();
adapter = new AppListAdapter(this, getContext(), listView = findViewById(R.id.list);
adapter = new AppListAdapter(listView, getContext(),
getContext().getContentResolver().query(InstalledAppProvider.getContentUri(), getContext().getContentResolver().query(InstalledAppProvider.getContentUri(),
InstalledAppTable.Cols.ALL, null, null, null)); InstalledAppTable.Cols.ALL, null, null, null));
setAdapter(adapter); listView.setAdapter(adapter);
setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
// either reconnect with an existing loader or start a new one // either reconnect with an existing loader or start a new one
getActivity().getSupportLoaderManager().initLoader(LOADER_INSTALLED_APPS, null, this); getActivity().getSupportLoaderManager().initLoader(R.layout.swap_select_apps, null, this);
setOnItemClickListener(new AdapterView.OnItemClickListener() { listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) { public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
toggleAppSelected(position); toggleAppSelected(position);
} }
}); });
} }
@Override
public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.swap_next_search, menu);
MenuItem nextMenuItem = menu.findItem(R.id.action_next);
int flags = MenuItemCompat.SHOW_AS_ACTION_ALWAYS | MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT;
MenuItemCompat.setShowAsAction(nextMenuItem, flags);
nextMenuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
getActivity().onAppsSelected();
return true;
}
});
SearchView searchView = new SearchView(getActivity());
MenuItem searchMenuItem = menu.findItem(R.id.action_search);
MenuItemCompat.setActionView(searchMenuItem, searchView);
MenuItemCompat.setShowAsAction(searchMenuItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
searchView.setOnQueryTextListener(this);
return true;
}
@Override
public int getStep() {
return SwapService.STEP_SELECT_APPS;
}
@Override
public int getPreviousStep() {
// TODO: The STEP_JOIN_WIFI step isn't shown first, need to make it
// so that it is, or so that this doesn't go back there.
return getState().isConnectingWithPeer() ? SwapService.STEP_INTRO : SwapService.STEP_JOIN_WIFI;
}
@ColorRes
public int getToolbarColour() {
return R.color.swap_bright_blue;
}
@Override
public String getToolbarTitle() {
return getResources().getString(R.string.swap_choose_apps);
}
private void toggleAppSelected(int position) { private void toggleAppSelected(int position) {
Cursor c = (Cursor) adapter.getItem(position); Cursor c = (Cursor) adapter.getItem(position);
String packageName = c.getString(c.getColumnIndex(InstalledAppTable.Cols.Package.NAME)); String packageName = c.getString(c.getColumnIndex(InstalledAppTable.Cols.Package.NAME));
@ -174,13 +113,13 @@ public class SelectAppsView extends ListView implements
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
adapter.swapCursor(cursor); adapter.swapCursor(cursor);
for (int i = 0; i < getCount(); i++) { for (int i = 0; i < listView.getCount(); i++) {
Cursor c = (Cursor) getItemAtPosition(i); Cursor c = (Cursor) listView.getItemAtPosition(i);
String packageName = c.getString(c.getColumnIndex(InstalledAppTable.Cols.Package.NAME)); String packageName = c.getString(c.getColumnIndex(InstalledAppTable.Cols.Package.NAME));
getState().ensureFDroidSelected(); getState().ensureFDroidSelected();
for (String selected : getState().getAppsToSwap()) { for (String selected : getState().getAppsToSwap()) {
if (TextUtils.equals(packageName, selected)) { if (TextUtils.equals(packageName, selected)) {
setItemChecked(i, true); listView.setItemChecked(i, true);
} }
} }
} }
@ -191,26 +130,6 @@ public class SelectAppsView extends ListView implements
adapter.swapCursor(null); adapter.swapCursor(null);
} }
@Override
public boolean onQueryTextChange(String newText) {
String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
if (currentFilterString == null && newFilter == null) {
return true;
}
if (currentFilterString != null && currentFilterString.equals(newFilter)) {
return true;
}
currentFilterString = newFilter;
getActivity().getSupportLoaderManager().restartLoader(LOADER_INSTALLED_APPS, null, this);
return true;
}
@Override
public boolean onQueryTextSubmit(String query) {
// this is not needed since we respond to every change in text
return true;
}
private class AppListAdapter extends CursorAdapter { private class AppListAdapter extends CursorAdapter {
@Nullable @Nullable

View File

@ -7,28 +7,23 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.graphics.LightingColorFilter; import android.graphics.LightingColorFilter;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.QrGenAsyncTask; import org.fdroid.fdroid.QrGenAsyncTask;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.localrepo.SwapService; import org.fdroid.fdroid.localrepo.SwapView;
import org.fdroid.fdroid.net.WifiStateChangeService; import org.fdroid.fdroid.net.WifiStateChangeService;
import org.fdroid.fdroid.views.swap.device.camera.CameraCharacteristicsChecker; import org.fdroid.fdroid.views.swap.device.camera.CameraCharacteristicsChecker;
public class SendFDroidView extends ScrollView implements SwapWorkflowActivity.InnerView { public class SendFDroidView extends SwapView {
private static final String TAG = "SendFDroidView"; private static final String TAG = "SendFDroidView";
@ -49,10 +44,6 @@ public class SendFDroidView extends ScrollView implements SwapWorkflowActivity.I
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
} }
private SwapWorkflowActivity getActivity() {
return (SwapWorkflowActivity) getContext();
}
@Override @Override
protected void onFinishInflate() { protected void onFinishInflate() {
super.onFinishInflate(); super.onFinishInflate();
@ -96,31 +87,6 @@ public class SendFDroidView extends ScrollView implements SwapWorkflowActivity.I
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onWifiStateChanged); LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onWifiStateChanged);
} }
@Override
public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) {
return false;
}
@Override
public int getStep() {
return SwapService.STEP_INTRO;
}
@Override
public int getPreviousStep() {
return SwapService.STEP_INTRO;
}
@ColorRes
public int getToolbarColour() {
return R.color.swap_blue;
}
@Override
public String getToolbarTitle() {
return getResources().getString(R.string.swap_send_fdroid);
}
@SuppressLint("HardwareIds") @SuppressLint("HardwareIds")
private void setUIFromWifi() { private void setUIFromWifi() {
if (TextUtils.isEmpty(FDroidApp.repo.address)) { if (TextUtils.isEmpty(FDroidApp.repo.address)) {

View File

@ -7,16 +7,12 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.widget.SwitchCompat; import android.support.v7.widget.SwitchCompat;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
@ -25,13 +21,13 @@ import android.widget.CompoundButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ListView; import android.widget.ListView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import cc.mvdan.accesspoint.WifiApControl; import cc.mvdan.accesspoint.WifiApControl;
import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.localrepo.SwapService; import org.fdroid.fdroid.localrepo.SwapService;
import org.fdroid.fdroid.localrepo.SwapView;
import org.fdroid.fdroid.localrepo.peers.Peer; import org.fdroid.fdroid.localrepo.peers.Peer;
import org.fdroid.fdroid.net.WifiStateChangeService; import org.fdroid.fdroid.net.WifiStateChangeService;
import rx.Subscriber; import rx.Subscriber;
@ -40,7 +36,7 @@ import rx.Subscription;
import java.util.ArrayList; import java.util.ArrayList;
@SuppressWarnings("LineLength") @SuppressWarnings("LineLength")
public class StartSwapView extends RelativeLayout implements SwapWorkflowActivity.InnerView { public class StartSwapView extends SwapView {
private static final String TAG = "StartSwapView"; private static final String TAG = "StartSwapView";
@ -58,7 +54,6 @@ public class StartSwapView extends RelativeLayout implements SwapWorkflowActivit
super(context, attrs); super(context, attrs);
} }
@TargetApi(11)
public StartSwapView(Context context, AttributeSet attrs, int defStyleAttr) { public StartSwapView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
} }
@ -91,10 +86,6 @@ public class StartSwapView extends RelativeLayout implements SwapWorkflowActivit
} }
private SwapWorkflowActivity getActivity() {
return (SwapWorkflowActivity) getContext();
}
private SwapService getManager() { private SwapService getManager() {
return getActivity().getState(); return getActivity().getState();
} }
@ -456,35 +447,4 @@ public class StartSwapView extends RelativeLayout implements SwapWorkflowActivit
private void onPeerSelected(Peer peer) { private void onPeerSelected(Peer peer) {
getActivity().swapWith(peer); getActivity().swapWith(peer);
} }
@Override
public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) {
return false;
}
@Override
public int getStep() {
return SwapService.STEP_INTRO;
}
@Override
public int getPreviousStep() {
// TODO: Currently this is handleed by the SwapWorkflowActivity as a special case, where
// if getStep is STEP_INTRO, don't even bother asking for getPreviousStep. But that is a
// bit messy. It would be nicer if this was handled using the same mechanism as everything
// else.
return SwapService.STEP_INTRO;
}
@Override
@ColorRes
public int getToolbarColour() {
return R.color.swap_bright_blue;
}
@Override
public String getToolbarTitle() {
return getResources().getString(R.string.swap_nearby);
}
} }

View File

@ -12,22 +12,16 @@ import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader; import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader; import android.support.v4.content.Loader;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.CursorAdapter; import android.support.v4.widget.CursorAdapter;
import android.support.v7.widget.SearchView;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
@ -47,7 +41,7 @@ import org.fdroid.fdroid.data.App;
import org.fdroid.fdroid.data.AppProvider; import org.fdroid.fdroid.data.AppProvider;
import org.fdroid.fdroid.data.Repo; import org.fdroid.fdroid.data.Repo;
import org.fdroid.fdroid.data.Schema.AppMetadataTable; import org.fdroid.fdroid.data.Schema.AppMetadataTable;
import org.fdroid.fdroid.localrepo.SwapService; import org.fdroid.fdroid.localrepo.SwapView;
import org.fdroid.fdroid.net.Downloader; import org.fdroid.fdroid.net.Downloader;
import org.fdroid.fdroid.net.DownloaderService; import org.fdroid.fdroid.net.DownloaderService;
@ -55,35 +49,26 @@ import java.util.List;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
public class SwapAppsView extends ListView implements public class SwapSuccessView extends SwapView implements LoaderManager.LoaderCallbacks<Cursor> {
SwapWorkflowActivity.InnerView, private static final String TAG = "SwapAppsView";
LoaderManager.LoaderCallbacks<Cursor>,
SearchView.OnQueryTextListener {
public SwapAppsView(Context context) { public SwapSuccessView(Context context) {
super(context); super(context);
} }
public SwapAppsView(Context context, AttributeSet attrs) { public SwapSuccessView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
} }
public SwapAppsView(Context context, AttributeSet attrs, int defStyleAttr) { public SwapSuccessView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
} }
@TargetApi(21) @TargetApi(21)
public SwapAppsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public SwapSuccessView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
} }
private SwapWorkflowActivity getActivity() {
return (SwapWorkflowActivity) getContext();
}
private static final int LOADER_SWAPABLE_APPS = 759283741;
private static final String TAG = "SwapAppsView";
private Repo repo; private Repo repo;
private AppListAdapter adapter; private AppListAdapter adapter;
private String currentFilterString; private String currentFilterString;
@ -102,11 +87,11 @@ public class SwapAppsView extends ListView implements
adapter = new AppListAdapter(getContext(), getContext().getContentResolver().query( adapter = new AppListAdapter(getContext(), getContext().getContentResolver().query(
AppProvider.getRepoUri(repo), AppMetadataTable.Cols.ALL, null, null, null)); AppProvider.getRepoUri(repo), AppMetadataTable.Cols.ALL, null, null, null));
ListView listView = findViewById(R.id.list);
setAdapter(adapter); listView.setAdapter(adapter);
// either reconnect with an existing loader or start a new one // either reconnect with an existing loader or start a new one
getActivity().getSupportLoaderManager().initLoader(LOADER_SWAPABLE_APPS, null, this); getActivity().getSupportLoaderManager().initLoader(R.layout.swap_success, null, this);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver( LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
pollForUpdatesReceiver, new IntentFilter(UpdateService.LOCAL_ACTION_STATUS)); pollForUpdatesReceiver, new IntentFilter(UpdateService.LOCAL_ACTION_STATUS));
@ -148,41 +133,6 @@ public class SwapAppsView extends ListView implements
}, 5000); }, 5000);
} }
@Override
public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.swap_search, menu);
SearchView searchView = new SearchView(getActivity());
MenuItem searchMenuItem = menu.findItem(R.id.action_search);
MenuItemCompat.setActionView(searchMenuItem, searchView);
MenuItemCompat.setShowAsAction(searchMenuItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
searchView.setOnQueryTextListener(this);
return true;
}
@Override
public int getStep() {
return SwapService.STEP_SUCCESS;
}
@Override
public int getPreviousStep() {
return SwapService.STEP_INTRO;
}
@ColorRes
public int getToolbarColour() {
return R.color.swap_bright_blue;
}
@Override
public String getToolbarTitle() {
return getResources().getString(R.string.swap_success);
}
@Override @Override
public CursorLoader onCreateLoader(int id, Bundle args) { public CursorLoader onCreateLoader(int id, Bundle args) {
Uri uri = TextUtils.isEmpty(currentFilterString) Uri uri = TextUtils.isEmpty(currentFilterString)
@ -203,26 +153,6 @@ public class SwapAppsView extends ListView implements
adapter.swapCursor(null); adapter.swapCursor(null);
} }
@Override
public boolean onQueryTextChange(String newText) {
String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
if (currentFilterString == null && newFilter == null) {
return true;
}
if (currentFilterString != null && currentFilterString.equals(newFilter)) {
return true;
}
currentFilterString = newFilter;
getActivity().getSupportLoaderManager().restartLoader(LOADER_SWAPABLE_APPS, null, this);
return true;
}
@Override
public boolean onQueryTextSubmit(String query) {
// this is not needed since we respond to every change in text
return true;
}
private class AppListAdapter extends CursorAdapter { private class AppListAdapter extends CursorAdapter {
private class ViewHolder { private class ViewHolder {

View File

@ -17,20 +17,25 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.provider.Settings; import android.provider.Settings;
import android.support.annotation.ColorRes;
import android.support.annotation.LayoutRes; import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import cc.mvdan.accesspoint.WifiApControl; import cc.mvdan.accesspoint.WifiApControl;
import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentIntegrator;
@ -48,6 +53,7 @@ import org.fdroid.fdroid.installer.InstallManagerService;
import org.fdroid.fdroid.installer.Installer; import org.fdroid.fdroid.installer.Installer;
import org.fdroid.fdroid.localrepo.LocalRepoManager; import org.fdroid.fdroid.localrepo.LocalRepoManager;
import org.fdroid.fdroid.localrepo.SwapService; import org.fdroid.fdroid.localrepo.SwapService;
import org.fdroid.fdroid.localrepo.SwapView;
import org.fdroid.fdroid.localrepo.peers.Peer; import org.fdroid.fdroid.localrepo.peers.Peer;
import org.fdroid.fdroid.net.BluetoothDownloader; import org.fdroid.fdroid.net.BluetoothDownloader;
import org.fdroid.fdroid.net.HttpDownloader; import org.fdroid.fdroid.net.HttpDownloader;
@ -68,6 +74,7 @@ import java.util.TimerTask;
*/ */
@SuppressWarnings("LineLength") @SuppressWarnings("LineLength")
public class SwapWorkflowActivity extends AppCompatActivity { public class SwapWorkflowActivity extends AppCompatActivity {
private static final String TAG = "SwapWorkflowActivity";
/** /**
* When connecting to a swap, we then go and initiate a connection with that * When connecting to a swap, we then go and initiate a connection with that
@ -87,28 +94,6 @@ public class SwapWorkflowActivity extends AppCompatActivity {
private ViewGroup container; private ViewGroup container;
/**
* A UI component (subclass of {@link View}) which forms part of the swap workflow.
* There is a one to one mapping between an {@link org.fdroid.fdroid.views.swap.SwapWorkflowActivity.InnerView}
* and a {@link SwapService.SwapStep}, and these views know what
* the previous view before them should be.
*/
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. */
@SwapService.SwapStep int getStep();
@SwapService.SwapStep int getPreviousStep();
@ColorRes int getToolbarColour();
String getToolbarTitle();
}
private static final String TAG = "SwapWorkflowActivity";
private static final int CONNECT_TO_SWAP = 1; private static final int CONNECT_TO_SWAP = 1;
private static final int REQUEST_BLUETOOTH_ENABLE_FOR_SWAP = 2; private static final int REQUEST_BLUETOOTH_ENABLE_FOR_SWAP = 2;
private static final int REQUEST_BLUETOOTH_DISCOVERABLE = 3; private static final int REQUEST_BLUETOOTH_DISCOVERABLE = 3;
@ -116,7 +101,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
private static final int REQUEST_WRITE_SETTINGS_PERMISSION = 5; private static final int REQUEST_WRITE_SETTINGS_PERMISSION = 5;
private Toolbar toolbar; private Toolbar toolbar;
private InnerView currentView; private SwapView currentView;
private boolean hasPreparedLocalRepo; private boolean hasPreparedLocalRepo;
private PrepareSwapRepo updateSwappableAppsTask; private PrepareSwapRepo updateSwappableAppsTask;
private NewRepoConfig confirmSwapConfig; private NewRepoConfig confirmSwapConfig;
@ -165,12 +150,50 @@ public class SwapWorkflowActivity extends AppCompatActivity {
@Override @Override
public void onBackPressed() { public void onBackPressed() {
if (currentView.getStep() == SwapService.STEP_INTRO) { if (currentView.getLayoutResId() == SwapService.STEP_INTRO) {
SwapService.stop(this); SwapService.stop(this); // TODO SwapService should always be running, while swap is running
finish(); finish();
} else { } else {
int nextStep = currentView.getPreviousStep(); // TODO: Currently StartSwapView is handleed by the SwapWorkflowActivity as a special case, where
getService().setStep(nextStep); // if getLayoutResId is STEP_INTRO, don't even bother asking for getPreviousStep. But that is a
// bit messy. It would be nicer if this was handled using the same mechanism as everything
// else.
int nextStep = -1;
switch (currentView.getLayoutResId()) {
case R.layout.swap_confirm_receive:
nextStep = SwapService.STEP_INTRO;
break;
case R.layout.swap_connecting:
nextStep = R.layout.swap_select_apps;
break;
case R.layout.swap_initial_loading:
nextStep = R.layout.swap_join_wifi;
break;
case R.layout.swap_join_wifi:
nextStep = SwapService.STEP_INTRO;
break;
case R.layout.swap_nfc:
nextStep = R.layout.swap_join_wifi;
break;
case R.layout.swap_select_apps:
// TODO: The STEP_JOIN_WIFI step isn't shown first, need to make it
// so that it is, or so that this doesn't go back there.
nextStep = getState().isConnectingWithPeer() ? SwapService.STEP_INTRO : R.layout.swap_join_wifi;
break;
case R.layout.swap_send_fdroid:
nextStep = SwapService.STEP_INTRO;
break;
case R.layout.swap_start_swap:
nextStep = SwapService.STEP_INTRO;
break;
case R.layout.swap_success:
nextStep = SwapService.STEP_INTRO;
break;
case R.layout.swap_wifi_qr:
nextStep = R.layout.swap_join_wifi;
break;
}
getService().setCurrentView(nextStep);
showRelevantView(); showRelevantView();
} }
} }
@ -194,7 +217,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
toolbar.setTitleTextAppearance(getApplicationContext(), R.style.SwapTheme_Wizard_Text_Toolbar); toolbar.setTitleTextAppearance(getApplicationContext(), R.style.SwapTheme_Wizard_Text_Toolbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
container = (ViewGroup) findViewById(R.id.fragment_container); container = (ViewGroup) findViewById(R.id.container);
localBroadcastManager = LocalBroadcastManager.getInstance(this); localBroadcastManager = LocalBroadcastManager.getInstance(this);
wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
@ -211,9 +234,99 @@ public class SwapWorkflowActivity extends AppCompatActivity {
@Override @Override
public boolean onPrepareOptionsMenu(Menu menu) { public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear(); menu.clear();
boolean parent = super.onPrepareOptionsMenu(menu);
boolean inner = currentView != null && currentView.buildMenu(menu, getMenuInflater()); MenuInflater menuInflater = getMenuInflater();
return parent || inner; switch (currentView.getLayoutResId()) {
case R.layout.swap_select_apps:
menuInflater.inflate(R.menu.swap_next_search, menu);
setUpNextButton(menu, R.string.next);
setUpSearchView(menu);
return true;
case R.layout.swap_success:
menuInflater.inflate(R.menu.swap_search, menu);
setUpSearchView(menu);
return true;
case R.layout.swap_join_wifi:
menuInflater.inflate(R.menu.swap_next, menu);
setUpNextButton(menu, R.string.next);
return true;
case R.layout.swap_nfc:
menuInflater.inflate(R.menu.swap_next, menu);
setUpNextButton(menu, R.string.skip);
return true;
}
return super.onPrepareOptionsMenu(menu);
}
private void setUpNextButton(Menu menu, @StringRes int titleResId) {
MenuItem next = menu.findItem(R.id.action_next);
CharSequence title = getString(titleResId);
next.setTitle(title);
next.setTitleCondensed(title);
MenuItemCompat.setShowAsAction(next,
MenuItemCompat.SHOW_AS_ACTION_ALWAYS | MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT);
next.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
sendNext();
return true;
}
});
}
void sendNext() {
int currentLayoutResId = currentView.getLayoutResId();
switch (currentLayoutResId) {
case R.layout.swap_select_apps:
onAppsSelected();
break;
case R.layout.swap_join_wifi:
inflateSwapView(R.layout.swap_select_apps);
break;
case R.layout.swap_nfc:
inflateSwapView(R.layout.swap_wifi_qr);
break;
}
}
private void setUpSearchView(Menu menu) {
SearchView searchView = new SearchView(this);
MenuItem searchMenuItem = menu.findItem(R.id.action_search);
MenuItemCompat.setActionView(searchMenuItem, searchView);
MenuItemCompat.setShowAsAction(searchMenuItem, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String newText) {
String currentFilterString = currentView.getCurrentFilterString();
String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
if (currentFilterString == null && newFilter == null) {
return true;
}
if (currentFilterString != null && currentFilterString.equals(newFilter)) {
return true;
}
currentView.setCurrentFilterString(newFilter);
if (currentView instanceof SelectAppsView) {
getSupportLoaderManager().restartLoader(currentView.getLayoutResId(), null,
(SelectAppsView) currentView);
} else if (currentView instanceof SwapSuccessView) {
getSupportLoaderManager().restartLoader(currentView.getLayoutResId(), null,
(SwapSuccessView) currentView);
} else {
throw new IllegalStateException(currentView.getClass() + " does not have Loader!");
}
return true;
}
@Override
public boolean onQueryTextChange(String s) {
return true;
}
});
} }
@Override @Override
@ -310,7 +423,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
private void showRelevantView(boolean forceReload) { private void showRelevantView(boolean forceReload) {
if (service == null) { if (service == null) {
showInitialLoading(); inflateSwapView(R.layout.swap_initial_loading);
return; return;
} }
@ -323,62 +436,50 @@ public class SwapWorkflowActivity extends AppCompatActivity {
return; return;
} }
if (!forceReload && (container.getVisibility() == View.GONE || currentView != null && currentView.getStep() == service.getStep())) { if (!forceReload && (container.getVisibility() == View.GONE || currentView != null && currentView.getLayoutResId() == service.getCurrentView())) {
// Already showing the correct step, so don't bother changing anything. // Already showing the correct step, so don't bother changing anything.
return; return;
} }
switch (service.getStep()) { int currentView = service.getCurrentView();
switch (currentView) {
case SwapService.STEP_INTRO: case SwapService.STEP_INTRO:
showIntro(); showIntro();
return;
case R.layout.swap_nfc:
if (!attemptToShowNfc()) {
inflateSwapView(R.layout.swap_wifi_qr);
return;
}
break; break;
case SwapService.STEP_SELECT_APPS: case R.layout.swap_connecting:
showSelectApps();
break;
case SwapService.STEP_SHOW_NFC:
showNfc();
break;
case SwapService.STEP_JOIN_WIFI:
showJoinWifi();
break;
case SwapService.STEP_WIFI_QR:
showWifiQr();
break;
case SwapService.STEP_SUCCESS:
showSwapConnected();
break;
case SwapService.STEP_CONNECTING:
// TODO: Properly decide what to do here (i.e. returning to the activity after it was connecting)... // TODO: Properly decide what to do here (i.e. returning to the activity after it was connecting)...
inflateInnerView(R.layout.swap_blank); inflateSwapView(R.layout.swap_start_swap);
break; return;
} }
inflateSwapView(currentView);
} }
public SwapService getState() { public SwapService getState() {
return service; return service;
} }
private void showNfc() { public SwapView inflateSwapView(@LayoutRes int viewRes) {
if (!attemptToShowNfc()) {
showWifiQr();
}
}
private InnerView inflateInnerView(@LayoutRes int viewRes) {
container.removeAllViews(); container.removeAllViews();
View view = ((LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(viewRes, container, false); View view = ((LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(viewRes, container, false);
currentView = (InnerView) view; currentView = (SwapView) view;
currentView.setLayoutResId(viewRes);
// Don't actually set the step to STEP_INITIAL_LOADING, as we are going to use this view // Don't actually set the step to STEP_INITIAL_LOADING, as we are going to use this view
// purely as a placeholder for _whatever view is meant to be shown_. // purely as a placeholder for _whatever view is meant to be shown_.
if (currentView.getStep() != SwapService.STEP_INITIAL_LOADING) { if (currentView.getLayoutResId() != R.layout.swap_initial_loading) {
if (service == null) { if (service == null) {
throw new IllegalStateException("We are not in the STEP_INITIAL_LOADING state, but the service is not ready."); throw new IllegalStateException("We are not in the STEP_INITIAL_LOADING state, but the service is not ready.");
} }
service.setStep(currentView.getStep()); service.setCurrentView(currentView.getLayoutResId());
} }
toolbar.setBackgroundColor(getResources().getColor(currentView.getToolbarColour())); toolbar.setBackgroundColor(currentView.getToolbarColour());
toolbar.setTitle(currentView.getToolbarTitle()); toolbar.setTitle(currentView.getToolbarTitle());
toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp); toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp);
toolbar.setNavigationOnClickListener(new View.OnClickListener() { toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@ -398,10 +499,6 @@ public class SwapWorkflowActivity extends AppCompatActivity {
finish(); finish();
} }
private void showInitialLoading() {
inflateInnerView(R.layout.swap_initial_loading);
}
public void showIntro() { public void showIntro() {
// If we were previously swapping with a specific client, forget that we were doing that, // If we were previously swapping with a specific client, forget that we were doing that,
// as we are starting over now. // as we are starting over now.
@ -414,11 +511,13 @@ public class SwapWorkflowActivity extends AppCompatActivity {
} }
} }
inflateInnerView(R.layout.swap_blank); inflateSwapView(R.layout.swap_start_swap);
} }
private void showConfirmSwap(@NonNull NewRepoConfig config) { private void showConfirmSwap(@NonNull NewRepoConfig config) {
((ConfirmReceive) inflateInnerView(R.layout.swap_confirm_receive)).setup(config); ((ConfirmReceiveView) inflateSwapView(R.layout.swap_confirm_receive)).setup(config);
TextView descriptionTextView = (TextView) findViewById(R.id.text_description);
descriptionTextView.setText(getResources().getString(R.string.swap_confirm_connect, config.getHost()));
} }
public void startQrWorkflow() { public void startQrWorkflow() {
@ -435,14 +534,10 @@ public class SwapWorkflowActivity extends AppCompatActivity {
}) })
.create().show(); .create().show();
} else { } else {
showWifiQr(); inflateSwapView(R.layout.swap_wifi_qr);
} }
} }
public void showSelectApps() {
inflateInnerView(R.layout.swap_select_apps);
}
/** /**
* On {@code android-26}, only apps with privileges can access * On {@code android-26}, only apps with privileges can access
* {@code WRITE_SETTINGS}. So this just shows the tethering settings * {@code WRITE_SETTINGS}. So this just shows the tethering settings
@ -471,7 +566,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
if (adapter == null if (adapter == null
|| Build.VERSION.SDK_INT >= 23 // TODO make Bluetooth work with content:// URIs || Build.VERSION.SDK_INT >= 23 // TODO make Bluetooth work with content:// URIs
|| (!adapter.isEnabled() && getService().getWifiSwap().isConnected())) { || (!adapter.isEnabled() && getService().getWifiSwap().isConnected())) {
showSendFDroid(); inflateSwapView(R.layout.swap_send_fdroid);
} else { } else {
sendFDroidBluetooth(); sendFDroidBluetooth();
} }
@ -503,8 +598,8 @@ public class SwapWorkflowActivity extends AppCompatActivity {
if (updateSwappableAppsTask == null && !hasPreparedLocalRepo) { if (updateSwappableAppsTask == null && !hasPreparedLocalRepo) {
updateSwappableAppsTask = new PrepareSwapRepo(getService().getAppsToSwap()); updateSwappableAppsTask = new PrepareSwapRepo(getService().getAppsToSwap());
updateSwappableAppsTask.execute(); updateSwappableAppsTask.execute();
getService().setStep(SwapService.STEP_CONNECTING); getService().setCurrentView(R.layout.swap_connecting);
inflateInnerView(R.layout.swap_connecting); inflateSwapView(R.layout.swap_connecting);
} else { } else {
onLocalRepoPrepared(); onLocalRepoPrepared();
} }
@ -513,10 +608,10 @@ public class SwapWorkflowActivity extends AppCompatActivity {
/** /**
* Once the UpdateAsyncTask has finished preparing our repository index, we can * Once the UpdateAsyncTask has finished preparing our repository index, we can
* show the next screen to the user. This will be one of two things: * show the next screen to the user. This will be one of two things:
* * If we directly selected a peer to swap with initially, we will skip straight to getting * * If we directly selected a peer to swap with initially, we will skip straight to getting
* the list of apps from that device. * the list of apps from that device.
* * Alternatively, if we didn't have a person to connect to, and instead clicked "Scan QR Code", * * 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. * then we want to show a QR code or NFC dialog.
*/ */
public void onLocalRepoPrepared() { public void onLocalRepoPrepared() {
updateSwappableAppsTask = null; updateSwappableAppsTask = null;
@ -524,29 +619,13 @@ public class SwapWorkflowActivity extends AppCompatActivity {
if (getService().isConnectingWithPeer()) { if (getService().isConnectingWithPeer()) {
startSwappingWithPeer(); startSwappingWithPeer();
} else if (!attemptToShowNfc()) { } else if (!attemptToShowNfc()) {
showWifiQr(); inflateSwapView(R.layout.swap_wifi_qr);
} }
} }
private void startSwappingWithPeer() { private void startSwappingWithPeer() {
getService().connectToPeer(); getService().connectToPeer();
inflateInnerView(R.layout.swap_connecting); inflateSwapView(R.layout.swap_connecting);
}
private void showJoinWifi() {
inflateInnerView(R.layout.swap_join_wifi);
}
public void showWifiQr() {
inflateInnerView(R.layout.swap_wifi_qr);
}
public void showSendFDroid() {
inflateInnerView(R.layout.swap_send_fdroid);
}
public void showSwapConnected() {
inflateInnerView(R.layout.swap_success);
} }
private boolean attemptToShowNfc() { private boolean attemptToShowNfc() {
@ -559,7 +638,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
boolean nfcMessageReady = NfcHelper.setPushMessage(this, Utils.getSharingUri(FDroidApp.repo)); boolean nfcMessageReady = NfcHelper.setPushMessage(this, Utils.getSharingUri(FDroidApp.repo));
if (Preferences.get().showNfcDuringSwap() && nfcMessageReady) { if (Preferences.get().showNfcDuringSwap() && nfcMessageReady) {
inflateInnerView(R.layout.swap_nfc); inflateSwapView(R.layout.swap_nfc);
return true; return true;
} }
return false; return false;
@ -567,20 +646,20 @@ public class SwapWorkflowActivity extends AppCompatActivity {
public void swapWith(Peer peer) { public void swapWith(Peer peer) {
getService().swapWith(peer); getService().swapWith(peer);
showSelectApps(); inflateSwapView(R.layout.swap_select_apps);
} }
/** /**
* This is for when we initiate a swap by viewing the "Are you sure you want to swap with" view * This is for when we initiate a swap by viewing the "Are you sure you want to swap with" view
* This can arise either: * This can arise either:
* * As a result of scanning a QR code (in which case we likely already have a repo setup) or * * As a result of scanning a QR code (in which case we likely already have a repo setup) or
* * As a result of the other device selecting our device in the "start swap" screen, in which * * As a result of the other device selecting our device in the "start swap" screen, in which
* case we are likely just sitting on the start swap screen also, and haven't configured * case we are likely just sitting on the start swap screen also, and haven't configured
* anything yet. * anything yet.
*/ */
public void swapWith(NewRepoConfig repoConfig) { public void swapWith(NewRepoConfig repoConfig) {
Peer peer = repoConfig.toPeer(); Peer peer = repoConfig.toPeer();
if (getService().getStep() == SwapService.STEP_INTRO || getService().getStep() == SwapService.STEP_CONFIRM_SWAP) { if (getService().getCurrentView() == SwapService.STEP_INTRO || getService().getCurrentView() == R.layout.swap_confirm_receive) {
// This will force the "Select apps to swap" workflow to begin. // This will force the "Select apps to swap" workflow to begin.
// TODO: Find a better way to decide whether we need to select the apps. Not sure if we // TODO: Find a better way to decide whether we need to select the apps. Not sure if we
// can or cannot be in STEP_INTRO with a full blown repo ready to swap. // can or cannot be in STEP_INTRO with a full blown repo ready to swap.
@ -784,15 +863,14 @@ public class SwapWorkflowActivity extends AppCompatActivity {
* the harder it becomes to reason about and debug the whole thing. Thus,this class * the harder it becomes to reason about and debug the whole thing. Thus,this class
* will periodically dump the state to logcat so that it is easier to see when certain * will periodically dump the state to logcat so that it is easier to see when certain
* protocols are enabled/disabled. * protocols are enabled/disabled.
* * <p>
* To view only this output from logcat: * To view only this output from logcat:
* * <p>
* adb logcat | grep 'Swap Status' * adb logcat | grep 'Swap Status'
* * <p>
* To exclude this output from logcat (it is very noisy): * To exclude this output from logcat (it is very noisy):
* * <p>
* adb logcat | grep -v 'Swap Status' * adb logcat | grep -v 'Swap Status'
*
*/ */
class SwapDebug { class SwapDebug {
@ -826,11 +904,11 @@ public class SwapWorkflowActivity extends AppCompatActivity {
Utils.debugLog("Swap Status", now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds() + " " + message); Utils.debugLog("Swap Status", now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds() + " " + message);
new Timer().schedule(new TimerTask() { new Timer().schedule(new TimerTask() {
@Override @Override
public void run() { public void run() {
new SwapDebug().logStatus(); new SwapDebug().logStatus();
} }
}, 1000 }, 1000
); );
} }
} }

View File

@ -7,31 +7,26 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.graphics.LightingColorFilter; import android.graphics.LightingColorFilter;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.QrGenAsyncTask; import org.fdroid.fdroid.QrGenAsyncTask;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.localrepo.SwapService; import org.fdroid.fdroid.localrepo.SwapView;
import org.fdroid.fdroid.net.WifiStateChangeService; import org.fdroid.fdroid.net.WifiStateChangeService;
import org.fdroid.fdroid.views.swap.device.camera.CameraCharacteristicsChecker; import org.fdroid.fdroid.views.swap.device.camera.CameraCharacteristicsChecker;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
public class WifiQrView extends ScrollView implements SwapWorkflowActivity.InnerView { public class WifiQrView extends SwapView {
private static final String TAG = "WifiQrView"; private static final String TAG = "WifiQrView";
@ -52,10 +47,6 @@ public class WifiQrView extends ScrollView implements SwapWorkflowActivity.Inner
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
} }
private SwapWorkflowActivity getActivity() {
return (SwapWorkflowActivity) getContext();
}
@Override @Override
protected void onFinishInflate() { protected void onFinishInflate() {
super.onFinishInflate(); super.onFinishInflate();
@ -98,32 +89,6 @@ public class WifiQrView extends ScrollView implements SwapWorkflowActivity.Inner
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onWifiStateChanged); LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onWifiStateChanged);
} }
@Override
public boolean buildMenu(Menu menu, @NonNull MenuInflater inflater) {
return false;
}
@Override
public int getStep() {
return SwapService.STEP_WIFI_QR;
}
@Override
public int getPreviousStep() {
// TODO: Find a way to make this optionally go back to the NFC screen if appropriate.
return SwapService.STEP_JOIN_WIFI;
}
@ColorRes
public int getToolbarColour() {
return R.color.swap_blue;
}
@Override
public String getToolbarTitle() {
return getResources().getString(R.string.swap_scan_qr);
}
private void setUIFromWifi() { private void setUIFromWifi() {
if (TextUtils.isEmpty(FDroidApp.repo.address)) { if (TextUtils.isEmpty(FDroidApp.repo.address)) {

View File

@ -1,32 +1,33 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout
xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/header" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:id="@+id/header"
android:layout_height="130dp" android:layout_width="match_parent"
android:layout_alignParentTop="true" android:layout_height="130dp"
tools:showIn="@layout/swap_blank"> android:layout_alignParentTop="true"
tools:showIn="@layout/swap_start_swap">
<ImageView <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:src="@drawable/swap_start_header" /> android:src="@drawable/swap_start_header"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:padding="20dp" android:padding="20dp"
android:paddingLeft="30dp" android:paddingLeft="30dp"
android:paddingRight="30dp" android:paddingRight="30dp"
android:paddingEnd="30dp" android:paddingEnd="30dp"
android:gravity="center" android:gravity="center"
android:textAlignment="center" android:textAlignment="center"
android:text="@string/swap_intro" android:text="@string/swap_intro"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textSize="18sp" android:textSize="18sp"
tools:ignore="UnusedAttribute" /> tools:ignore="UnusedAttribute"/>
</RelativeLayout> </RelativeLayout>

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout
android:id="@+id/header" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:id="@+id/header"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:layout_alignParentTop="true"> android:layout_height="wrap_content"
android:layout_alignParentTop="true">
</RelativeLayout> </RelativeLayout>

View File

@ -5,20 +5,20 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<android.support.v7.widget.Toolbar <android.support.v7.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:titleTextAppearance="@style/SwapTheme.Wizard.Text" android:titleTextAppearance="@style/SwapTheme.Wizard.Text"
titleTextAppearance="@style/SwapTheme.Wizard.Text" titleTextAppearance="@style/SwapTheme.Wizard.Text"
android:minHeight="?attr/actionBarSize" android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
tools:ignore="UnusedAttribute" /> tools:ignore="UnusedAttribute"/>
<FrameLayout <FrameLayout
android:id="@+id/fragment_container" android:id="@+id/container"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" /> android:layout_height="fill_parent"/>
</LinearLayout> </LinearLayout>

View File

@ -1,96 +1,96 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout <RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
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:minHeight="?android:attr/listPreferredItemHeight" android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingBottom="2dip" android:paddingBottom="2dip"
android:paddingTop="2dip"> android:paddingTop="2dip">
<ImageView <ImageView
android:id="@android:id/icon" android:id="@android:id/icon"
android:layout_width="48dip" android:layout_width="48dip"
android:layout_height="48dip" android:layout_height="48dip"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart" android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_marginLeft="10dp" android:layout_marginLeft="10dp"
android:layout_marginTop="6dip" android:layout_marginTop="6dip"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
tools:src="@drawable/ic_launcher" /> tools:src="@drawable/ic_launcher"/>
<LinearLayout <LinearLayout
android:id="@+id/button_or_text" android:id="@+id/button_or_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:orientation="vertical" android:orientation="vertical"
android:gravity="end" android:gravity="end"
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd" android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
android:layout_marginRight="10dp"> android:layout_marginRight="10dp">
<Button <Button
android:id="@+id/btn_install" android:id="@+id/btn_install"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:backgroundTint="@color/swap_light_blue" android:backgroundTint="@color/swap_light_blue"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:maxEms="10" android:maxEms="10"
android:ellipsize="end" android:ellipsize="end"
android:singleLine="true" android:singleLine="true"
android:text="@string/menu_install" android:text="@string/menu_install"
tools:ignore="UnusedAttribute" /> tools:ignore="UnusedAttribute"/>
<TextView <TextView
android:id="@+id/status_installed" android:id="@+id/status_installed"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textStyle="italic" android:textStyle="italic"
android:text="@string/app_installed" /> android:text="@string/app_installed"/>
<TextView <TextView
android:id="@+id/status_incompatible" android:id="@+id/status_incompatible"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textStyle="italic" android:textStyle="italic"
android:textColor="@color/swap_incompatible" android:textColor="@color/swap_incompatible"
android:text="@string/app_incompatible" /> android:text="@string/app_incompatible"/>
</LinearLayout> </LinearLayout>
<TextView <TextView
android:id="@+id/name" android:id="@+id/name"
android:layout_toEndOf="@android:id/icon" android:layout_toEndOf="@android:id/icon"
android:layout_toRightOf="@android:id/icon" android:layout_toRightOf="@android:id/icon"
android:layout_toStartOf="@+id/button_or_text" android:layout_toStartOf="@+id/button_or_text"
android:layout_toLeftOf="@+id/button_or_text" android:layout_toLeftOf="@+id/button_or_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart" android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_marginLeft="10dp" android:layout_marginLeft="10dp"
android:layout_marginTop="6dip" android:layout_marginTop="6dip"
android:layout_marginBottom="6dip" android:layout_marginBottom="6dip"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
tools:text="F-Droid" /> tools:text="F-Droid"/>
<ProgressBar <ProgressBar
android:id="@+id/progress" android:id="@+id/progress"
android:visibility="gone" android:visibility="gone"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:indeterminate="true" android:indeterminate="true"
style="?android:attr/progressBarStyleHorizontal" style="?android:attr/progressBarStyleHorizontal"
android:layout_toEndOf="@android:id/icon" android:layout_toEndOf="@android:id/icon"
android:paddingStart="5dp" android:paddingStart="5dp"
android:paddingLeft="5dp" android:paddingLeft="5dp"
android:paddingEnd="5dp" android:paddingEnd="5dp"
android:paddingRight="5dp" android:paddingRight="5dp"
android:layout_toRightOf="@android:id/icon" android:layout_toRightOf="@android:id/icon"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_below="@+id/name" android:layout_below="@+id/name"
/> />
</RelativeLayout> </RelativeLayout>

View File

@ -1,210 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- TODO: Add paddingStart in places where there is only paddingLeft. However Android Studio lint
gives an error, which is discussed here:
http://stackoverflow.com/questions/27449776/conflicting-lint-messages-regarding-paddingstart-usage?lq=1
-->
<org.fdroid.fdroid.views.swap.StartSwapView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".views.swap.SwapWorkflowActivity">
<!-- Misc header -->
<include layout="@layout/start_swap_header" />
<!-- Bluetooth swap status + toggle -->
<LinearLayout
android:id="@+id/bluetooth_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/header"
android:padding="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:tint="@color/swap_grey_icon"
android:src="@drawable/ic_bluetooth_white" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="15dp"
android:paddingStart="15dp"
android:layout_weight="1.00"
tools:ignore="RtlSymmetry">
<TextView
android:id="@+id/bluetooth_visible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="@string/swap_visible_bluetooth"
android:textSize="18sp" />
<TextView
android:id="@+id/device_id_bluetooth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="SP-120"
android:textColor="@color/swap_light_text" />
</LinearLayout>
<android.support.v7.widget.SwitchCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:id="@+id/switch_bluetooth" />
</LinearLayout>
<!-- WiFi swap status + toggle -->
<LinearLayout
android:id="@+id/wifi_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/bluetooth_info"
android:padding="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:tint="@color/swap_grey_icon"
android:src="@drawable/ic_network_wifi_white" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="15dp"
android:paddingStart="15dp"
android:layout_weight="1.00"
tools:ignore="RtlSymmetry">
<TextView
android:id="@+id/wifi_visible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="@string/swap_not_visible_wifi"
android:textSize="18sp" />
<TextView
android:id="@+id/device_id_wifi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/swap_wifi_device_name"
android:textColor="@color/swap_light_text" />
<TextView
android:id="@+id/wifi_network"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="wifi network name"
android:textColor="@color/swap_bright_blue"
android:textSize="16sp" />
</LinearLayout>
<android.support.v7.widget.SwitchCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:id="@+id/switch_wifi" />
</LinearLayout>
<!-- Feedback for "searching for nearby people..." -->
<LinearLayout
android:id="@+id/feedback_searching"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/wifi_info"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:paddingBottom="5dp"
android:paddingTop="20dp">
<TextView
android:id="@+id/text_people_nearby"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/swap_people_nearby"
android:textColor="@color/swap_light_text"
android:layout_weight="1.00"/>
<ProgressBar
android:id="@+id/searching_people_nearby"
android:layout_width="24dp"
android:layout_height="24dp"
android:indeterminate="true" />
</LinearLayout>
<!-- Buttons to help the user when they can't find any peers. Shown at bottom of relative layout -->
<LinearLayout
android:id="@+id/cant_find_peers"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<Button
android:id="@+id/btn_send_fdroid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_fdroid_grey"
android:drawableStart="@drawable/ic_fdroid_grey"
android:text="@string/swap_send_fdroid"
android:drawablePadding="10dp"
android:paddingLeft="25dp"
android:paddingRight="25dp"
android:paddingEnd="25dp"
android:background="@android:color/transparent" />
<Button
android:id="@+id/btn_qr_scanner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_qr_grey"
android:drawableStart="@drawable/ic_qr_grey"
android:text="@string/swap_scan_qr"
android:drawablePadding="10dp"
android:paddingLeft="25dp"
android:paddingRight="25dp"
android:paddingEnd="25dp"
android:background="@android:color/transparent" />
</LinearLayout>
<!-- Heading for "can't find peers" -->
<TextView
android:id="@+id/header_cant_find_peers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/cant_find_peers"
android:text="@string/swap_cant_find_peers"
android:paddingLeft="20dp"
android:paddingStart="20dp"
android:paddingRight="20dp"
android:paddingEnd="20dp"
android:paddingTop="20dp"
android:textColor="@color/swap_light_text" />
<!-- List of all currently known peers (i.e. bluetooth and wifi devices that have been identified -->
<ListView
android:id="@+id/list_people_nearby"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/feedback_searching"
android:layout_above="@id/header_cant_find_peers">
</ListView>
</org.fdroid.fdroid.views.swap.StartSwapView>

View File

@ -1,12 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.fdroid.fdroid.views.swap.ConfirmReceive xmlns:android="http://schemas.android.com/apk/res/android" <org.fdroid.fdroid.views.swap.ConfirmReceiveView
xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" xmlns:swap="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent" swap:toolbarTitle="@string/swap_confirm"
android:background="@color/swap_blue" android:orientation="vertical"
android:padding="18dp"> android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/swap_blue"
android:padding="18dp">
<!-- Padding is 32px * 0.56 = 18dip --> <!-- Padding is 32px * 0.56 = 18dip -->
<ImageView <ImageView
@ -17,7 +20,7 @@
android:layout_width="117.6dp" android:layout_width="117.6dp"
android:layout_height="117.6dp" android:layout_height="117.6dp"
android:layout_centerHorizontal="true"/> android:layout_centerHorizontal="true"/>
<!-- 210 * 0.56 = 117.6 --> <!-- 210 * 0.56 = 117.6 -->
<TextView <TextView
android:id="@+id/text_title" android:id="@+id/text_title"
@ -27,10 +30,10 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="28sp" android:textSize="28sp"
android:lines="1" /> android:lines="1"/>
<!-- 60 * 0.56 = 33.6 --> <!-- 60 * 0.56 = 33.6 -->
<!-- Temporarily making it smaller than 33.6 until we figure out how to <!-- Temporarily making it smaller than 33.6 until we figure out how to
prevent line breaks on the hyphen in F-Droid. --> prevent line breaks on the hyphen in F-Droid. -->
<TextView <TextView
android:id="@+id/text_description" android:id="@+id/text_description"
@ -40,7 +43,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="25.75sp"/> android:textSize="25.75sp"/>
<!-- 46px * 0.56 = 25.76sp --> <!-- 46px * 0.56 = 25.76sp -->
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -49,9 +52,9 @@
android:layout_below="@+id/text_description" android:layout_below="@+id/text_description"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:layout_marginTop="45dp"> android:layout_marginTop="45dp">
<!-- 80px * 0.56 = 45dp --> <!-- 80px * 0.56 = 45dp -->
<!-- TODO: Remove associated style files style="@style/SwapTheme.Wizard.ReceiveSwap.Deny"--> <!-- TODO: Remove associated style files style="@style/SwapTheme.Wizard.ReceiveSwap.Deny"-->
<Button <Button
android:id="@+id/no_button" android:id="@+id/no_button"
android:text="@string/no" android:text="@string/no"
@ -60,7 +63,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="25dp" android:layout_marginEnd="25dp"
android:layout_marginRight="25dp" android:layout_marginRight="25dp"
tools:ignore="UnusedAttribute" /> tools:ignore="UnusedAttribute"/>
<!-- TODO: Remove associated style files style="@style/SwapTheme.Wizard.ReceiveSwap.Confirm" --> <!-- TODO: Remove associated style files style="@style/SwapTheme.Wizard.ReceiveSwap.Confirm" -->
<Button <Button
@ -69,8 +72,8 @@
android:backgroundTint="@color/swap_light_blue" android:backgroundTint="@color/swap_light_blue"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:ignore="UnusedAttribute" /> tools:ignore="UnusedAttribute"/>
</LinearLayout> </LinearLayout>
</org.fdroid.fdroid.views.swap.ConfirmReceive> </org.fdroid.fdroid.views.swap.ConfirmReceiveView>

View File

@ -1,50 +1,52 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.fdroid.fdroid.views.swap.SwapConnecting <org.fdroid.fdroid.views.swap.ConnectingView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:swap="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" swap:toolbarColor="@color/swap_bright_blue"
android:layout_width="match_parent" swap:toolbarTitle="@string/swap_connecting"
android:layout_height="match_parent"> android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView <TextView
android:id="@+id/heading" android:id="@+id/heading"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:textSize="20sp" android:textSize="20sp"
android:padding="30dp" android:padding="30dp"
android:textAlignment="center" android:textAlignment="center"
android:gravity="center" android:gravity="center"/>
tools:text="Connecting with Nexus 4"
tools:ignore="UnusedAttribute" />
<ProgressBar <ProgressBar
android:id="@+id/progress_bar"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:indeterminate="true" android:indeterminate="true"
android:layout_gravity="center" /> android:layout_centerInParent="true"
android:layout_below="@+id/heading"/>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:id="@+id/error" android:id="@+id/error"
android:textSize="20sp" android:textSize="20sp"
android:textAlignment="center" android:textAlignment="center"
android:gravity="center"
android:text="@string/swap_connection_misc_error" android:text="@string/swap_connection_misc_error"
android:visibility="gone" android:visibility="gone"
android:padding="30dp" android:padding="30dp"/>
tools:ignore="UnusedAttribute" />
<Button <Button
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@+id/error"
android:id="@+id/back" android:id="@+id/back"
android:backgroundTint="@color/swap_light_blue" android:backgroundTint="@color/swap_light_blue"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:layout_gravity="center_horizontal"
android:visibility="gone" android:visibility="gone"
android:text="@string/back" android:text="@string/back"/>
tools:ignore="UnusedAttribute" />
</org.fdroid.fdroid.views.swap.SwapConnecting> </org.fdroid.fdroid.views.swap.ConnectingView>

View File

@ -1,26 +1,29 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.fdroid.fdroid.views.swap.InitialLoadingView xmlns:android="http://schemas.android.com/apk/res/android" <org.fdroid.fdroid.localrepo.SwapView
android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" xmlns:swap="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent" swap:toolbarTitle="@string/swap"
android:background="@color/swap_blue" android:orientation="vertical"
android:paddingTop="38.8dp"> <!-- 69px * 96dpi / 160dpi --> android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/swap_blue"
android:paddingTop="38.8dp"> <!-- 69px * 96dpi / 160dpi -->
<ProgressBar <ProgressBar
android:id="@+id/progress" android:id="@+id/progress"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" android:layout_centerInParent="true"
/> />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/loading" android:text="@string/loading"
android:textSize="18sp" android:textSize="18sp"
android:layout_below="@+id/progress" android:layout_below="@+id/progress"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:layout_centerHorizontal="true" /> android:layout_centerHorizontal="true"/>
</org.fdroid.fdroid.views.swap.InitialLoadingView> </org.fdroid.fdroid.localrepo.SwapView>

View File

@ -1,12 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.fdroid.fdroid.views.swap.JoinWifiView xmlns:android="http://schemas.android.com/apk/res/android" <org.fdroid.fdroid.views.swap.JoinWifiView
android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent" xmlns:swap="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" swap:toolbarTitle="@string/swap_join_same_wifi"
android:background="@color/swap_blue" android:orientation="vertical"
tools:context=".views.swap.SwapWorkflowActivity"> android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/swap_blue"
tools:context=".views.swap.SwapWorkflowActivity">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -24,7 +27,7 @@
android:id="@+id/wifi_icon" android:id="@+id/wifi_icon"
android:src="@drawable/wifi" android:src="@drawable/wifi"
android:layout_below="@+id/text_description" android:layout_below="@+id/text_description"
android:layout_centerHorizontal="true" /> android:layout_centerHorizontal="true"/>
<!-- <!--
<Button style="@style/SwapTheme.Wizard.OptionButton" <Button style="@style/SwapTheme.Wizard.OptionButton"
@ -40,7 +43,7 @@
android:id="@+id/wifi_ssid" android:id="@+id/wifi_ssid"
style="@style/SwapTheme.Wizard.WifiSSID" style="@style/SwapTheme.Wizard.WifiSSID"
android:layout_below="@id/wifi_icon" android:layout_below="@id/wifi_icon"
android:layout_centerHorizontal="true" /> android:layout_centerHorizontal="true"/>
<!--android:layout_above="@id/wifi_available_networks_prompt"--> <!--android:layout_above="@id/wifi_available_networks_prompt"-->
<TextView <TextView

View File

@ -1,11 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.fdroid.fdroid.views.swap.NfcView xmlns:android="http://schemas.android.com/apk/res/android" <org.fdroid.fdroid.views.swap.NfcView
android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" xmlns:swap="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent" swap:toolbarTitle="@string/swap_nfc_title"
android:background="@color/swap_blue" android:orientation="vertical"
android:paddingTop="38.8dp"> <!-- 69px * 96dpi / 160dpi --> android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/swap_blue"
android:paddingTop="38.8dp"> <!-- 69px * 96dpi / 160dpi -->
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -21,7 +24,7 @@
style="@style/SwapTheme.Wizard.MainText" style="@style/SwapTheme.Wizard.MainText"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/icon_nfc" /> android:layout_below="@id/icon_nfc"/>
<CheckBox <CheckBox
android:id="@+id/checkbox_dont_show" android:id="@+id/checkbox_dont_show"

View File

@ -1,45 +1,45 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
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="?attr/listPreferredItemHeight" android:layout_height="?attr/listPreferredItemHeight"
android:orientation="horizontal" android:orientation="horizontal"
android:minHeight="?attr/listPreferredItemHeight" android:minHeight="?attr/listPreferredItemHeight"
android:paddingBottom="4dip" android:paddingBottom="4dip"
android:paddingTop="4dip"> android:paddingTop="4dip">
<RelativeLayout <RelativeLayout
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft" android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart" android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:layout_gravity="center_vertical"> android:layout_gravity="center_vertical">
<ImageView <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:src="@drawable/circle" android:src="@drawable/circle"
android:tint="@color/swap_light_grey_icon"/> android:tint="@color/swap_light_grey_icon"/>
<ImageView <ImageView
android:id="@+id/icon" android:id="@+id/icon"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:layout_centerInParent="true" android:layout_centerInParent="true"
tools:src="@drawable/ic_bluetooth_white" /> tools:src="@drawable/ic_bluetooth_white"/>
</RelativeLayout> </RelativeLayout>
<TextView <TextView
android:id="@+id/peer_name" android:id="@+id/peer_name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft" android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart" android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
android:textSize="20sp" android:textSize="20sp"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
tools:text="Nexus 4" /> tools:text="Nexus 4"/>
</LinearLayout> </LinearLayout>

View File

@ -2,8 +2,17 @@
<org.fdroid.fdroid.views.swap.SelectAppsView <org.fdroid.fdroid.views.swap.SelectAppsView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" xmlns:swap="http://schemas.android.com/apk/res-auto"
swap:toolbarColor="@color/swap_bright_blue"
swap:toolbarTitle="@string/swap_choose_apps"
android:id="@+id/select_apps"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</org.fdroid.fdroid.views.swap.SelectAppsView> </org.fdroid.fdroid.views.swap.SelectAppsView>

View File

@ -3,10 +3,13 @@
<org.fdroid.fdroid.views.swap.SendFDroidView <org.fdroid.fdroid.views.swap.SendFDroidView
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:swap="http://schemas.android.com/apk/res-auto"
swap:toolbarTitle="@string/swap_send_fdroid"
android:background="@color/swap_blue" android:background="@color/swap_blue"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_width="wrap_content"> android:layout_width="wrap_content">
<ScrollView android:layout_width="match_parent" android:layout_height="match_parent">
<LinearLayout android:orientation="vertical" <LinearLayout android:orientation="vertical"
android:gravity="center" android:gravity="center"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -46,5 +49,5 @@
style="@style/SwapTheme.Wizard.QRScanWarningText"/> style="@style/SwapTheme.Wizard.QRScanWarningText"/>
</LinearLayout> </LinearLayout>
</ScrollView>
</org.fdroid.fdroid.views.swap.SendFDroidView> </org.fdroid.fdroid.views.swap.SendFDroidView>

View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- TODO: Add paddingStart in places where there is only paddingLeft. However Android Studio lint
gives an error, which is discussed here:
http://stackoverflow.com/questions/27449776/conflicting-lint-messages-regarding-paddingstart-usage?lq=1
-->
<org.fdroid.fdroid.views.swap.StartSwapView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:swap="http://schemas.android.com/apk/res-auto"
swap:toolbarColor="@color/swap_bright_blue"
swap:toolbarTitle="@string/swap_nearby"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".views.swap.SwapWorkflowActivity">
<!-- Misc header -->
<include layout="@layout/start_swap_header"/>
<!-- Bluetooth swap status + toggle -->
<LinearLayout
android:id="@+id/bluetooth_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/header"
android:padding="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:tint="@color/swap_grey_icon"
android:src="@drawable/ic_bluetooth_white"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="15dp"
android:paddingStart="15dp"
android:layout_weight="1.00"
tools:ignore="RtlSymmetry">
<TextView
android:id="@+id/bluetooth_visible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="@string/swap_visible_bluetooth"
android:textSize="18sp"/>
<TextView
android:id="@+id/device_id_bluetooth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="SP-120"
android:textColor="@color/swap_light_text"/>
</LinearLayout>
<android.support.v7.widget.SwitchCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:id="@+id/switch_bluetooth"/>
</LinearLayout>
<!-- WiFi swap status + toggle -->
<LinearLayout
android:id="@+id/wifi_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/bluetooth_info"
android:padding="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:tint="@color/swap_grey_icon"
android:src="@drawable/ic_network_wifi_white"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="15dp"
android:paddingStart="15dp"
android:layout_weight="1.00"
tools:ignore="RtlSymmetry">
<TextView
android:id="@+id/wifi_visible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="@string/swap_not_visible_wifi"
android:textSize="18sp"/>
<TextView
android:id="@+id/device_id_wifi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/swap_wifi_device_name"
android:textColor="@color/swap_light_text"/>
<TextView
android:id="@+id/wifi_network"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="wifi network name"
android:textColor="@color/swap_bright_blue"
android:textSize="16sp"/>
</LinearLayout>
<android.support.v7.widget.SwitchCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:id="@+id/switch_wifi"/>
</LinearLayout>
<!-- Feedback for "searching for nearby people..." -->
<LinearLayout
android:id="@+id/feedback_searching"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/wifi_info"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:paddingBottom="5dp"
android:paddingTop="20dp">
<TextView
android:id="@+id/text_people_nearby"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/swap_people_nearby"
android:textColor="@color/swap_light_text"
android:layout_weight="1.00"/>
<ProgressBar
android:id="@+id/searching_people_nearby"
android:layout_width="24dp"
android:layout_height="24dp"
android:indeterminate="true"/>
</LinearLayout>
<!-- Buttons to help the user when they can't find any peers. Shown at bottom of relative layout -->
<LinearLayout
android:id="@+id/cant_find_peers"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<Button
android:id="@+id/btn_send_fdroid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_fdroid_grey"
android:drawableStart="@drawable/ic_fdroid_grey"
android:text="@string/swap_send_fdroid"
android:drawablePadding="10dp"
android:paddingLeft="25dp"
android:paddingRight="25dp"
android:paddingEnd="25dp"
android:background="@android:color/transparent"/>
<Button
android:id="@+id/btn_qr_scanner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_qr_grey"
android:drawableStart="@drawable/ic_qr_grey"
android:text="@string/swap_scan_qr"
android:drawablePadding="10dp"
android:paddingLeft="25dp"
android:paddingRight="25dp"
android:paddingEnd="25dp"
android:background="@android:color/transparent"/>
</LinearLayout>
<!-- Heading for "can't find peers" -->
<TextView
android:id="@+id/header_cant_find_peers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/cant_find_peers"
android:text="@string/swap_cant_find_peers"
android:paddingLeft="20dp"
android:paddingStart="20dp"
android:paddingRight="20dp"
android:paddingEnd="20dp"
android:paddingTop="20dp"
android:textColor="@color/swap_light_text"/>
<!-- List of all currently known peers (i.e. bluetooth and wifi devices that have been identified -->
<ListView
android:id="@+id/list_people_nearby"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/feedback_searching"
android:layout_above="@id/header_cant_find_peers">
</ListView>
</org.fdroid.fdroid.views.swap.StartSwapView>

View File

@ -1,9 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.fdroid.fdroid.views.swap.SwapAppsView <org.fdroid.fdroid.views.swap.SwapSuccessView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" xmlns:swap="http://schemas.android.com/apk/res-auto"
swap:toolbarColor="@color/swap_bright_blue"
swap:toolbarTitle="@string/swap_success"
android:id="@+id/swap_success"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
</org.fdroid.fdroid.views.swap.SwapAppsView> <ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</org.fdroid.fdroid.views.swap.SwapSuccessView>

View File

@ -1,12 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.fdroid.fdroid.views.swap.WifiQrView <org.fdroid.fdroid.views.swap.WifiQrView
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/swap_blue" xmlns:swap="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent" swap:toolbarTitle="@string/swap_scan_qr"
android:layout_width="wrap_content"> android:background="@color/swap_blue"
android:layout_height="match_parent"
android:layout_width="wrap_content">
<ScrollView android:layout_width="match_parent" android:layout_height="match_parent">
<LinearLayout android:orientation="vertical" <LinearLayout android:orientation="vertical"
android:gravity="center" android:gravity="center"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -20,10 +23,10 @@
tools:src="@drawable/swap_qr_example"/> tools:src="@drawable/swap_qr_example"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/swap_scan_or_type_url" android:text="@string/swap_scan_or_type_url"
style="@style/SwapTheme.Wizard.MainText"/> style="@style/SwapTheme.Wizard.MainText"/>
<!-- <!--
<Button style="@style/SwapTheme.Wizard.OptionButton" <Button style="@style/SwapTheme.Wizard.OptionButton"
@ -45,13 +48,13 @@
android:id="@+id/btn_qr_scanner"/> android:id="@+id/btn_qr_scanner"/>
<TextView <TextView
android:id="@+id/warning_qr_scanner" android:id="@+id/warning_qr_scanner"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/warning_scaning_qr_code" android:text="@string/warning_scaning_qr_code"
android:visibility="gone" android:visibility="gone"
style="@style/SwapTheme.Wizard.QRScanWarningText"/> style="@style/SwapTheme.Wizard.QRScanWarningText"/>
</LinearLayout> </LinearLayout>
</ScrollView>
</org.fdroid.fdroid.views.swap.WifiQrView> </org.fdroid.fdroid.views.swap.WifiQrView>

View File

@ -1,12 +0,0 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_next"
android:icon="@drawable/ic_arrow_forward_white"
android:title="@string/skip"
android:titleCondensed="@string/skip"/>
<!-- Currently in a style, but that style probably wont work on 8 -> 11 devices -->
<!--android:drawable="@drawable/swap_action_button_skin"-->
</menu>

View File

@ -3,4 +3,8 @@
<integer name="unhidePin">1337</integer> <integer name="unhidePin">1337</integer>
<declare-styleable name="SwapView">
<attr name="toolbarColor" format="color"/>
<attr name="toolbarTitle" format="string"/>
</declare-styleable>
</resources> </resources>