Location control set changes

* Replace 'more' icon with notification indicator
* Move 'call' and 'view website' to main location dialog
pull/795/head
Alex Baker 7 years ago
parent fbcd321f8e
commit 072d2a378f

@ -1,18 +0,0 @@
package org.tasks.location;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import org.tasks.data.Location;
import org.tasks.preferences.Preferences;
public class PlacePicker {
public static Intent getIntent(Activity activity) {
return null;
}
public static Location getPlace(Context context, Intent data, Preferences preferences) {
return null;
}
}

@ -7,7 +7,6 @@ import io.reactivex.disposables.Disposable;
import io.reactivex.disposables.Disposables; import io.reactivex.disposables.Disposables;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.drive.DriveLoginActivity; import org.tasks.drive.DriveLoginActivity;
import org.tasks.location.LocationPickerActivity;
import org.tasks.play.AuthResultHandler; import org.tasks.play.AuthResultHandler;
public class PlayServices { public class PlayServices {
@ -38,8 +37,4 @@ public class PlayServices {
public Disposable check(MainActivity mainActivity) { public Disposable check(MainActivity mainActivity) {
return Disposables.empty(); return Disposables.empty();
} }
public Disposable checkMaps(LocationPickerActivity locationPickerActivity) {
return Disposables.empty();
}
} }

@ -17,7 +17,6 @@ import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity;
import io.reactivex.Single; import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.internal.disposables.EmptyDisposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import java.io.IOException; import java.io.IOException;
import javax.inject.Inject; import javax.inject.Inject;
@ -71,21 +70,6 @@ public class PlayServices {
}); });
} }
public Disposable checkMaps(Activity activity) {
if (preferences.useGooglePlaces() || preferences.useGoogleMaps()) {
return Single.fromCallable(this::refreshAndCheck)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(success -> {
if (!success) {
resolve(activity);
}
});
} else {
return EmptyDisposable.INSTANCE;
}
}
public boolean refreshAndCheck() { public boolean refreshAndCheck() {
refresh(); refresh();
return isPlayServicesAvailable(); return isPlayServicesAvailable();

@ -11,6 +11,7 @@ import com.google.common.base.Strings;
import com.todoroo.astrid.helper.UUIDHelper; import com.todoroo.astrid.helper.UUIDHelper;
import java.io.Serializable; import java.io.Serializable;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.tasks.location.MapPosition;
@Entity(tableName = "places") @Entity(tableName = "places")
public class Place implements Serializable, Parcelable { public class Place implements Serializable, Parcelable {
@ -56,12 +57,6 @@ public class Place implements Serializable, Parcelable {
@ColumnInfo(name = "longitude") @ColumnInfo(name = "longitude")
private double longitude; private double longitude;
public static Place newPlace() {
Place place = new Place();
place.setUid(UUIDHelper.newUUID());
return place;
}
public Place() {} public Place() {}
@Ignore @Ignore
@ -88,6 +83,12 @@ public class Place implements Serializable, Parcelable {
longitude = parcel.readDouble(); longitude = parcel.readDouble();
} }
public static Place newPlace() {
Place place = new Place();
place.setUid(UUIDHelper.newUUID());
return place;
}
public long getId() { public long getId() {
return id; return id;
} }
@ -152,18 +153,6 @@ public class Place implements Serializable, Parcelable {
this.url = url; this.url = url;
} }
public void apply(Place place) {
if (Strings.isNullOrEmpty(address)) {
address = place.address;
}
if (Strings.isNullOrEmpty(phone)) {
phone = place.phone;
}
if (Strings.isNullOrEmpty(url)) {
url = place.url;
}
}
public String getDisplayName() { public String getDisplayName() {
if (Strings.isNullOrEmpty(address)) { if (Strings.isNullOrEmpty(address)) {
return name; return name;
@ -177,12 +166,16 @@ public class Place implements Serializable, Parcelable {
return name; return name;
} }
public String getGeoUri() { String getGeoUri() {
return String.format( return String.format(
"geo:%s,%s?q=%s", "geo:%s,%s?q=%s",
latitude, longitude, Uri.encode(Strings.isNullOrEmpty(address) ? name : address)); latitude, longitude, Uri.encode(Strings.isNullOrEmpty(address) ? name : address));
} }
public MapPosition getMapPosition() {
return new MapPosition(latitude, longitude);
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) { if (this == o) {

@ -8,7 +8,6 @@ import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcelable; import android.os.Parcelable;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -21,9 +20,9 @@ import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnCheckedChanged; import butterknife.OnCheckedChanged;
import butterknife.OnClick; import butterknife.OnClick;
import com.google.common.base.Strings;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.data.Geofence;
import org.tasks.data.Location; import org.tasks.data.Location;
import org.tasks.injection.DialogFragmentComponent; import org.tasks.injection.DialogFragmentComponent;
import org.tasks.injection.ForActivity; import org.tasks.injection.ForActivity;
@ -36,8 +35,8 @@ import org.tasks.ui.Toaster;
public class LocationDialog extends InjectingDialogFragment { public class LocationDialog extends InjectingDialogFragment {
public static final String EXTRA_LOCATION = "extra_location"; public static final String EXTRA_GEOFENCE = "extra_geofence";
public static final String EXTRA_ORIGINAL = "extra_original"; private static final String EXTRA_ORIGINAL = "extra_original";
private static final String FRAG_TAG_SEEKBAR = "frag_tag_seekbar"; private static final String FRAG_TAG_SEEKBAR = "frag_tag_seekbar";
private static final int REQUEST_RADIUS = 10101; private static final int REQUEST_RADIUS = 10101;
@ -55,12 +54,6 @@ public class LocationDialog extends InjectingDialogFragment {
@BindView(R.id.location_departure) @BindView(R.id.location_departure)
Switch departureView; Switch departureView;
@BindView(R.id.location_call)
TextView callView;
@BindView(R.id.location_url)
TextView urlView;
@BindView(R.id.location_radius_value) @BindView(R.id.location_radius_value)
TextView radiusValue; TextView radiusValue;
@ -82,36 +75,26 @@ public class LocationDialog extends InjectingDialogFragment {
@NonNull @NonNull
@Override @Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Location location = Location original = getArguments().getParcelable(EXTRA_ORIGINAL);
Geofence geofence =
savedInstanceState == null savedInstanceState == null
? getOriginal() ? original.geofence
: savedInstanceState.getParcelable(EXTRA_LOCATION); : savedInstanceState.getParcelable(EXTRA_GEOFENCE);
LayoutInflater layoutInflater = LayoutInflater.from(context); LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.location_details, null); View view = layoutInflater.inflate(R.layout.location_details, null);
ButterKnife.bind(this, view); ButterKnife.bind(this, view);
boolean hasLocationPermission = permissionChecker.canAccessLocation(); boolean hasLocationPermission = permissionChecker.canAccessLocation();
arrivalView.setChecked(hasLocationPermission && location.isArrival()); arrivalView.setChecked(hasLocationPermission && geofence.isArrival());
departureView.setChecked(hasLocationPermission && location.isDeparture()); departureView.setChecked(hasLocationPermission && geofence.isDeparture());
updateRadius(location.getRadius()); updateRadius(geofence.getRadius());
String phone = location.getPhone();
if (!Strings.isNullOrEmpty(phone)) {
callView.setVisibility(View.VISIBLE);
callView.setText(getString(R.string.call_number, phone));
}
String url = location.getUrl();
if (!Strings.isNullOrEmpty(url)) {
urlView.setVisibility(View.VISIBLE);
urlView.setText(getString(R.string.open_url, url));
}
return dialogBuilder return dialogBuilder
.newDialog() .newDialog()
.setTitle(location.getDisplayName()) .setTitle(original.getDisplayName())
.setView(view) .setView(view)
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
.setOnCancelListener(this::sendResult) .setOnCancelListener(this::sendResult)
.setPositiveButton(android.R.string.ok, this::sendResult) .setPositiveButton(android.R.string.ok, this::sendResult)
.setNeutralButton(R.string.delete, this::delete)
.create(); .create();
} }
@ -120,29 +103,17 @@ public class LocationDialog extends InjectingDialogFragment {
sendResult(dialog); sendResult(dialog);
} }
private Location toLocation() { private Geofence toGeofence() {
Location result = getOriginal(); Geofence geofence = new Geofence();
result.setArrival(arrivalView.isChecked()); geofence.setArrival(arrivalView.isChecked());
result.setDeparture(departureView.isChecked()); geofence.setDeparture(departureView.isChecked());
result.setRadius((int) radiusValue.getTag()); geofence.setRadius((int) radiusValue.getTag());
return result; return geofence;
}
private Location getOriginal() {
return getArguments().getParcelable(EXTRA_ORIGINAL);
} }
private void sendResult(DialogInterface d, int... i) { private void sendResult(DialogInterface d, int... i) {
sendResult(toLocation());
}
private void delete(DialogInterface d, int i) {
sendResult(null);
}
private void sendResult(Location result) {
Intent data = new Intent(); Intent data = new Intent();
data.putExtra(EXTRA_LOCATION, (Parcelable) result); data.putExtra(EXTRA_GEOFENCE, (Parcelable) toGeofence());
getTargetFragment().onActivityResult(getTargetRequestCode(), RESULT_OK, data); getTargetFragment().onActivityResult(getTargetRequestCode(), RESULT_OK, data);
dismiss(); dismiss();
} }
@ -151,7 +122,7 @@ public class LocationDialog extends InjectingDialogFragment {
public void onSaveInstanceState(@NonNull Bundle outState) { public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
outState.putParcelable(EXTRA_LOCATION, toLocation()); outState.putParcelable(EXTRA_GEOFENCE, toGeofence());
} }
@Override @Override
@ -191,24 +162,10 @@ public class LocationDialog extends InjectingDialogFragment {
} }
} }
@OnClick(R.id.location_url)
void openUrl() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(getOriginal().getUrl()));
startActivity(intent);
}
@OnClick(R.id.location_call)
void openDialer() {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + getOriginal().getPhone()));
startActivity(intent);
}
@OnClick(R.id.location_radius) @OnClick(R.id.location_radius)
void selectRadius() { void selectRadius() {
SeekBarDialog seekBarDialog = SeekBarDialog seekBarDialog =
newSeekBarDialog(R.layout.dialog_radius_seekbar, 75, 1000, toLocation().getRadius()); newSeekBarDialog(R.layout.dialog_radius_seekbar, 75, 1000, toGeofence().getRadius());
seekBarDialog.setTargetFragment(this, REQUEST_RADIUS); seekBarDialog.setTargetFragment(this, REQUEST_RADIUS);
seekBarDialog.show(getFragmentManager(), FRAG_TAG_SEEKBAR); seekBarDialog.show(getFragmentManager(), FRAG_TAG_SEEKBAR);
} }

@ -55,9 +55,9 @@ import org.tasks.Event;
import org.tasks.R; import org.tasks.R;
import org.tasks.billing.Inventory; import org.tasks.billing.Inventory;
import org.tasks.data.LocationDao; import org.tasks.data.LocationDao;
import org.tasks.data.Place;
import org.tasks.data.PlaceUsage; import org.tasks.data.PlaceUsage;
import org.tasks.dialogs.DialogBuilder; import org.tasks.dialogs.DialogBuilder;
import org.tasks.gtasks.PlayServices;
import org.tasks.injection.ActivityComponent; import org.tasks.injection.ActivityComponent;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.injection.InjectingAppCompatActivity; import org.tasks.injection.InjectingAppCompatActivity;
@ -81,6 +81,7 @@ public class LocationPickerActivity extends InjectingAppCompatActivity
OnPredictionPicked, OnPredictionPicked,
OnActionExpandListener { OnActionExpandListener {
public static final String EXTRA_PLACE = "extra_place";
private static final String EXTRA_MAP_POSITION = "extra_map_position"; private static final String EXTRA_MAP_POSITION = "extra_map_position";
private static final String EXTRA_APPBAR_OFFSET = "extra_appbar_offset"; private static final String EXTRA_APPBAR_OFFSET = "extra_appbar_offset";
private static final Pattern pattern = Pattern.compile("(\\d+):(\\d+):(\\d+\\.\\d+)"); private static final Pattern pattern = Pattern.compile("(\\d+):(\\d+):(\\d+\\.\\d+)");
@ -111,7 +112,6 @@ public class LocationPickerActivity extends InjectingAppCompatActivity
@Inject Theme theme; @Inject Theme theme;
@Inject Toaster toaster; @Inject Toaster toaster;
@Inject Inventory inventory; @Inject Inventory inventory;
@Inject PlayServices playServices;
@Inject LocationDao locationDao; @Inject LocationDao locationDao;
@Inject PlaceSearchProvider searchProvider; @Inject PlaceSearchProvider searchProvider;
@Inject PermissionChecker permissionChecker; @Inject PermissionChecker permissionChecker;
@ -170,7 +170,15 @@ public class LocationPickerActivity extends InjectingAppCompatActivity
searchView.setVisibility(View.GONE); searchView.setVisibility(View.GONE);
} }
if (savedInstanceState != null) { Place currentPlace = getIntent().getParcelableExtra(EXTRA_PLACE);
recentsAdapter.setCurrentPlace(currentPlace);
if (savedInstanceState == null) {
if (currentPlace != null) {
mapPosition = currentPlace.getMapPosition();
}
mapPosition = getIntent().getParcelableExtra(EXTRA_MAP_POSITION);
} else {
mapPosition = savedInstanceState.getParcelable(EXTRA_MAP_POSITION); mapPosition = savedInstanceState.getParcelable(EXTRA_MAP_POSITION);
offset = savedInstanceState.getInt(EXTRA_APPBAR_OFFSET); offset = savedInstanceState.getInt(EXTRA_APPBAR_OFFSET);
viewModel.restoreState(savedInstanceState); viewModel.restoreState(savedInstanceState);
@ -305,7 +313,6 @@ public class LocationPickerActivity extends InjectingAppCompatActivity
@OnClick(R.id.select_this_location) @OnClick(R.id.select_this_location)
void selectLocation() { void selectLocation() {
loadingIndicator.setVisibility(View.VISIBLE); loadingIndicator.setVisibility(View.VISIBLE);
MapPosition mapPosition = map.getMapPosition(); MapPosition mapPosition = map.getMapPosition();
disposables.add( disposables.add(
Single.fromCallable( Single.fromCallable(
@ -361,8 +368,7 @@ public class LocationPickerActivity extends InjectingAppCompatActivity
Location location = result.getLastLocation(); Location location = result.getLastLocation();
if (location != null) { if (location != null) {
map.movePosition( map.movePosition(
new MapPosition(location.getLatitude(), location.getLongitude(), 15f), new MapPosition(location.getLatitude(), location.getLongitude()), animate);
animate);
} }
} }
@ -382,16 +388,13 @@ public class LocationPickerActivity extends InjectingAppCompatActivity
org.tasks.data.Place existing = org.tasks.data.Place existing =
locationDao.findPlace(place.getLatitude(), place.getLongitude()); locationDao.findPlace(place.getLatitude(), place.getLongitude());
if (existing == null) { if (existing == null) {
long placeId = locationDao.insert(place); place.setId(locationDao.insert(place));
place.setId(placeId);
} else { } else {
existing.apply(place);
locationDao.update(existing);
place = existing; place = existing;
} }
} }
hideKeyboard(this); hideKeyboard(this);
setResult(RESULT_OK, new Intent().putExtra(PlacePicker.EXTRA_PLACE, (Parcelable) place)); setResult(RESULT_OK, new Intent().putExtra(EXTRA_PLACE, (Parcelable) place));
finish(); finish();
} }
@ -401,13 +404,12 @@ public class LocationPickerActivity extends InjectingAppCompatActivity
viewModel.observe(this, searchAdapter::submitList, this::returnPlace, this::handleError); viewModel.observe(this, searchAdapter::submitList, this::returnPlace, this::handleError);
disposables = new CompositeDisposable(playServices.checkMaps(this)); disposables =
new CompositeDisposable(
disposables.add( searchSubject
searchSubject .debounce(SEARCH_DEBOUNCE_TIMEOUT, TimeUnit.MILLISECONDS)
.debounce(SEARCH_DEBOUNCE_TIMEOUT, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread()) .subscribe(query -> viewModel.query(query, mapPosition)));
.subscribe(query -> viewModel.query(query, mapPosition)));
} }
private void handleError(Event<String> error) { private void handleError(Event<String> error) {

@ -5,6 +5,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.DiffUtil.ItemCallback; import androidx.recyclerview.widget.DiffUtil.ItemCallback;
import androidx.recyclerview.widget.ListAdapter; import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -17,6 +18,7 @@ import org.tasks.location.LocationPickerAdapter.PlaceViewHolder;
public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHolder> { public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHolder> {
private final OnLocationPicked callback; private final OnLocationPicked callback;
private Place currentPlace;
LocationPickerAdapter(OnLocationPicked callback) { LocationPickerAdapter(OnLocationPicked callback) {
super(new DiffCallback()); super(new DiffCallback());
@ -24,6 +26,10 @@ public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHold
this.callback = callback; this.callback = callback;
} }
void setCurrentPlace(@Nullable Place currentPlace) {
this.currentPlace = currentPlace;
}
@Override @Override
public long getItemId(int position) { public long getItemId(int position) {
return getItem(position).place.getId(); return getItem(position).place.getId();
@ -48,7 +54,7 @@ public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHold
void delete(Place place); void delete(Place place);
} }
public static class PlaceViewHolder extends RecyclerView.ViewHolder { public class PlaceViewHolder extends RecyclerView.ViewHolder {
private final TextView name; private final TextView name;
private final TextView address; private final TextView address;
private final View delete; private final View delete;
@ -64,7 +70,7 @@ public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHold
} }
public void bind(PlaceUsage placeUsage) { public void bind(PlaceUsage placeUsage) {
this.place = placeUsage.place; place = placeUsage.place;
String name = place.getDisplayName(); String name = place.getDisplayName();
String address = place.getAddress(); String address = place.getAddress();
this.name.setText(name); this.name.setText(name);
@ -74,7 +80,7 @@ public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHold
this.address.setText(address); this.address.setText(address);
this.address.setVisibility(View.VISIBLE); this.address.setVisibility(View.VISIBLE);
} }
delete.setVisibility(placeUsage.count > 0 ? View.GONE : View.VISIBLE); delete.setVisibility(placeUsage.count > 0 || place.equals(currentPlace) ? View.GONE : View.VISIBLE);
} }
} }

@ -21,6 +21,10 @@ public class MapPosition implements Parcelable {
private final double longitude; private final double longitude;
private final float zoom; private final float zoom;
public MapPosition(double latitude, double longitude) {
this(latitude, longitude, 15.0f);
}
public MapPosition(double latitude, double longitude, float zoom) { public MapPosition(double latitude, double longitude, float zoom) {
this.latitude = latitude; this.latitude = latitude;
this.longitude = longitude; this.longitude = longitude;

@ -1,33 +0,0 @@
package org.tasks.location;
import android.app.Activity;
import android.content.Intent;
import org.tasks.R;
import org.tasks.data.Geofence;
import org.tasks.data.Location;
import org.tasks.preferences.Preferences;
import timber.log.Timber;
public class PlacePicker {
static final String EXTRA_PLACE = "extra_place";
public static Intent getIntent(Activity activity) {
return new Intent(activity, LocationPickerActivity.class);
}
public static Location getPlace(Intent data, Preferences preferences) {
org.tasks.data.Place result = data.getParcelableExtra(EXTRA_PLACE);
Geofence g = new Geofence();
g.setRadius(preferences.getInt(R.string.p_default_location_radius, 250));
int defaultReminders =
preferences.getIntegerFromString(R.string.p_default_location_reminder_key, 1);
g.setArrival(defaultReminders == 1 || defaultReminders == 3);
g.setDeparture(defaultReminders == 2 || defaultReminders == 3);
Location location = new Location(g, result);
Timber.i("Picked %s", location);
return location;
}
}

@ -1,27 +1,34 @@
package org.tasks.ui; package org.tasks.ui;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.transform;
import static org.tasks.dialogs.LocationDialog.newLocationDialog; import static org.tasks.dialogs.LocationDialog.newLocationDialog;
import static org.tasks.location.LocationPickerActivity.EXTRA_PLACE;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcelable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.Spanned; import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan; import android.text.style.ClickableSpan;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.util.Pair;
import butterknife.BindView; import butterknife.BindView;
import butterknife.OnClick; import butterknife.OnClick;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import org.tasks.R; import org.tasks.R;
import org.tasks.data.Geofence; import org.tasks.data.Geofence;
@ -32,7 +39,7 @@ import org.tasks.dialogs.DialogBuilder;
import org.tasks.dialogs.LocationDialog; import org.tasks.dialogs.LocationDialog;
import org.tasks.injection.FragmentComponent; import org.tasks.injection.FragmentComponent;
import org.tasks.location.GeofenceApi; import org.tasks.location.GeofenceApi;
import org.tasks.location.PlacePicker; import org.tasks.location.LocationPickerActivity;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
public class LocationControlSet extends TaskEditControlFragment { public class LocationControlSet extends TaskEditControlFragment {
@ -56,9 +63,8 @@ public class LocationControlSet extends TaskEditControlFragment {
TextView locationAddress; TextView locationAddress;
@BindView(R.id.location_more) @BindView(R.id.location_more)
View locationOptions; ImageView locationOptions;
private long taskId;
private Location original; private Location original;
private Location location; private Location location;
@ -68,28 +74,85 @@ public class LocationControlSet extends TaskEditControlFragment {
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState); View view = super.onCreateView(inflater, container, savedInstanceState);
taskId = task.getId();
if (savedInstanceState == null) { if (savedInstanceState == null) {
original = locationDao.getGeofences(taskId); if (!task.isNew()) {
location = original; original = locationDao.getGeofences(task.getId());
if (original != null) {
setLocation(new Location(original.geofence, original.place));
}
}
} else { } else {
original = savedInstanceState.getParcelable(EXTRA_ORIGINAL); original = savedInstanceState.getParcelable(EXTRA_ORIGINAL);
location = savedInstanceState.getParcelable(EXTRA_LOCATION); setLocation(savedInstanceState.getParcelable(EXTRA_LOCATION));
} }
updateUI();
return view; return view;
} }
private void setLocation(@Nullable Location location) {
this.location = location;
if (this.location == null) {
locationName.setText("");
locationOptions.setVisibility(View.GONE);
locationAddress.setVisibility(View.GONE);
} else {
locationOptions.setVisibility(View.VISIBLE);
locationOptions.setImageResource(
this.location.isArrival() || this.location.isDeparture()
? R.drawable.ic_outline_notifications_24px
: R.drawable.ic_outline_notifications_off_24px);
String name = this.location.getDisplayName();
String address = this.location.getAddress();
if (!Strings.isNullOrEmpty(address) && !address.equals(name)) {
locationAddress.setText(address);
locationAddress.setVisibility(View.VISIBLE);
} else {
locationAddress.setVisibility(View.GONE);
}
SpannableString spannableString = new SpannableString(name);
spannableString.setSpan(
new ClickableSpan() {
@Override
public void onClick(@NonNull View view) {}
},
0,
name.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
locationName.setText(spannableString);
}
}
@OnClick({R.id.location_name, R.id.location_address}) @OnClick({R.id.location_name, R.id.location_address})
void addAlarm(View view) { void locationClick(View view) {
if (location == null) { if (location == null) {
startActivityForResult(PlacePicker.getIntent(getActivity()), REQUEST_LOCATION_REMINDER); chooseLocation();
} else { } else {
openMap(); List<Pair<Integer, Runnable>> options = new ArrayList<>();
options.add(Pair.create(R.string.open_map, this::openMap));
if (!Strings.isNullOrEmpty(location.getPhone())) {
options.add(Pair.create(R.string.action_call, this::call));
}
if (!Strings.isNullOrEmpty(location.getUrl())) {
options.add(Pair.create(R.string.visit_website, this::openWebsite));
}
options.add(Pair.create(R.string.choose_new_location, this::chooseLocation));
options.add(Pair.create(R.string.delete, () -> setLocation(null)));
dialogBuilder
.newDialog()
.setTitle(location.getDisplayName())
.setItems(
newArrayList(transform(options, o -> getString(o.first))),
(dialog, which) -> options.get(which).second.run())
.show();
}
}
private void chooseLocation() {
Intent intent = new Intent(getActivity(), LocationPickerActivity.class);
if (location != null) {
intent.putExtra(EXTRA_PLACE, (Parcelable) location.place);
} }
startActivityForResult(intent, REQUEST_LOCATION_REMINDER);
} }
@OnClick(R.id.location_more) @OnClick(R.id.location_more)
@ -114,46 +177,34 @@ public class LocationControlSet extends TaskEditControlFragment {
return TAG; return TAG;
} }
private void updateUI() {
if (location == null) {
locationName.setText("");
locationOptions.setVisibility(View.GONE);
locationAddress.setVisibility(View.GONE);
} else {
locationOptions.setVisibility(View.VISIBLE);
String name = location.getDisplayName();
String address = location.getAddress();
if (!Strings.isNullOrEmpty(address) && !address.equals(name)) {
locationAddress.setText(address);
locationAddress.setVisibility(View.VISIBLE);
} else {
locationAddress.setVisibility(View.GONE);
}
SpannableString spannableString = new SpannableString(name);
spannableString.setSpan(
new ClickableSpan() {
@Override
public void onClick(@NonNull View view) {
openMap();
}
},
0,
name.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
locationName.setText(spannableString);
locationName.setMovementMethod(LinkMovementMethod.getInstance());
}
}
private void openMap() { private void openMap() {
Intent intent = new Intent(Intent.ACTION_VIEW); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(location.getGeoUri())); intent.setData(Uri.parse(location.getGeoUri()));
startActivity(intent); startActivity(intent);
} }
private void openWebsite() {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(location.getUrl())));
}
private void call() {
startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + location.getPhone())));
}
@Override @Override
public boolean hasChanges(Task task) { public boolean hasChanges(Task task) {
return original == null ? location == null : !original.equals(location); if (original == null) {
return location != null;
}
if (location == null) {
return true;
}
if (!original.place.equals(location.place)) {
return true;
}
return original.isDeparture() != location.isDeparture()
|| original.isArrival() != location.isArrival()
|| original.getRadius() != location.getRadius();
} }
@Override @Override
@ -165,7 +216,7 @@ public class LocationControlSet extends TaskEditControlFragment {
if (location != null) { if (location != null) {
Place place = location.place; Place place = location.place;
Geofence geofence = location.geofence; Geofence geofence = location.geofence;
geofence.setTask(taskId); geofence.setTask(task.getId());
geofence.setPlace(place.getUid()); geofence.setPlace(place.getUid());
geofence.setId(locationDao.insert(geofence)); geofence.setId(locationDao.insert(geofence));
geofenceApi.register(Collections.singletonList(location)); geofenceApi.register(Collections.singletonList(location));
@ -185,13 +236,26 @@ public class LocationControlSet extends TaskEditControlFragment {
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_LOCATION_REMINDER) { if (requestCode == REQUEST_LOCATION_REMINDER) {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
location = PlacePicker.getPlace(data, preferences); Place place = data.getParcelableExtra(EXTRA_PLACE);
updateUI(); Geofence geofence = new Geofence();
if (location == null) {
geofence.setRadius(preferences.getInt(R.string.p_default_location_radius, 250));
int defaultReminders =
preferences.getIntegerFromString(R.string.p_default_location_reminder_key, 1);
geofence.setArrival(defaultReminders == 1 || defaultReminders == 3);
geofence.setDeparture(defaultReminders == 2 || defaultReminders == 3);
} else {
Geofence existing = location.geofence;
geofence.setArrival(existing.isArrival());
geofence.setDeparture(existing.isDeparture());
geofence.setRadius(existing.getRadius());
}
setLocation(new Location(geofence, place));
} }
} else if (requestCode == REQUEST_LOCATION_DETAILS) { } else if (requestCode == REQUEST_LOCATION_DETAILS) {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
location = data.getParcelableExtra(LocationDialog.EXTRA_LOCATION); location.geofence = data.getParcelableExtra(LocationDialog.EXTRA_GEOFENCE);
updateUI(); setLocation(location);
} }
} else { } else {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);

