implement share location button, share location timespan, rename threadId to chatId

This commit is contained in:
cyBerta
2019-03-06 17:25:01 +01:00
committed by B. Petersen
parent 3e28cbed05
commit be8a718b3f
11 changed files with 176 additions and 68 deletions
@@ -177,7 +177,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private Recipient recipient;
private ApplicationDcContext dcContext;
private DcChat dcChat = new DcChat(0);
private int threadId;
private int chatId;
private boolean archived;
private final boolean isSecureText = true;
private boolean isDefaultSms = true;
@@ -284,7 +284,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
titleView.setTitle(glideRequests, dcChat);
MessageNotifier.updateVisibleChat(this, threadId);
MessageNotifier.updateVisibleChat(this, chatId);
markThreadAsRead();
}
@@ -359,7 +359,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
addAttachmentContactInfo(data);
break;
case GROUP_EDIT:
dcChat = dcContext.getChat(threadId);
dcChat = dcContext.getChat(chatId);
titleView.setTitle(glideRequests, dcChat);
supportInvalidateOptionsMenu();
break;
@@ -402,11 +402,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
MenuInflater inflater = this.getMenuInflater();
menu.clear();
if(threadId==DcChat.DC_CHAT_ID_DEADDROP) {
if(chatId ==DcChat.DC_CHAT_ID_DEADDROP) {
return true;
}
if (recipient != null && Prefs.isChatMuted(this, threadId)) {
if (recipient != null && Prefs.isChatMuted(this, chatId)) {
inflater.inflate(R.menu.conversation_muted, menu);
}
else {
@@ -487,13 +487,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void handleMuteNotifications() {
MuteDialog.show(this, until -> {
Prefs.setChatMutedUntil(this, threadId, until);
Prefs.setChatMutedUntil(this, chatId, until);
titleView.setTitle(glideRequests, dcChat); // update title-mute-icon
});
}
private void handleConversationSettings() {
if(threadId!=DcChat.DC_CHAT_ID_DEADDROP) {
if(chatId !=DcChat.DC_CHAT_ID_DEADDROP) {
Intent intent = new Intent(ConversationActivity.this, RecipientPreferenceActivity.class);
intent.putExtra(RecipientPreferenceActivity.ADDRESS_EXTRA, recipient.getAddress());
startActivitySceneTransition(intent, titleView.findViewById(R.id.contact_photo_image), "avatar");
@@ -501,7 +501,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void handleUnmuteNotifications() {
Prefs.setChatMutedUntil(this, threadId, 0);
Prefs.setChatMutedUntil(this, chatId, 0);
titleView.setTitle(glideRequests, dcChat); // update title-mute-icon
}
@@ -515,7 +515,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
new AlertDialog.Builder(this)
.setMessage(getString(R.string.ask_leave_group))
.setPositiveButton(R.string.yes, (dialog, which) -> {
dcContext.removeContactFromChat(threadId, DcContact.DC_CONTACT_ID_SELF);
dcContext.removeContactFromChat(chatId, DcContact.DC_CONTACT_ID_SELF);
Toast.makeText(this, getString(R.string.done), Toast.LENGTH_SHORT).show();
})
.setNegativeButton(R.string.no, null)
@@ -523,8 +523,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void handleArchiveChat() {
int doArchive = dcContext.getChat(threadId).getArchived()==0? 1: 0;
dcContext.archiveChat(threadId, doArchive);
int doArchive = dcContext.getChat(chatId).getArchived()==0? 1: 0;
dcContext.archiveChat(chatId, doArchive);
Toast.makeText(this, getString(R.string.done), Toast.LENGTH_SHORT).show();
if( doArchive == 1 ) {
finish();
@@ -535,7 +535,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
new AlertDialog.Builder(this)
.setMessage(getResources().getQuantityString(R.plurals.ask_delete_chat, 1, 1))
.setPositiveButton(R.string.delete, (dialog, which) -> {
dcContext.deleteChat(threadId);
dcContext.deleteChat(chatId);
Toast.makeText(this, getString(R.string.done), Toast.LENGTH_SHORT).show();
finish();
})
@@ -545,7 +545,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void handleEditPushGroup() {
Intent intent = new Intent(ConversationActivity.this, GroupCreateActivity.class);
intent.putExtra(GroupCreateActivity.EDIT_GROUP_CHAT_ID, threadId);
intent.putExtra(GroupCreateActivity.EDIT_GROUP_CHAT_ID, chatId);
if (dcChat.isVerified()) {
intent.putExtra(GroupCreateActivity.GROUP_CREATE_VERIFIED_EXTRA, true);
}
@@ -614,7 +614,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
new AsyncTask<Void, Void, DcMsg>() {
@Override
protected DcMsg doInBackground(Void... params) {
return dcContext.getDraft(threadId);
return dcContext.getDraft(chatId);
}
@Override
@@ -764,10 +764,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void initializeResources() {
threadId = getIntent().getIntExtra(THREAD_ID_EXTRA, -1);
if(threadId == DcChat.DC_CHAT_NO_CHAT)
chatId = getIntent().getIntExtra(THREAD_ID_EXTRA, -1);
if(chatId == DcChat.DC_CHAT_NO_CHAT)
throw new IllegalStateException("can't display a conversation for no chat.");
dcChat = dcContext.getChat(threadId);
dcChat = dcContext.getChat(chatId);
recipient = dcContext.getRecipient(dcChat);
archived = getIntent().getBooleanExtra(IS_ARCHIVED_EXTRA, false);
glideRequests = GlideApp.with(this);
@@ -779,7 +779,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
conversationContainer.setClipToPadding(true);
}
if(threadId==DcChat.DC_CHAT_ID_DEADDROP) {
if(chatId ==DcChat.DC_CHAT_ID_DEADDROP) {
composePanel.setVisibility(View.GONE);
titleView.hideAvatar();
}
@@ -799,7 +799,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
case AttachmentTypeSelector.ADD_CONTACT_INFO:
startContactChooserActivity(); break;
case AttachmentTypeSelector.ADD_LOCATION:
AttachmentManager.selectLocation(this, PICK_LOCATION); break;
AttachmentManager.selectLocation(this, chatId); break;
case AttachmentTypeSelector.TAKE_PHOTO:
attachmentManager.capturePhoto(this, TAKE_PHOTO); break;
}
@@ -840,8 +840,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
return this.recipient;
}
protected long getThreadId() {
return this.threadId;
protected long getChatId() {
return this.chatId;
}
private MediaConstraints getCurrentMediaConstraints() {
@@ -852,10 +852,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
new AsyncTask<Integer, Void, Void>() {
@Override
protected Void doInBackground(Integer... params) {
MessageNotifier.updateNotification(ConversationActivity.this, threadId, false);
MessageNotifier.updateNotification(ConversationActivity.this, chatId, false);
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, threadId);
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, chatId);
}
private String getRealPathFromAttachment(Attachment attachment) {
@@ -976,7 +976,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
protected void onPostExecute(Void result) {
future.set(threadId);
future.set(chatId);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, msg, recompress);
@@ -984,8 +984,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
protected void sendComplete(int threadId) {
boolean refreshFragment = (threadId != this.threadId);
this.threadId = threadId;
boolean refreshFragment = (threadId != this.chatId);
this.chatId = threadId;
if (fragment == null || !fragment.isVisible() || isFinishing()) {
return;
@@ -1279,8 +1279,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
@Override
public void setThreadId(int threadId) {
this.threadId = threadId;
public void setChatId(int chatId) {
this.chatId = chatId;
}
@Override
@@ -544,7 +544,7 @@ public class ConversationFragment extends Fragment
}
public interface ConversationFragmentListener {
void setThreadId(int threadId);
void setChatId(int threadId);
void handleReplyMessage(DcMsg messageRecord);
}
@@ -0,0 +1,55 @@
package org.thoughtcrime.securesms;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import java.util.concurrent.TimeUnit;
/**
* Created by cyberta on 06.03.19.
*/
public class ShareLocationDialog extends AlertDialog {
protected ShareLocationDialog(Context context) {
super(context);
}
protected ShareLocationDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
protected ShareLocationDialog(Context context, int theme) {
super(context, theme);
}
public static void show(final Context context, final @NonNull ShareLocationDurationSelectionListener listener) {
Builder builder = new Builder(context);
builder.setTitle(R.string.title_share_location);
builder.setItems(R.array.share_location_durations, (dialog, which) -> {
final int shareLocationUnit;
switch (which) {
default:
case 0: shareLocationUnit = 1; break;
case 1: shareLocationUnit = 5 * 60; break;
case 2: shareLocationUnit = 30 * 60; break;
case 3: shareLocationUnit = 60 * 60; break;
case 4: shareLocationUnit = 60 * 60 * 2; break;
case 5: shareLocationUnit = 60 * 60 * 6; break;
}
listener.onSelected(shareLocationUnit);
});
builder.show();
}
public interface ShareLocationDurationSelectionListener {
void onSelected(int durationInSeconds);
}
}
@@ -25,7 +25,7 @@ public class DcLocation extends Observable {
}
public Location getLastLocation() {
return instance.lastLocation;
return lastLocation;
}
void updateLocation(Location location) {
@@ -8,6 +8,7 @@ import android.location.Location;
import android.os.IBinder;
import android.util.Log;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Observer;
@@ -23,11 +24,14 @@ public class DcLocationManager implements Observer {
private LocationBackgroundService.LocationBackgroundServiceBinder serviceBinder;
private Context context;
private DcLocation dcLocation = DcLocation.getInstance();
private LinkedList<Integer> pendingShareLastLocation = new LinkedList<>();
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
serviceBinder = (LocationBackgroundService.LocationBackgroundServiceBinder) service;
startLocationEngine();
while (pendingShareLastLocation.size() > 0) {
shareLastLocation(pendingShareLastLocation.pop());
}
}
@Override
@@ -60,8 +64,14 @@ public class DcLocationManager implements Observer {
serviceBinder.stop();
}
public void shareLastLocation() {
public void shareLocation(int duration, int chatId) {
startLocationEngine();
Log.d(TAG, String.format("Share location in chat %d for %d seconds", chatId, duration));
}
public void shareLastLocation(int chatId) {
if (serviceBinder == null) {
pendingShareLastLocation.push(chatId);
initializeLocationEngine();
return;
}
@@ -81,5 +91,6 @@ public class DcLocationManager implements Observer {
private void writeDcLocationUpdateMessage() {
//TODO: implement me!
Log.d(TAG, "Share location: " + dcLocation.getLastLocation().getLatitude() + ", " + dcLocation.getLastLocation().getLongitude());
}
}
@@ -11,6 +11,7 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
/**
* Created by cyberta on 06.03.19.
@@ -22,7 +23,7 @@ public class LocationBackgroundService extends Service {
private static final String TAG = LocationBackgroundService.class.getSimpleName();
private LocationManager locationManager = null;
private static final int LOCATION_INTERVAL = 1000;
private static final float LOCATION_DISTANCE = 20f;
private static final float LOCATION_DISTANCE = 25F;
ServiceLocationListener locationListener;
private final IBinder mBinder = new LocationBackgroundServiceBinder();
@@ -80,7 +81,7 @@ public class LocationBackgroundService extends Service {
locationManager.requestLocationUpdates(
provider, LOCATION_INTERVAL, LOCATION_DISTANCE,
locationListener);
} catch (SecurityException | IllegalArgumentException ex) {
} catch (SecurityException | IllegalArgumentException ex) {
Log.e(TAG, String.format("Unable to request %s provider based location updates.", provider), ex);
}
}
@@ -109,10 +110,11 @@ public class LocationBackgroundService extends Service {
}
private class ServiceLocationListener implements LocationListener {
private static final int EARTH_RADIUS = 6371;
@Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location);
Log.d(TAG, "onLocationChanged: " + location);
if (isBetterLocation(location, DcLocation.getInstance().getLastLocation())) {
DcLocation.getInstance().updateLocation(location);
}
@@ -147,38 +149,50 @@ public class LocationBackgroundService extends Service {
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TIMEOUT;
boolean isSignificantlyOlder = timeDelta < -TIMEOUT;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
boolean isSignificantlyMoreAccurate = accuracyDelta < -50;
boolean isSameProvider = isSameProvider(location.getProvider(), currentBestLocation.getProvider());
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
if (isSignificantlyMoreAccurate && isSameProvider) {
return true;
}
return false;
boolean isSignificantlyLessAccurate = accuracyDelta > 50;
boolean hasLocationChanged = hasLocationDistanceChanged(location, currentBestLocation);
return hasLocationChanged && !isSignificantlyLessAccurate;
}
private boolean hasLocationDistanceChanged(Location location, Location currentBestLocation) {
return distance(location.getLatitude(), location.getLongitude(), currentBestLocation.getLatitude(), currentBestLocation.getLongitude()) > LOCATION_DISTANCE;
}
private double distance(double startLat, double startLong,
double endLat, double endLong) {
double dLat = Math.toRadians(endLat - startLat);
double dLong = Math.toRadians(endLong - startLong);
startLat = Math.toRadians(startLat);
endLat = Math.toRadians(endLat);
double a = haversin(dLat) + Math.cos(startLat) * Math.cos(endLat) * haversin(dLong);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double distance = EARTH_RADIUS * c * 1000;
Log.d(TAG, "Distance between location updates: " + distance);
Toast.makeText(LocationBackgroundService.this, "Distance in m between location updates: " + distance , Toast.LENGTH_LONG).show();
return distance;
}
private double haversin(double val) {
return Math.pow(Math.sin(val / 2), 2);
}
/** Checks whether two providers are the same */
@@ -37,18 +37,23 @@ import android.util.Pair;
import android.view.View;
import android.widget.Toast;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.MediaPreviewActivity;
import org.thoughtcrime.securesms.MuteDialog;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.ShareLocationDialog;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.audio.AudioSlidePlayer;
import org.thoughtcrime.securesms.components.AudioView;
import org.thoughtcrime.securesms.components.DocumentView;
import org.thoughtcrime.securesms.components.RemovableEditableMediaView;
import org.thoughtcrime.securesms.components.ThumbnailView;
import org.thoughtcrime.securesms.geolocation.DcLocationManager;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
@@ -385,21 +390,27 @@ public class AttachmentManager {
.execute();
}
public static void selectLocation(Activity activity, int requestCode) {
/*
public static void selectLocation(Activity activity, int chatId) {
Permissions.with(activity)
.request(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)
.ifNecessary()
.withPermanentDenialDialog(activity.getString(R.string.perm_explain_access_to_location_denied))
.onAllGranted(() -> {
try {
activity.startActivityForResult(new PlacePicker.IntentBuilder().build(activity), requestCode);
} catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException e) {
Log.w(TAG, e);
}
ShareLocationDialog.show(activity, durationInSeconds -> {
DcLocationManager dcLocationManager = ApplicationContext.getInstance(activity).dcLocationManager;
switch (durationInSeconds) {
case 1: dcLocationManager.shareLastLocation(chatId); break;
default:
dcLocationManager.shareLocation(durationInSeconds, chatId);
break;
}
});
})
.execute();
*/
}
private @Nullable Uri getSlideUri() {
@@ -71,7 +71,7 @@ public class DirectShareService extends ChooserTargetService {
// parcel.writeParcelable(recipient.getAddress(), 0);
//
// Bundle bundle = new Bundle();
// bundle.putLong(ShareActivity.EXTRA_THREAD_ID, record.getThreadId());
// bundle.putLong(ShareActivity.EXTRA_THREAD_ID, record.getChatId());
// bundle.putByteArray(ShareActivity.EXTRA_ADDRESS_MARSHALLED, parcel.marshall());
// bundle.putInt(ShareActivity.EXTRA_DISTRIBUTION_TYPE, record.getDistributionType());
// bundle.setClassLoader(getClassLoader());