Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-jig the welcome modal shown to 1st time users #2507

Merged
merged 1 commit into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/androidTest/java/de/blau/android/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ public static void grantPermissons(@NonNull UiDevice device) {
* @param ctx Android context
*/
public static void dismissStartUpDialogs(@NonNull UiDevice device, @NonNull Context ctx) {
clickText(device, true, ctx.getResources().getString(R.string.okay), false, false);
if (findText(device, false, ctx.getResources().getString(R.string.welcome_title))) {
clickText(device, true, ctx.getResources().getString(R.string.next), true, false);
clickResource(device, false, device.getCurrentPackageName() + ":id/authorize", false);
clickText(device, true, ctx.getResources().getString(R.string.welcome_start), true, false);
}
}

/**
Expand Down
171 changes: 149 additions & 22 deletions src/main/java/de/blau/android/dialogs/Newbie.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,59 @@
package de.blau.android.dialogs;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AlertDialog.Builder;
import androidx.appcompat.app.AppCompatDialog;
import androidx.appcompat.widget.SwitchCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.preference.PreferenceManager;
import de.blau.android.App;
import de.blau.android.Authorize;
import de.blau.android.HelpViewer;
import de.blau.android.Main;
import de.blau.android.R;
import de.blau.android.osm.ViewBox;
import de.blau.android.prefs.AdvancedPrefDatabase;
import de.blau.android.prefs.Preferences;
import de.blau.android.resources.DataStyle;
import de.blau.android.resources.TileLayerSource;
import de.blau.android.resources.TileLayerSource.Category;
import de.blau.android.resources.TileLayerSource.TileType;
import de.blau.android.util.ImmersiveDialogFragment;
import de.blau.android.util.OnPageSelectedListener;
import de.blau.android.util.ThemeUtils;
import de.blau.android.util.Util;
import de.blau.android.views.ExtendedViewPager;
import de.blau.android.views.layers.MapTilesLayer;

/**
* Display a dialog giving new users minimal instructions
*
*/
public class Newbie extends ImmersiveDialogFragment {

private static final String DEBUG_TAG = Newbie.class.getSimpleName();

private static final String TAG = "fragment_newbie";

private Main main;
private static final String PAGER_POS_KEY = "pagerPos";
private static final String AUTHORIZE_KEY = "authorize";
private static final String PEN_SETUP_KEY = "penSetup";
private static final String AUTO_DOWNLOAD_KEY = "autoDownload";
private static final String USE_IMAGERY_KEY = "useImagery";

private static final int SETTINGS_PAGE_INDEX = 1;
private static final int WELCOME_PAGE_INDEX = 0;

/**
* Display a dialog giving new users minimal instructions
Expand Down Expand Up @@ -71,37 +99,136 @@ public void onAttach(Context context) {
if (!(context instanceof Main)) {
throw new ClassCastException(context.toString() + " can only be called from Main");
}
main = (Main) context;
}

@NonNull
@Override
public AppCompatDialog onCreateDialog(Bundle savedInstanceState) {
Builder builder = new AlertDialog.Builder(getActivity());
final FragmentActivity activity = getActivity();
if (!(activity instanceof Main)) {
throw new ClassCastException(activity.toString() + " can only be called from Main");
}
Builder builder = new AlertDialog.Builder(activity);
builder.setIcon(null);
builder.setTitle(R.string.welcome_title);
final LayoutInflater inflater = ThemeUtils.getLayoutInflater(activity);
final View layout = inflater.inflate(R.layout.welcome_tabs, null);
final SwitchCompat displayImagery = layout.findViewById(R.id.use_imagery);
final SwitchCompat autoDownload = layout.findViewById(R.id.auto_download);
final SwitchCompat penSetup = layout.findViewById(R.id.pen_setup);
final SwitchCompat authorize = layout.findViewById(R.id.authorize);
final ExtendedViewPager pager = (ExtendedViewPager) layout.findViewById(R.id.pager);
pager.setAdapter(new ViewPagerAdapter(activity, layout, new int[] { R.id.welcome_page, R.id.settings_page },
new int[] { R.string.confirm_upload_edits_page, R.string.menu_tags }));
// set saved state before the on page change listener is set
if (savedInstanceState != null) {
displayImagery.setChecked(savedInstanceState.getBoolean(USE_IMAGERY_KEY));
autoDownload.setChecked(savedInstanceState.getBoolean(AUTO_DOWNLOAD_KEY));
penSetup.setChecked(savedInstanceState.getBoolean(PEN_SETUP_KEY));
authorize.setChecked(savedInstanceState.getBoolean(AUTHORIZE_KEY, true));
pager.setCurrentItem(savedInstanceState.getInt(PAGER_POS_KEY, 0));
}
pager.addOnPageChangeListener((OnPageSelectedListener) position -> {
AlertDialog dialog = ((AlertDialog) getDialog());
if (dialog == null) {
Log.e(DEBUG_TAG, "Dialog null");
return;
}
Button positive = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
Button negative = dialog.getButton(DialogInterface.BUTTON_NEGATIVE);
positive.clearFocus();
if (position == WELCOME_PAGE_INDEX) {
positive.setText(R.string.next);
positive.setOnClickListener((View v) -> pager.setCurrentItem(SETTINGS_PAGE_INDEX));
negative.setText(R.string.skip);
negative.setOnClickListener((View v) -> getDialog().dismiss());
}
if (position == SETTINGS_PAGE_INDEX) {
positive.setText(R.string.welcome_start);
positive.setOnClickListener((View v) -> {
((Main) activity).gotoCurrentLocation();
((Main) activity).setFollowGPS(true);

Preferences prefs = App.getPreferences(activity);
if (displayImagery.isChecked()) {
setBestBackground(activity);
}

prefs.setPanAndZoomAutoDownload(autoDownload.isChecked());

boolean penConfig = penSetup.isChecked();
prefs.setLargeDragArea(!penConfig);
prefs.setWayNodeDragging(penConfig);
prefs.setDataStyle(penConfig ? Preferences.DEFAULT_PEN_MAP_STYLE : Preferences.DEFAULT_MAP_STYLE);

((Main) activity).getMap().setPrefs(activity, prefs);

Newbie.dismissDialog(activity);

if (authorize.isChecked()) {
Authorize.startForResult(activity, null);
}
});
negative.setText(R.string.back);
negative.setOnClickListener((View v) -> pager.setCurrentItem(0));
}
});

String message = getString(R.string.welcome_message);
if (main.isFullScreen()) {
if (((Main) activity).isFullScreen()) {
message = message + getString(R.string.welcome_message_fullscreen);
}
builder.setMessage(Util.fromHtml(message));
builder.setPositiveButton(R.string.okay, (dialog, which) -> {
FragmentActivity activity = getActivity();
if (activity instanceof Main) {
main.gotoCurrentLocation();
main.setFollowGPS(true);
} else {
Log.e(DEBUG_TAG, "getActivity returned null in onClick");
}
((TextView) layout.findViewById(R.id.welcome_message)).setText(Util.fromHtml(message));
builder.setView(layout);

builder.setNegativeButton(R.string.skip, null);
builder.setPositiveButton(R.string.next, null);
builder.setNeutralButton(R.string.read_introduction, null);
AlertDialog dialog = builder.create();
dialog.setOnShowListener((DialogInterface d) -> {
Button neutral = dialog.getButton(DialogInterface.BUTTON_NEUTRAL);
neutral.setOnClickListener((View v) -> {
Context ctx = getActivity();
if (ctx instanceof FragmentActivity) {
HelpViewer.start((FragmentActivity) ctx, R.string.help_introduction);
return;
}
Log.e(DEBUG_TAG, "Not a fragment activity");
});
Button positive = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
positive.setOnClickListener((View v) -> pager.setCurrentItem(SETTINGS_PAGE_INDEX));
});
builder.setNeutralButton(R.string.read_introduction, (dialog, which) -> {
FragmentActivity activity = getActivity();
if (activity != null) {
HelpViewer.start(activity, R.string.help_introduction);
} else {
Log.e(DEBUG_TAG, "getActivity returned null in onClick");
return dialog;
}

/**
* Set the best background for the current ViewBox
*
* @param activity the current activity
*/
private void setBestBackground(@NonNull final FragmentActivity activity) {
final String[] ids = TileLayerSource.getIds(App.getLogic().getMap().getViewBox(), true, Category.photo, null);
if (ids.length > 0) {
TileLayerSource tileSource = TileLayerSource.get(activity, ids[0], false);
MapTilesLayer<?> tileLayer = ((Main) activity).getMap().getBackgroundLayer();
tileLayer.setRendererInfo(tileSource);
try (AdvancedPrefDatabase db = new AdvancedPrefDatabase(activity)) {
db.setLayerContentId(tileLayer.getIndex(), tileSource.getId());
}
});
return builder.create();
} else {
Log.w(DEBUG_TAG, "No applicable imagery found!");
}
}