@ -1,5 +0,0 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
</vector>

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zM12,6.5c2.49,0 4,2.02 4,4.5v0.1l2,2L18,11c0,-3.07 -1.63,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68c-0.24,0.06 -0.47,0.15 -0.69,0.23l1.64,1.64c0.18,-0.02 0.36,-0.05 0.55,-0.05zM5.41,3.35L4,4.76l2.81,2.81C6.29,8.57 6,9.74 6,11v5l-2,2v1h14.24l1.74,1.74 1.41,-1.41L5.41,3.35zM16,17L8,17v-6c0,-0.68 0.12,-1.32 0.34,-1.9L16,16.76L16,17z"/>
</vector>

@ -8,37 +8,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView
android:id="@+id/location_call"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:paddingStart="@dimen/keyline_second"
android:paddingEnd="@dimen/keyline_first"
android:paddingLeft="@dimen/keyline_second"
android:paddingRight="@dimen/keyline_first"
android:background="?attr/selectableItemBackground"
android:gravity="center_vertical"
android:text="Call"
android:textAppearance="?attr/textAppearanceListItemSmall"
android:visibility="gone"
tools:ignore="HardcodedText"/>
<TextView
android:id="@+id/location_url"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:paddingStart="@dimen/keyline_second"
android:paddingEnd="@dimen/keyline_first"
android:paddingLeft="@dimen/keyline_second"
android:paddingRight="@dimen/keyline_first"
android:background="?attr/selectableItemBackground"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="2"
android:singleLine="false"
android:text="Open"
android:textAppearance="?attr/textAppearanceListItem"
android:visibility="gone"
tools:ignore="HardcodedText"/>
<Switch <Switch
android:id="@+id/location_arrival" android:id="@+id/location_arrival"
android:layout_width="match_parent" android:layout_width="match_parent"

