diff --git a/res/values/strings.xml b/res/values/strings.xml
index a0986a0e3..67860c29a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -221,6 +221,7 @@
Show location traces in time frame
+ Last position
diff --git a/src/org/thoughtcrime/securesms/components/rangeslider/RangeSliderView.java b/src/org/thoughtcrime/securesms/components/rangeslider/RangeSliderView.java
index 5dfacf477..8e361e55b 100644
--- a/src/org/thoughtcrime/securesms/components/rangeslider/RangeSliderView.java
+++ b/src/org/thoughtcrime/securesms/components/rangeslider/RangeSliderView.java
@@ -7,6 +7,7 @@ import android.graphics.Canvas;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
@@ -43,8 +44,11 @@ public class RangeSliderView extends View {
protected float delta;
private float beginTrackOffsetX;
+ private boolean isThumbViewLocked;
private OnValueChangedListener onValueChangedListener;
+ GestureDetector longPressDetector;
+
public interface OnValueChangedListener {
void onValueChanged(int minValue, int maxValue);
@@ -125,6 +129,17 @@ public class RangeSliderView extends View {
values.add(index);
}
delta = 0;
+
+ longPressDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
+ public void onLongPress(MotionEvent e) {
+ if (minValue == maxValue && (minValueThumb.isHighlight || maxValueThumb.isHighlight)) {
+ isThumbViewLocked = true;
+ minValueThumb.isHighlight = true;
+ maxValueThumb.isHighlight = true;
+ invalidate();
+ }
+ }
+ });
}
void setOnValueChangedListener(OnValueChangedListener onValueChangedListener) {
@@ -183,21 +198,28 @@ public class RangeSliderView extends View {
@Override
public boolean onTouchEvent(MotionEvent event) {
+ longPressDetector.onTouchEvent(event);
+
if (event.getAction() == MotionEvent.ACTION_CANCEL) {
minValueThumb.isHighlight = false;
maxValueThumb.isHighlight = false;
+ isThumbViewLocked = false;
invalidate();
return true;
}
- if (event.getAction() == MotionEvent.ACTION_UP && (minValueThumb.isHighlight || maxValueThumb.isHighlight)) {
- if (onValueChangedListener != null) {
- onValueChangedListener.onValueChanged(minValue, maxValue);
+
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ isThumbViewLocked = false;
+ if (minValueThumb.isHighlight || maxValueThumb.isHighlight) {
+ if (onValueChangedListener != null) {
+ onValueChangedListener.onValueChanged(minValue, maxValue);
+ }
+ minValueThumb.isHighlight = false;
+ maxValueThumb.isHighlight = false;
+ invalidate();
+ return true;
}
- minValueThumb.isHighlight = false;
- maxValueThumb.isHighlight = false;
- invalidate();
- return true;
}
int offsetX = (int) event.getX();
@@ -232,6 +254,7 @@ public class RangeSliderView extends View {
minValueThumb.isHighlight = false;
maxValueThumb.isHighlight = true;
}
+
int count = values.size();
int index = getIndexFromPosition(offsetX);
Log.d(TAG, "move - index: " + index + ", offsetX: " + offsetX);
@@ -241,7 +264,10 @@ public class RangeSliderView extends View {
index = count - 1;
}
- if (minValueThumb.isHighlight) {
+ if (isThumbViewLocked) {
+ minValue = values.get(index);
+ maxValue = values.get(index);
+ } else if (minValueThumb.isHighlight) {
if (index > values.indexOf(maxValue)) {
minValue = maxValue;
} else {
diff --git a/src/org/thoughtcrime/securesms/components/rangeslider/TimeRangeSlider.java b/src/org/thoughtcrime/securesms/components/rangeslider/TimeRangeSlider.java
index e4ea2ed40..4a27b0429 100644
--- a/src/org/thoughtcrime/securesms/components/rangeslider/TimeRangeSlider.java
+++ b/src/org/thoughtcrime/securesms/components/rangeslider/TimeRangeSlider.java
@@ -108,6 +108,9 @@ public class TimeRangeSlider extends RangeSliderView implements RangeSliderView.
@Override
public String parseMaxValueDisplayText(int maxValue) {
+ if (minValue == maxValue && maxValue == getCount()) {
+ return getContext().getResources().getString(R.string.filter_last_position);
+ }
return getStringForValue(maxValue);
}
diff --git a/src/org/thoughtcrime/securesms/map/MapActivity.java b/src/org/thoughtcrime/securesms/map/MapActivity.java
index be60fe1e7..a1ab7ffb0 100644
--- a/src/org/thoughtcrime/securesms/map/MapActivity.java
+++ b/src/org/thoughtcrime/securesms/map/MapActivity.java
@@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.map;
import android.content.Intent;
import android.graphics.PointF;
import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetBehavior;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AlertDialog;
@@ -13,8 +15,11 @@ import android.widget.RelativeLayout;
import com.b44t.messenger.DcMsg;
import com.mapbox.geojson.Feature;
import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdate;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.exceptions.InvalidLatLngBoundsException;
import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.maps.SupportMapFragment;
@@ -34,11 +39,12 @@ import java.util.Observer;
import static android.support.design.widget.BottomSheetBehavior.STATE_COLLAPSED;
import static android.support.design.widget.BottomSheetBehavior.STATE_EXPANDED;
+import static android.support.design.widget.BottomSheetBehavior.STATE_HIDDEN;
import static com.b44t.messenger.DcChat.DC_CHAT_NO_CHAT;
import static org.thoughtcrime.securesms.map.MapDataManager.MARKER_SELECTED;
import static org.thoughtcrime.securesms.map.MapDataManager.MESSAGE_ID;
-public class MapActivity extends BaseActivity implements Observer {
+public class MapActivity extends BaseActivity implements Observer, TimeRangeSlider.OnTimestampChangedListener {
public static final String TAG = MapActivity.class.getSimpleName();
public static final String CHAT_ID = "chat_id";
@@ -209,4 +215,20 @@ public class MapActivity extends BaseActivity implements Observer {
//TODO: consider implementing a button -> center map to current location
}
}
+
+ @Override
+ public void onValueChanged(long startTimestamp, long stopTimestamp) {
+ if (this.mapboxMap == null) {
+ return;
+ }
+ LatLngBounds.Builder boundingBuilder = new LatLngBounds.Builder();
+ mapDataManager.filter(startTimestamp, stopTimestamp, boundingBuilder);
+ try {
+ mapboxMap.easeCamera(
+ CameraUpdateFactory.newLatLngBounds(boundingBuilder.build(), 50, 50, 50, 200),
+ 500);
+ } catch (InvalidLatLngBoundsException e) {
+ e.printStackTrace();
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/map/MapDataManager.java b/src/org/thoughtcrime/securesms/map/MapDataManager.java
index 2cf377ea6..2a7596725 100644
--- a/src/org/thoughtcrime/securesms/map/MapDataManager.java
+++ b/src/org/thoughtcrime/securesms/map/MapDataManager.java
@@ -204,12 +204,24 @@ public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateIn
}
}
+ public void filter(long startTimestamp, long endTimestamp, LatLngBounds.Builder builder) {
+ int[] contactIds = getContactIds(chatId);
+ for (int contactId : contactIds) {
+ resetSource(chatId);
+ updateSource(chatId, contactId, startTimestamp, endTimestamp, builder);
+ }
+ }
+
private void updateSource(int chatId, int contactId) {
updateSource(chatId, contactId, null);
}
private void updateSource(int chatId, int contactId, LatLngBounds.Builder boundingBuilder) {
- DcArray locations = dcContext.getLocations(chatId, contactId, System.currentTimeMillis() - TIMEOUT, TIMESTAMP_NOW);
+ updateSource(chatId, contactId, System.currentTimeMillis() - TIMEOUT, TIMESTAMP_NOW, boundingBuilder );
+ }
+
+ private void updateSource(int chatId, int contactId, long startTimestamp, long endTimestamp, LatLngBounds.Builder boundingBuilder) {
+ DcArray locations = dcContext.getLocations(chatId, contactId, startTimestamp, endTimestamp);
MapSource contactMapMetadata = contactMapSources.get(contactId);
if (contactMapMetadata == null) {
contactMapMetadata = addContactMapSource(contactId);
@@ -405,6 +417,12 @@ public class MapDataManager implements DcEventCenter.DcEventDelegate, GenerateIn
}
}
+ private void resetSource(int contactId) {
+ MapSource contactMapMetadata = contactMapSources.get(contactId);
+ if (contactMapMetadata != null) {
+ featureCollections.put(contactMapMetadata.getMarkerFeatureCollection(), new FeatureTreeSet());
+ }
+ }
private void replaceSelectedMarker(String featureId) {
Feature feature = getFeatureWithId(featureId);