@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(DEBUG_TAG, "onSaveInstanceState");
Dialog dialog = getDialog();
outState.putBoolean(USE_IMAGERY_KEY, ((SwitchCompat) dialog.findViewById(R.id.use_imagery)).isChecked());
outState.putBoolean(AUTO_DOWNLOAD_KEY, ((SwitchCompat) dialog.findViewById(R.id.auto_download)).isChecked());
outState.putBoolean(PEN_SETUP_KEY, ((SwitchCompat) dialog.findViewById(R.id.pen_setup)).isChecked());
outState.putBoolean(AUTHORIZE_KEY, ((SwitchCompat) dialog.findViewById(R.id.authorize)).isChecked());
outState.putInt(PAGER_POS_KEY, ((ExtendedViewPager) dialog.findViewById(R.id.pager)).getCurrentItem());
}
}
29 changes: 25 additions & 4 deletions src/main/java/de/blau/android/prefs/Preferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class Preferences {
private final boolean isAntiAliasingEnabled;
private final boolean isKeepScreenOnEnabled;
private final boolean useBackForUndo;
private final boolean largeDragArea;
private boolean largeDragArea;
private final boolean tagFormEnabled;
private String scaleLayer;
private String mapProfile;
Expand Down Expand Up @@ -122,7 +122,7 @@ public class Preferences {
private final int maxOffsetDistance;
private final Set<String> enabledValidations;
private final int autoNameCap;
private final boolean wayNodeDragging;
private boolean wayNodeDragging;
private final boolean splitWindowForPropertyEditor;
private final boolean useImperialUnits;
private final boolean supportPresetLabels;
Expand All @@ -140,7 +140,8 @@ public class Preferences {
private final double maxCircleSegment;
private final double minCircleSegment;

private static final String DEFAULT_MAP_PROFILE = "Color Round Nodes";
public static final String DEFAULT_MAP_STYLE = "Color Round Nodes";
public static final String DEFAULT_PEN_MAP_STYLE = "Pen Round Nodes";

private final SharedPreferences prefs;

Expand Down Expand Up @@ -434,6 +435,16 @@ public boolean largeDragArea() {
return largeDragArea;
}

/**
* Enable or disable the large drag area
*
* @param enabled if true enable the large drag area
*/
public void setLargeDragArea(boolean enabled) {
largeDragArea = enabled;
prefs.edit().putBoolean(r.getString(R.string.config_largeDragArea_key), enabled).commit();
}

/**
* Get kind of scale that should be displayed
*
Expand Down Expand Up @@ -463,7 +474,7 @@ public String getDataStyle() {
// check if we actually still have the profile
if (DataStyle.getStyle(mapProfile) == null) {
Log.w(DEBUG_TAG, "Style " + mapProfile + " missing, replacing by default");
setDataStyle(DataStyle.getStyle(DEFAULT_MAP_PROFILE) == null ? DataStyle.getBuiltinStyleName() : DEFAULT_MAP_PROFILE);
setDataStyle(DataStyle.getStyle(DEFAULT_MAP_STYLE) == null ? DataStyle.getBuiltinStyleName() : DEFAULT_MAP_STYLE);
}
return mapProfile;
}
Expand Down Expand Up @@ -1674,6 +1685,16 @@ public boolean isWayNodeDraggingEnabled() {
return wayNodeDragging;
}

/**
* Enable or disable the way node dragging
*
* @param enabled if true enable way node dragging
*/
public void setWayNodeDragging(boolean enabled) {
wayNodeDragging = enabled;
prefs.edit().putBoolean(r.getString(R.string.config_wayNodeDragging_key), enabled).commit();
}

/**
* Check if we should try to use split window functionality for the PropertyEditor
*
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/de/blau/android/util/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ public void handleTag(boolean opening, String tag, Editable output, XMLReader xm
output.append("\n");
}
if ("li".equals(tag) && opening) {
output.append("\n\t");
output.append("\n\t<b>&bull;</b>");
}
}
}
Expand Down
Loading
Loading