@ -15,7 +15,8 @@
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:src="@drawable/ic_outline_more_vert_24px" android:src="@drawable/ic_outline_notifications_off_24px"
android:visibility="gone"
android:tint="?attr/icon_tint"/> android:tint="?attr/icon_tint"/>
<TextView <TextView

@ -868,12 +868,11 @@ File %1$s contained %2$s.\n\n
<string name="show_list_indicators">Show list chips</string> <string name="show_list_indicators">Show list chips</string>
<string name="location_remind_arrival">Remind on arrival</string> <string name="location_remind_arrival">Remind on arrival</string>
<string name="location_remind_departure">Remind on departure</string> <string name="location_remind_departure">Remind on departure</string>
<string name="call_number">Call %s</string> <string name="visit_website">Visit website</string>
<string name="open_url">Open %s</string>
<string name="location_arrived">Arrived at %s</string> <string name="location_arrived">Arrived at %s</string>
<string name="location_departed">Departed %s</string> <string name="location_departed">Departed %s</string>
<string name="building_notifications">Generating notifications</string> <string name="building_notifications">Generating notifications</string>
<string name="choose_a_location">Choose a recent location</string> <string name="choose_a_location">Choose a location</string>
<string name="pick_this_location">Select this location</string> <string name="pick_this_location">Select this location</string>
<string name="or_choose_a_location">Or choose a location</string> <string name="or_choose_a_location">Or choose a location</string>
<string name="map_provider">Map provider</string> <string name="map_provider">Map provider</string>
@ -883,4 +882,6 @@ File %1$s contained %2$s.\n\n
<string name="missing_permissions">Missing permissions</string> <string name="missing_permissions">Missing permissions</string>
<string name="location_permission_required_geofence">Location permissions are needed for location reminders</string> <string name="location_permission_required_geofence">Location permissions are needed for location reminders</string>
<string name="location_permission_required_location">Location permissions are needed to find your current location</string> <string name="location_permission_required_location">Location permissions are needed to find your current location</string>
<string name="open_map">Open map</string>
<string name="choose_new_location">Choose new location</string>
</resources> </resources>

Loading…
Cancel
Save