mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 20:15:21 +00:00
Merge branch 'dev' into sealed-sender
This commit is contained in:
commit
8aa46aebec
@ -178,8 +178,6 @@
|
|||||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.LinkedDevicesActivity"
|
android:name="org.thoughtcrime.securesms.loki.redesign.activities.LinkedDevicesActivity"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait" />
|
||||||
<!-- Session -->
|
<!-- Session -->
|
||||||
<activity android:name="org.thoughtcrime.securesms.loki.LinkedDevicesActivity"
|
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.thoughtcrime.securesms.WebRtcCallActivity"
|
android:name="org.thoughtcrime.securesms.WebRtcCallActivity"
|
||||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|fontScale"
|
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|screenSize|fontScale"
|
||||||
@ -549,27 +547,7 @@
|
|||||||
android:name="org.thoughtcrime.securesms.ShortcutLauncherActivity"
|
android:name="org.thoughtcrime.securesms.ShortcutLauncherActivity"
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:theme="@style/TextSecure.LightNoActionBar" /> <!-- Loki -->
|
android:theme="@style/TextSecure.LightNoActionBar" />
|
||||||
<activity
|
|
||||||
android:name="org.thoughtcrime.securesms.loki.DisplayNameActivity"
|
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:theme="@style/TextSecure.DarkRegistrationTheme"
|
|
||||||
android:windowSoftInputMode="stateUnchanged" />
|
|
||||||
<activity
|
|
||||||
android:name="org.thoughtcrime.securesms.loki.SeedActivity"
|
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:theme="@style/TextSecure.DarkRegistrationTheme"
|
|
||||||
android:windowSoftInputMode="stateUnchanged" />
|
|
||||||
<activity
|
|
||||||
android:name="org.thoughtcrime.securesms.loki.NewConversationActivity"
|
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
|
||||||
android:windowSoftInputMode="stateAlwaysVisible" />
|
|
||||||
<activity
|
|
||||||
android:name="org.thoughtcrime.securesms.loki.AddPublicChatActivity"
|
|
||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
|
||||||
android:windowSoftInputMode="stateAlwaysVisible" /> <!-- Loki -->
|
|
||||||
<service
|
<service
|
||||||
android:name="org.thoughtcrime.securesms.service.WebRtcCallService"
|
android:name="org.thoughtcrime.securesms.service.WebRtcCallService"
|
||||||
android:enabled="true" />
|
android:enabled="true" />
|
||||||
@ -808,12 +786,12 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<!-- Session -->
|
<!-- Session -->
|
||||||
<receiver android:name="org.thoughtcrime.securesms.loki.BackgroundPollWorker">
|
<receiver android:name="org.thoughtcrime.securesms.loki.redesign.messaging.BackgroundPollWorker">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver android:name="org.thoughtcrime.securesms.loki.BackgroundPublicChatPollWorker">
|
<receiver android:name="org.thoughtcrime.securesms.loki.redesign.messaging.BackgroundPublicChatPollWorker">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
@ -187,7 +187,6 @@ dependencies {
|
|||||||
implementation "org.whispersystems:curve25519-java:0.5.0"
|
implementation "org.whispersystems:curve25519-java:0.5.0"
|
||||||
// Remote:
|
// Remote:
|
||||||
// implementation "com.github.loki-project:loki-messenger-android-service:dev-SNAPSHOT"
|
// implementation "com.github.loki-project:loki-messenger-android-service:dev-SNAPSHOT"
|
||||||
// implementation "org.signal:signal-metadata-android:0.0.3"
|
|
||||||
implementation "com.google.protobuf:protobuf-java:2.5.0"
|
implementation "com.google.protobuf:protobuf-java:2.5.0"
|
||||||
implementation "com.googlecode.libphonenumber:libphonenumber:8.10.7"
|
implementation "com.googlecode.libphonenumber:libphonenumber:8.10.7"
|
||||||
implementation "com.fasterxml.jackson.core:jackson-databind:2.9.8"
|
implementation "com.fasterxml.jackson.core:jackson-databind:2.9.8"
|
||||||
|
@ -66,8 +66,8 @@ import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger;
|
|||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.logging.PersistentLogger;
|
import org.thoughtcrime.securesms.logging.PersistentLogger;
|
||||||
import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger;
|
import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger;
|
||||||
import org.thoughtcrime.securesms.loki.BackgroundPollWorker;
|
import org.thoughtcrime.securesms.loki.redesign.messaging.BackgroundPollWorker;
|
||||||
import org.thoughtcrime.securesms.loki.BackgroundPublicChatPollWorker;
|
import org.thoughtcrime.securesms.loki.redesign.messaging.BackgroundPublicChatPollWorker;
|
||||||
import org.thoughtcrime.securesms.loki.LokiAPIDatabase;
|
import org.thoughtcrime.securesms.loki.LokiAPIDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.LokiPublicChatManager;
|
import org.thoughtcrime.securesms.loki.LokiPublicChatManager;
|
||||||
import org.thoughtcrime.securesms.loki.LokiRSSFeedPoller;
|
import org.thoughtcrime.securesms.loki.LokiRSSFeedPoller;
|
||||||
|
@ -41,8 +41,6 @@ import android.util.Log;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||||
import org.thoughtcrime.securesms.loki.LinkedDevicesActivity;
|
|
||||||
import org.thoughtcrime.securesms.loki.QRCodeDialog;
|
|
||||||
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
|
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
|
||||||
import org.thoughtcrime.securesms.preferences.ChatsPreferenceFragment;
|
import org.thoughtcrime.securesms.preferences.ChatsPreferenceFragment;
|
||||||
import org.thoughtcrime.securesms.preferences.CorrectedPreferenceFragment;
|
import org.thoughtcrime.securesms.preferences.CorrectedPreferenceFragment;
|
||||||
@ -338,13 +336,8 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
|||||||
shareIntent.setType("text/plain");
|
shareIntent.setType("text/plain");
|
||||||
startActivity(shareIntent);
|
startActivity(shareIntent);
|
||||||
break;
|
break;
|
||||||
case PREFERENCE_CATEGORY_QR_CODE:
|
case PREFERENCE_CATEGORY_QR_CODE: break;
|
||||||
QRCodeDialog.INSTANCE.show(getContext());
|
case PREFERENCE_CATEGORY_LINKED_DEVICES: break;
|
||||||
break;
|
|
||||||
case PREFERENCE_CATEGORY_LINKED_DEVICES:
|
|
||||||
Intent intent = new Intent(getActivity(), LinkedDevicesActivity.class);
|
|
||||||
startActivity(intent);
|
|
||||||
break;
|
|
||||||
case PREFERENCE_CATEGORY_SEED:
|
case PREFERENCE_CATEGORY_SEED:
|
||||||
Analytics.Companion.getShared().track("Seed Modal Shown");
|
Analytics.Companion.getShared().track("Seed Modal Shown");
|
||||||
File languageFileDirectory = new File(getContext().getApplicationInfo().dataDir);
|
File languageFileDirectory = new File(getContext().getApplicationInfo().dataDir);
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -35,7 +34,6 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewOutlineProvider;
|
import android.view.ViewOutlineProvider;
|
||||||
import android.view.ViewTreeObserver;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
@ -46,20 +44,16 @@ import org.greenrobot.eventbus.Subscribe;
|
|||||||
import org.greenrobot.eventbus.ThreadMode;
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
import org.thoughtcrime.securesms.components.RatingManager;
|
import org.thoughtcrime.securesms.components.RatingManager;
|
||||||
import org.thoughtcrime.securesms.components.SearchToolbar;
|
import org.thoughtcrime.securesms.components.SearchToolbar;
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
|
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationActivity;
|
import org.thoughtcrime.securesms.conversation.ConversationActivity;
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||||
import org.thoughtcrime.securesms.lock.RegistrationLockDialog;
|
import org.thoughtcrime.securesms.lock.RegistrationLockDialog;
|
||||||
import org.thoughtcrime.securesms.loki.AddPublicChatActivity;
|
|
||||||
import org.thoughtcrime.securesms.loki.JazzIdenticonDrawable;
|
|
||||||
import org.thoughtcrime.securesms.loki.RecipientAvatarModifiedEvent;
|
import org.thoughtcrime.securesms.loki.RecipientAvatarModifiedEvent;
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.activities.JoinPublicChatActivity;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.search.SearchFragment;
|
import org.thoughtcrime.securesms.search.SearchFragment;
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
@ -68,7 +62,6 @@ import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
|||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
|
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
|
||||||
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -333,7 +326,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addNewPublicChat() {
|
private void addNewPublicChat() {
|
||||||
startActivity(new Intent(this, AddPublicChatActivity.class));
|
startActivity(new Intent(this, JoinPublicChatActivity.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
@ -74,7 +74,7 @@ import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
|||||||
import org.thoughtcrime.securesms.database.loaders.ConversationListLoader;
|
import org.thoughtcrime.securesms.database.loaders.ConversationListLoader;
|
||||||
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
|
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
|
||||||
import org.thoughtcrime.securesms.jobs.ServiceOutageDetectionJob;
|
import org.thoughtcrime.securesms.jobs.ServiceOutageDetectionJob;
|
||||||
import org.thoughtcrime.securesms.loki.NewConversationActivity;
|
import org.thoughtcrime.securesms.loki.redesign.activities.CreatePrivateChatActivity;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||||
@ -155,7 +155,7 @@ public class ConversationListFragment extends Fragment
|
|||||||
super.onActivityCreated(bundle);
|
super.onActivityCreated(bundle);
|
||||||
|
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
fab.setOnClickListener(v -> startActivity(new Intent(getActivity(), NewConversationActivity.class)));
|
fab.setOnClickListener(v -> startActivity(new Intent(getActivity(), CreatePrivateChatActivity.class)));
|
||||||
initializeListAdapter();
|
initializeListAdapter();
|
||||||
initializeTypingObserver();
|
initializeTypingObserver();
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ import org.thoughtcrime.securesms.components.FromTextView;
|
|||||||
import org.thoughtcrime.securesms.components.ThumbnailView;
|
import org.thoughtcrime.securesms.components.ThumbnailView;
|
||||||
import org.thoughtcrime.securesms.components.TypingIndicatorView;
|
import org.thoughtcrime.securesms.components.TypingIndicatorView;
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||||
import org.thoughtcrime.securesms.loki.LokiAPIUtilities;
|
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIUtilities;
|
||||||
import org.thoughtcrime.securesms.loki.redesign.utilities.MentionUtilities;
|
import org.thoughtcrime.securesms.loki.redesign.utilities.MentionUtilities;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
@ -26,7 +26,7 @@ import org.thoughtcrime.securesms.database.loaders.DeviceListLoader;
|
|||||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||||
import org.thoughtcrime.securesms.devicelist.Device;
|
import org.thoughtcrime.securesms.devicelist.Device;
|
||||||
import org.thoughtcrime.securesms.loki.DeviceListBottomSheetFragment;
|
import org.thoughtcrime.securesms.loki.DeviceListBottomSheetFragment;
|
||||||
import org.thoughtcrime.securesms.loki.MnemonicUtilities;
|
import org.thoughtcrime.securesms.loki.redesign.utilities.MnemonicUtilities;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
import org.whispersystems.libsignal.util.guava.Function;
|
import org.whispersystems.libsignal.util.guava.Function;
|
||||||
|
@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob;
|
|||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;
|
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;
|
||||||
import org.thoughtcrime.securesms.loki.redesign.activities.LandingActivity;
|
import org.thoughtcrime.securesms.loki.redesign.activities.LandingActivity;
|
||||||
import org.thoughtcrime.securesms.loki.SeedActivity;
|
import org.thoughtcrime.securesms.loki.redesign.activities.SeedActivity;
|
||||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
@ -13,7 +13,6 @@ import org.thoughtcrime.securesms.conversation.ConversationActivity;
|
|||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.loki.NewConversationActivity;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.util.Rfc5724Uri;
|
import org.thoughtcrime.securesms.util.Rfc5724Uri;
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
|
|||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel;
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.loki.LokiAPIUtilities;
|
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIUtilities;
|
||||||
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.LokiThreadDatabaseDelegate;
|
import org.thoughtcrime.securesms.loki.LokiThreadDatabaseDelegate;
|
||||||
|
@ -2,47 +2,23 @@ package org.thoughtcrime.securesms.database.loaders;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
|
||||||
import org.thoughtcrime.securesms.database.Database;
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.devicelist.Device;
|
import org.thoughtcrime.securesms.devicelist.Device;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.loki.MnemonicUtilities;
|
import org.thoughtcrime.securesms.loki.redesign.utilities.MnemonicUtilities;
|
||||||
import org.thoughtcrime.securesms.util.AsyncLoader;
|
import org.thoughtcrime.securesms.util.AsyncLoader;
|
||||||
import org.thoughtcrime.securesms.util.Base64;
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.whispersystems.libsignal.InvalidKeyException;
|
|
||||||
import org.whispersystems.libsignal.ecc.Curve;
|
|
||||||
import org.whispersystems.libsignal.ecc.ECPrivateKey;
|
|
||||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
|
||||||
import org.whispersystems.libsignal.util.ByteUtil;
|
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
|
||||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo;
|
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
|
||||||
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
|
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
|
||||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec;
|
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
|
||||||
import javax.crypto.Mac;
|
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
|
|
||||||
import static org.thoughtcrime.securesms.devicelist.DeviceNameProtos.*;
|
|
||||||
import static org.whispersystems.signalservice.loki.utilities.TrimmingKt.removing05PrefixIfNeeded;
|
|
||||||
|
|
||||||
public class DeviceListLoader extends AsyncLoader<List<Device>> {
|
public class DeviceListLoader extends AsyncLoader<List<Device>> {
|
||||||
|
|
||||||
private static final String TAG = DeviceListLoader.class.getSimpleName();
|
private static final String TAG = DeviceListLoader.class.getSimpleName();
|
||||||
|
@ -68,7 +68,7 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
|||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.loki.FriendRequestHandler;
|
import org.thoughtcrime.securesms.loki.FriendRequestHandler;
|
||||||
import org.thoughtcrime.securesms.loki.LokiAPIUtilities;
|
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIUtilities;
|
||||||
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
|
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase;
|
import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase;
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Patterns
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.inputmethod.InputMethodManager
|
|
||||||
import android.widget.Toast
|
|
||||||
import kotlinx.android.synthetic.main.activity_add_public_chat.*
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import nl.komponents.kovenant.ui.failUi
|
|
||||||
import nl.komponents.kovenant.ui.successUi
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
|
||||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
|
||||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
|
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
|
||||||
|
|
||||||
class AddPublicChatActivity : PassphraseRequiredActionBarActivity() {
|
|
||||||
private val dynamicTheme = DynamicTheme()
|
|
||||||
|
|
||||||
override fun onPreCreate() {
|
|
||||||
dynamicTheme.onCreate(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(bundle: Bundle?, isReady: Boolean) {
|
|
||||||
supportActionBar!!.setTitle(R.string.fragment_add_public_chat_title)
|
|
||||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
|
||||||
setContentView(R.layout.activity_add_public_chat)
|
|
||||||
updateUI(false)
|
|
||||||
addButton.setOnClickListener { addPublicChatIfPossible() }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
dynamicTheme.onResume(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
if (item.itemId == android.R.id.home) {
|
|
||||||
onBackPressed()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addPublicChatIfPossible() {
|
|
||||||
val inputMethodManager = getSystemService(BaseActionBarActivity.INPUT_METHOD_SERVICE) as InputMethodManager
|
|
||||||
inputMethodManager.hideSoftInputFromWindow(urlEditText.windowToken, 0)
|
|
||||||
val url = urlEditText.text.toString().toLowerCase().replace("http://", "https://")
|
|
||||||
if (!Patterns.WEB_URL.matcher(url).matches() || !url.startsWith("https://")) {
|
|
||||||
return Toast.makeText(this, R.string.fragment_add_public_chat_invalid_url_message, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
updateUI(true)
|
|
||||||
val application = ApplicationContext.getInstance(this)
|
|
||||||
val channel: Long = 1
|
|
||||||
val displayName = TextSecurePreferences.getProfileName(this)
|
|
||||||
val lokiPublicChatAPI = application.lokiPublicChatAPI!!
|
|
||||||
application.lokiPublicChatManager.addChat(url, channel).successUi {
|
|
||||||
lokiPublicChatAPI.getMessages(channel, url)
|
|
||||||
lokiPublicChatAPI.setDisplayName(displayName, url)
|
|
||||||
val profileKey: ByteArray = ProfileKeyUtil.getProfileKey(this)
|
|
||||||
val profileUrl: String? = TextSecurePreferences.getProfileAvatarUrl(this)
|
|
||||||
lokiPublicChatAPI.setProfilePicture(url, profileKey, profileUrl)
|
|
||||||
finish()
|
|
||||||
}.failUi {
|
|
||||||
updateUI(false)
|
|
||||||
Toast.makeText(this, R.string.fragment_add_public_chat_connection_failed_message, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateUI(isConnecting: Boolean) {
|
|
||||||
addButton.isEnabled = !isConnecting
|
|
||||||
val text = if (isConnecting) R.string.fragment_add_public_chat_add_button_title_2 else R.string.fragment_add_public_chat_add_button_title_1
|
|
||||||
addButton.setText(text)
|
|
||||||
urlEditText.isEnabled = !isConnecting
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
|
||||||
|
|
||||||
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
|
||||||
|
|
||||||
// Loki - TODO: Remove this yucky delegate pattern for device linking dialog once we have the redesign
|
|
||||||
interface DeviceLinkingDelegate {
|
|
||||||
companion object {
|
|
||||||
fun combine(vararg delegates: DeviceLinkingDelegate?): DeviceLinkingDelegate {
|
|
||||||
val validDelegates = delegates.filterNotNull()
|
|
||||||
return object : DeviceLinkingDelegate {
|
|
||||||
override fun handleDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) {
|
|
||||||
for (delegate in validDelegates) { delegate.handleDeviceLinkAuthorized(pairingAuthorisation) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleDeviceLinkingDialogDismissed() {
|
|
||||||
for (delegate in validDelegates) { delegate.handleDeviceLinkingDialogDismissed() }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) {
|
|
||||||
for (delegate in validDelegates) { delegate.sendPairingAuthorizedMessage(pairingAuthorisation) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun handleDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) {}
|
|
||||||
fun handleDeviceLinkingDialogDismissed() {}
|
|
||||||
fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) {}
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.support.v7.app.AlertDialog
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
|
||||||
import org.thoughtcrime.securesms.util.Util
|
|
||||||
import org.whispersystems.signalservice.loki.api.DeviceLinkingSession
|
|
||||||
import org.whispersystems.signalservice.loki.api.DeviceLinkingSessionListener
|
|
||||||
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
|
||||||
|
|
||||||
class DeviceLinkingDialog private constructor(private val context: Context, private val mode: DeviceLinkingView.Mode, private val delegate: DeviceLinkingDelegate?) : DeviceLinkingDelegate, DeviceLinkingSessionListener {
|
|
||||||
private lateinit var view: DeviceLinkingView
|
|
||||||
private lateinit var dialog: AlertDialog
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun show(context: Context, mode: DeviceLinkingView.Mode, delegate: DeviceLinkingDelegate?): DeviceLinkingDialog {
|
|
||||||
val dialog = DeviceLinkingDialog(context, mode, delegate)
|
|
||||||
dialog.show()
|
|
||||||
return dialog
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun show() {
|
|
||||||
val delegate = DeviceLinkingDelegate.combine(this, this.delegate)
|
|
||||||
view = DeviceLinkingView(context, mode, delegate)
|
|
||||||
dialog = AlertDialog.Builder(context).setView(view).show()
|
|
||||||
dialog.setCanceledOnTouchOutside(false)
|
|
||||||
view.dismiss = { dismiss() }
|
|
||||||
DeviceLinkingSession.shared.startListeningForLinkingRequests()
|
|
||||||
DeviceLinkingSession.shared.addListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun dismiss() {
|
|
||||||
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
|
||||||
DeviceLinkingSession.shared.removeListener(this)
|
|
||||||
dialog.dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleDeviceLinkingDialogDismissed() {
|
|
||||||
if (mode == DeviceLinkingView.Mode.Master && view.pairingAuthorisation != null) {
|
|
||||||
val authorisation = view.pairingAuthorisation!!
|
|
||||||
DatabaseFactory.getLokiPreKeyBundleDatabase(context).removePreKeyBundle(authorisation.secondaryDevicePublicKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun requestUserAuthorization(authorisation: PairingAuthorisation) {
|
|
||||||
Util.runOnMain {
|
|
||||||
view.requestUserAuthorization(authorisation)
|
|
||||||
}
|
|
||||||
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDeviceLinkRequestAuthorized(authorisation: PairingAuthorisation) {
|
|
||||||
Util.runOnMain {
|
|
||||||
view.onDeviceLinkAuthorized(authorisation)
|
|
||||||
}
|
|
||||||
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,132 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.os.Handler
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.util.DisplayMetrics
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import kotlinx.android.synthetic.main.view_device_linking.view.*
|
|
||||||
import kotlinx.android.synthetic.main.view_device_linking.view.cancelButton
|
|
||||||
import kotlinx.android.synthetic.main.view_device_linking.view.explanationTextView
|
|
||||||
import kotlinx.android.synthetic.main.view_device_linking.view.titleTextView
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.thoughtcrime.securesms.qr.QrCode
|
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
|
||||||
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
|
||||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class DeviceLinkingView private constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, private val mode: Mode, private var delegate: DeviceLinkingDelegate) : LinearLayout(context, attrs, defStyleAttr) {
|
|
||||||
private val languageFileDirectory: File = MnemonicUtilities.getLanguageFileDirectory(context)
|
|
||||||
var dismiss: (() -> Unit)? = null
|
|
||||||
var pairingAuthorisation: PairingAuthorisation? = null
|
|
||||||
private set
|
|
||||||
|
|
||||||
// region Types
|
|
||||||
enum class Mode { Master, Slave }
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Lifecycle
|
|
||||||
constructor(context: Context, mode: Mode, delegate: DeviceLinkingDelegate) : this(context, null, 0, mode, delegate)
|
|
||||||
private constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0, Mode.Master, object : DeviceLinkingDelegate { }) // Just pass in a dummy mode
|
|
||||||
private constructor(context: Context) : this(context, null)
|
|
||||||
|
|
||||||
init {
|
|
||||||
setUpViewHierarchy()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setUpViewHierarchy() {
|
|
||||||
inflate(context, R.layout.view_device_linking, this)
|
|
||||||
spinner.indeterminateDrawable.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)
|
|
||||||
val titleID = when (mode) {
|
|
||||||
Mode.Master -> R.string.view_device_linking_title_1
|
|
||||||
Mode.Slave -> R.string.view_device_linking_title_2
|
|
||||||
}
|
|
||||||
titleTextView.text = resources.getString(titleID)
|
|
||||||
val explanationID = when (mode) {
|
|
||||||
Mode.Master -> R.string.view_device_linking_explanation_1
|
|
||||||
Mode.Slave -> R.string.view_device_linking_explanation_2
|
|
||||||
}
|
|
||||||
explanationTextView.text = resources.getString(explanationID)
|
|
||||||
mnemonicTextView.visibility = if (mode == Mode.Master) View.GONE else View.VISIBLE
|
|
||||||
if (mode == Mode.Slave) {
|
|
||||||
val hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
|
||||||
mnemonicTextView.text = MnemonicUtilities.getFirst3Words(MnemonicCodec(languageFileDirectory), hexEncodedPublicKey)
|
|
||||||
}
|
|
||||||
authorizeButton.visibility = View.GONE
|
|
||||||
authorizeButton.setOnClickListener { authorizePairing() }
|
|
||||||
|
|
||||||
// QR Code
|
|
||||||
spinner.visibility = if (mode == Mode.Master) View.GONE else View.VISIBLE
|
|
||||||
qrCodeImageView.visibility = if (mode == Mode.Master) View.VISIBLE else View.GONE
|
|
||||||
if (mode == Mode.Master) {
|
|
||||||
val hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
|
||||||
val displayMetrics = DisplayMetrics()
|
|
||||||
ServiceUtil.getWindowManager(context).defaultDisplay.getMetrics(displayMetrics)
|
|
||||||
val size = displayMetrics.widthPixels - 2 * toPx(96, resources)
|
|
||||||
val qrCode = QrCode.create(hexEncodedPublicKey, size)
|
|
||||||
qrCodeImageView.setImageBitmap(qrCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelButton.setOnClickListener { cancel() }
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Device Linking
|
|
||||||
fun requestUserAuthorization(pairingAuthorisation: PairingAuthorisation) {
|
|
||||||
if (mode != Mode.Master || pairingAuthorisation.type != PairingAuthorisation.Type.REQUEST || this.pairingAuthorisation != null) { return }
|
|
||||||
this.pairingAuthorisation = pairingAuthorisation
|
|
||||||
spinner.visibility = View.GONE
|
|
||||||
qrCodeImageView.visibility = View.GONE
|
|
||||||
val titleTextViewLayoutParams = titleTextView.layoutParams as LayoutParams
|
|
||||||
titleTextViewLayoutParams.topMargin = toPx(16, resources)
|
|
||||||
titleTextView.layoutParams = titleTextViewLayoutParams
|
|
||||||
titleTextView.text = resources.getString(R.string.view_device_linking_title_3)
|
|
||||||
explanationTextView.text = resources.getString(R.string.view_device_linking_explanation_2)
|
|
||||||
mnemonicTextView.visibility = View.VISIBLE
|
|
||||||
mnemonicTextView.text = MnemonicUtilities.getFirst3Words(MnemonicCodec(languageFileDirectory), pairingAuthorisation.secondaryDevicePublicKey)
|
|
||||||
authorizeButton.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) {
|
|
||||||
if (mode != Mode.Slave || pairingAuthorisation.type != PairingAuthorisation.Type.GRANT || this.pairingAuthorisation != null) { return }
|
|
||||||
this.pairingAuthorisation = pairingAuthorisation
|
|
||||||
spinner.visibility = View.GONE
|
|
||||||
val titleTextViewLayoutParams = titleTextView.layoutParams as LayoutParams
|
|
||||||
titleTextViewLayoutParams.topMargin = toPx(8, resources)
|
|
||||||
titleTextView.layoutParams = titleTextViewLayoutParams
|
|
||||||
titleTextView.text = resources.getString(R.string.view_device_linking_title_4)
|
|
||||||
val explanationTextViewLayoutParams = explanationTextView.layoutParams as LayoutParams
|
|
||||||
explanationTextViewLayoutParams.bottomMargin = toPx(12, resources)
|
|
||||||
explanationTextView.layoutParams = explanationTextViewLayoutParams
|
|
||||||
explanationTextView.text = resources.getString(R.string.view_device_linking_explanation_3)
|
|
||||||
titleTextView.text = resources.getString(R.string.view_device_linking_title_4)
|
|
||||||
mnemonicTextView.visibility = View.GONE
|
|
||||||
buttonContainer.visibility = View.GONE
|
|
||||||
cancelButton.visibility = View.GONE
|
|
||||||
Handler().postDelayed({
|
|
||||||
delegate.handleDeviceLinkAuthorized(pairingAuthorisation)
|
|
||||||
dismiss?.invoke()
|
|
||||||
}, 4000)
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Interaction
|
|
||||||
private fun authorizePairing() {
|
|
||||||
val pairingAuthorisation = this.pairingAuthorisation
|
|
||||||
if (mode != Mode.Master || pairingAuthorisation == null) { return; }
|
|
||||||
delegate.sendPairingAuthorizedMessage(pairingAuthorisation)
|
|
||||||
delegate.handleDeviceLinkAuthorized(pairingAuthorisation)
|
|
||||||
dismiss?.invoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun cancel() {
|
|
||||||
delegate.handleDeviceLinkingDialogDismissed()
|
|
||||||
dismiss?.invoke()
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
}
|
|
@ -9,16 +9,16 @@ import kotlinx.android.synthetic.main.fragment_device_list_bottom_sheet.*
|
|||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
|
||||||
public class DeviceListBottomSheetFragment : BottomSheetDialogFragment() {
|
public class DeviceListBottomSheetFragment : BottomSheetDialogFragment() {
|
||||||
var onEditTapped: (() -> Unit)? = null
|
var onEditTapped: (() -> Unit)? = null
|
||||||
var onUnlinkTapped: (() -> Unit)? = null
|
var onUnlinkTapped: (() -> Unit)? = null
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
return inflater.inflate(R.layout.fragment_device_list_bottom_sheet, container, false)
|
return inflater.inflate(R.layout.fragment_device_list_bottom_sheet, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
editDisplayNameText.setOnClickListener { onEditTapped?.invoke() }
|
editDisplayNameText.setOnClickListener { onEditTapped?.invoke() }
|
||||||
unlinkDeviceText.setOnClickListener { onUnlinkTapped?.invoke() }
|
unlinkDeviceText.setOnClickListener { onUnlinkTapped?.invoke() }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,61 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.inputmethod.InputMethodManager
|
|
||||||
import kotlinx.android.synthetic.main.activity_display_name.*
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
|
||||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
|
||||||
import org.thoughtcrime.securesms.ConversationListActivity
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
|
||||||
import org.thoughtcrime.securesms.loki.redesign.utilities.show
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
|
||||||
import org.whispersystems.signalservice.api.crypto.ProfileCipher
|
|
||||||
import org.whispersystems.signalservice.loki.utilities.Analytics
|
|
||||||
|
|
||||||
class DisplayNameActivity : BaseActionBarActivity() {
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_display_name)
|
|
||||||
nextButton.setOnClickListener { continueIfPossible() }
|
|
||||||
Analytics.shared.track("Display Name Screen Viewed")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun continueIfPossible() {
|
|
||||||
val name = nameEditText.text.toString()
|
|
||||||
if (name.isEmpty()) {
|
|
||||||
return nameEditText.input.setError("Invalid")
|
|
||||||
}
|
|
||||||
if (!name.matches(Regex("[a-zA-Z0-9_]+"))) {
|
|
||||||
return nameEditText.input.setError("Invalid (a-z, A-Z, 0-9 and _ only)")
|
|
||||||
}
|
|
||||||
if (name.toByteArray().size > ProfileCipher.NAME_PADDED_LENGTH) {
|
|
||||||
return nameEditText.input.setError("Too Long")
|
|
||||||
} else {
|
|
||||||
Analytics.shared.track("Display Name Updated")
|
|
||||||
TextSecurePreferences.setProfileName(this, name)
|
|
||||||
}
|
|
||||||
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
|
||||||
inputMethodManager.hideSoftInputFromWindow(nameEditText.windowToken, 0)
|
|
||||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
|
|
||||||
TextSecurePreferences.setPromptedPushRegistration(this, true)
|
|
||||||
val application = ApplicationContext.getInstance(this)
|
|
||||||
application.setUpP2PAPI()
|
|
||||||
application.startLongPollingIfNeeded()
|
|
||||||
application.setUpStorageAPIIfNeeded()
|
|
||||||
show(Intent(this, ConversationListActivity::class.java))
|
|
||||||
finish()
|
|
||||||
val publicChatAPI = ApplicationContext.getInstance(this).lokiPublicChatAPI
|
|
||||||
if (publicChatAPI != null) {
|
|
||||||
application.createDefaultPublicChatsIfNeeded()
|
|
||||||
application.createRSSFeedsIfNeeded()
|
|
||||||
application.lokiPublicChatManager.startPollersIfNeeded()
|
|
||||||
application.startRSSFeedPollersIfNeeded()
|
|
||||||
val servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers()
|
|
||||||
servers.forEach { publicChatAPI.setDisplayName(name, it) }
|
|
||||||
application.updatePublicChatProfileAvatarIfNeeded()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
|
||||||
|
|
||||||
import android.os.AsyncTask
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.widget.Toast
|
|
||||||
import org.thoughtcrime.securesms.*
|
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme
|
|
||||||
import org.thoughtcrime.securesms.util.DynamicLanguage
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import nl.komponents.kovenant.then
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
|
||||||
import org.thoughtcrime.securesms.util.Util
|
|
||||||
import org.whispersystems.signalservice.loki.api.LokiStorageAPI
|
|
||||||
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
|
||||||
|
|
||||||
class LinkedDevicesActivity : PassphraseRequiredActionBarActivity(), DeviceLinkingDelegate {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val TAG = DeviceActivity::class.java.simpleName
|
|
||||||
}
|
|
||||||
|
|
||||||
private val dynamicTheme = DynamicTheme()
|
|
||||||
private val dynamicLanguage = DynamicLanguage()
|
|
||||||
private lateinit var deviceListFragment: DeviceListFragment
|
|
||||||
|
|
||||||
public override fun onPreCreate() {
|
|
||||||
dynamicTheme.onCreate(this)
|
|
||||||
dynamicLanguage.onCreate(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
|
|
||||||
super.onCreate(savedInstanceState, ready)
|
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
|
||||||
supportActionBar?.setTitle(R.string.AndroidManifest__linked_devices)
|
|
||||||
this.deviceListFragment = DeviceListFragment()
|
|
||||||
this.deviceListFragment.setAddDeviceButtonListener {
|
|
||||||
DeviceLinkingDialog.show(this, DeviceLinkingView.Mode.Master, this)
|
|
||||||
}
|
|
||||||
this.deviceListFragment.setHandleDisconnectDevice { devicePublicKey ->
|
|
||||||
// Purge the device pairing from our database
|
|
||||||
val ourPublicKey = TextSecurePreferences.getLocalNumber(this)
|
|
||||||
val database = DatabaseFactory.getLokiAPIDatabase(this)
|
|
||||||
database.removePairingAuthorisation(ourPublicKey, devicePublicKey)
|
|
||||||
// Update mapping on the file server
|
|
||||||
LokiStorageAPI.shared.updateUserDeviceMappings().success {
|
|
||||||
// Send an unpair request to let the device know that it has been revoked
|
|
||||||
MessageSender.sendUnpairRequest(this, devicePublicKey)
|
|
||||||
}
|
|
||||||
// Refresh the list
|
|
||||||
this.deviceListFragment.refresh()
|
|
||||||
Toast.makeText(this, R.string.DeviceListActivity_unlinked_device, Toast.LENGTH_LONG).show()
|
|
||||||
return@setHandleDisconnectDevice null
|
|
||||||
}
|
|
||||||
this.deviceListFragment.setHandleDeviceNameChange { pair ->
|
|
||||||
DatabaseFactory.getLokiUserDatabase(this).setDisplayName(pair.first, pair.second)
|
|
||||||
this.deviceListFragment.refresh()
|
|
||||||
return@setHandleDeviceNameChange null
|
|
||||||
}
|
|
||||||
initFragment(android.R.id.content, deviceListFragment, dynamicLanguage.currentLocale)
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
dynamicTheme.onResume(this)
|
|
||||||
dynamicLanguage.onResume(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
if (item.itemId == android.R.id.home) {
|
|
||||||
finish()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun sendPairingAuthorizedMessage(pairingAuthorisation: PairingAuthorisation) {
|
|
||||||
AsyncTask.execute {
|
|
||||||
signAndSendPairingAuthorisationMessage(this, pairingAuthorisation)
|
|
||||||
Util.runOnMain { this.deviceListFragment.refresh() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,6 +4,7 @@ import android.content.ContentValues
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import org.thoughtcrime.securesms.database.Database
|
import org.thoughtcrime.securesms.database.Database
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.*
|
||||||
import org.thoughtcrime.securesms.util.Base64
|
import org.thoughtcrime.securesms.util.Base64
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.signalservice.loki.api.LokiAPIDatabaseProtocol
|
import org.whispersystems.signalservice.loki.api.LokiAPIDatabaseProtocol
|
||||||
|
@ -6,6 +6,9 @@ import org.thoughtcrime.securesms.database.Address
|
|||||||
import org.thoughtcrime.securesms.database.Database
|
import org.thoughtcrime.securesms.database.Database
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.get
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.getInt
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.insertOrUpdate
|
||||||
import org.whispersystems.signalservice.loki.messaging.LokiMessageDatabaseProtocol
|
import org.whispersystems.signalservice.loki.messaging.LokiMessageDatabaseProtocol
|
||||||
import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus
|
import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus
|
||||||
|
|
||||||
|
@ -9,6 +9,10 @@ import org.thoughtcrime.securesms.database.Database
|
|||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||||
import org.thoughtcrime.securesms.logging.Log
|
import org.thoughtcrime.securesms.logging.Log
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.get
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.getBase64EncodedData
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.getInt
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.insertOrUpdate
|
||||||
import org.thoughtcrime.securesms.util.Base64
|
import org.thoughtcrime.securesms.util.Base64
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.libsignal.IdentityKey
|
import org.whispersystems.libsignal.IdentityKey
|
||||||
|
@ -5,6 +5,9 @@ import android.content.Context
|
|||||||
import org.thoughtcrime.securesms.crypto.PreKeyUtil
|
import org.thoughtcrime.securesms.crypto.PreKeyUtil
|
||||||
import org.thoughtcrime.securesms.database.Database
|
import org.thoughtcrime.securesms.database.Database
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.get
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.getInt
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.insertOrUpdate
|
||||||
import org.whispersystems.libsignal.state.PreKeyRecord
|
import org.whispersystems.libsignal.state.PreKeyRecord
|
||||||
import org.whispersystems.signalservice.loki.messaging.LokiPreKeyRecordDatabaseProtocol
|
import org.whispersystems.signalservice.loki.messaging.LokiPreKeyRecordDatabaseProtocol
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import org.thoughtcrime.securesms.ApplicationContext
|
|||||||
import org.thoughtcrime.securesms.database.DatabaseContentProviders
|
import org.thoughtcrime.securesms.database.DatabaseContentProviders
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.groups.GroupManager
|
import org.thoughtcrime.securesms.groups.GroupManager
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiPublicChatPoller
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.thoughtcrime.securesms.util.Util
|
import org.thoughtcrime.securesms.util.Util
|
||||||
import org.whispersystems.signalservice.loki.api.LokiPublicChat
|
import org.whispersystems.signalservice.loki.api.LokiPublicChat
|
||||||
|
@ -7,6 +7,11 @@ import org.thoughtcrime.securesms.database.Address
|
|||||||
import org.thoughtcrime.securesms.database.Database
|
import org.thoughtcrime.securesms.database.Database
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.get
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.getInt
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.getLong
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.getString
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.insertOrUpdate
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.signalservice.internal.util.JsonUtil
|
import org.whispersystems.signalservice.internal.util.JsonUtil
|
||||||
|
@ -7,6 +7,8 @@ import android.util.Log
|
|||||||
import org.thoughtcrime.securesms.database.Address
|
import org.thoughtcrime.securesms.database.Address
|
||||||
import org.thoughtcrime.securesms.database.Database
|
import org.thoughtcrime.securesms.database.Database
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.get
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.insertOrUpdate
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.signalservice.loki.messaging.LokiUserDatabaseProtocol
|
import org.whispersystems.signalservice.loki.messaging.LokiUserDatabaseProtocol
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.widget.Toast
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
|
||||||
import org.thoughtcrime.securesms.database.Address
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions
|
|
||||||
import org.thoughtcrime.securesms.qr.ScanListener
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
|
||||||
import org.thoughtcrime.securesms.util.DynamicTheme
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
|
||||||
import org.whispersystems.signalservice.loki.utilities.Analytics
|
|
||||||
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
|
|
||||||
|
|
||||||
class NewConversationActivity : PassphraseRequiredActionBarActivity(), ScanListener {
|
|
||||||
private val dynamicTheme = DynamicTheme()
|
|
||||||
|
|
||||||
override fun onPreCreate() {
|
|
||||||
dynamicTheme.onCreate(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(bundle: Bundle?, isReady: Boolean) {
|
|
||||||
supportActionBar!!.setTitle(R.string.fragment_new_conversation_title)
|
|
||||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
|
||||||
val fragment = NewConversationFragment()
|
|
||||||
initFragment(android.R.id.content, fragment, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
dynamicTheme.onResume(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
if (item.itemId == android.R.id.home) {
|
|
||||||
onBackPressed()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun scanQRCode() {
|
|
||||||
Permissions.with(this)
|
|
||||||
.request(Manifest.permission.CAMERA)
|
|
||||||
.ifNecessary()
|
|
||||||
.withPermanentDenialDialog(getString(R.string.fragment_scan_qr_code_camera_permission_dialog_message))
|
|
||||||
.onAllGranted {
|
|
||||||
val fragment = ScanQRCodeFragment()
|
|
||||||
fragment.scanListener = this
|
|
||||||
supportFragmentManager.beginTransaction().replace(android.R.id.content, fragment).addToBackStack(null).commitAllowingStateLoss()
|
|
||||||
}
|
|
||||||
.onAnyDenied { Toast.makeText(this, R.string.fragment_scan_qr_code_camera_permission_dialog_message, Toast.LENGTH_SHORT).show() }
|
|
||||||
.execute()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onQrDataFound(hexEncodedPublicKey: String) {
|
|
||||||
Analytics.shared.track("QR Code Scanned")
|
|
||||||
startNewConversationIfPossible(hexEncodedPublicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun startNewConversationIfPossible(hexEncodedPublicKey: String) {
|
|
||||||
if (!PublicKeyValidation.isValid(hexEncodedPublicKey)) { return Toast.makeText(this, R.string.fragment_new_conversation_invalid_public_key_message, Toast.LENGTH_SHORT).show() }
|
|
||||||
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this)
|
|
||||||
// If we try to contact our master device then redirect to note to self
|
|
||||||
val contactPublicKey = if (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == hexEncodedPublicKey) userHexEncodedPublicKey else hexEncodedPublicKey
|
|
||||||
val contact = Recipient.from(this, Address.fromSerialized(contactPublicKey), true)
|
|
||||||
val intent = Intent(this, ConversationActivity::class.java)
|
|
||||||
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, contact.address)
|
|
||||||
intent.putExtra(ConversationActivity.TEXT_EXTRA, getIntent().getStringExtra(ConversationActivity.TEXT_EXTRA))
|
|
||||||
intent.setDataAndType(getIntent().data, getIntent().type)
|
|
||||||
val existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(contact)
|
|
||||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread)
|
|
||||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT)
|
|
||||||
Analytics.shared.track("New Conversation Started")
|
|
||||||
startActivity(intent)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.support.v4.app.Fragment
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import kotlinx.android.synthetic.main.fragment_new_conversation.*
|
|
||||||
import network.loki.messenger.R
|
|
||||||
|
|
||||||
class NewConversationFragment : Fragment() {
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
||||||
return inflater.inflate(R.layout.fragment_new_conversation, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
qrCodeButton.setOnClickListener {
|
|
||||||
val activity = activity as NewConversationActivity
|
|
||||||
activity.scanQRCode()
|
|
||||||
}
|
|
||||||
nextButton.setOnClickListener {
|
|
||||||
val activity = activity as NewConversationActivity
|
|
||||||
val hexEncodedPublicKey = publicKeyEditText.text.toString().trim()
|
|
||||||
activity.startNewConversationIfPossible(hexEncodedPublicKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
val activity = activity as NewConversationActivity
|
|
||||||
activity.supportActionBar!!.setTitle(R.string.fragment_new_conversation_title)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.support.v7.app.AlertDialog
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.util.DisplayMetrics
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import kotlinx.android.synthetic.main.view_qr_code.view.*
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.thoughtcrime.securesms.qr.QrCode
|
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
|
||||||
|
|
||||||
object QRCodeDialog {
|
|
||||||
|
|
||||||
fun show(context: Context) {
|
|
||||||
val view = QRCodeView(context)
|
|
||||||
val dialog = AlertDialog.Builder(context).setView(view).show()
|
|
||||||
view.onCancel = { dialog.dismiss() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class QRCodeView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : LinearLayout(context, attrs, defStyleAttr) {
|
|
||||||
var onCancel: (() -> Unit)? = null
|
|
||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
|
||||||
constructor(context: Context) : this(context, null)
|
|
||||||
|
|
||||||
init {
|
|
||||||
inflate(context, R.layout.view_qr_code, this)
|
|
||||||
val hexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(getContext()) ?: TextSecurePreferences.getLocalNumber(context)
|
|
||||||
val displayMetrics = DisplayMetrics()
|
|
||||||
ServiceUtil.getWindowManager(context).defaultDisplay.getMetrics(displayMetrics)
|
|
||||||
val size = displayMetrics.widthPixels - 2 * toPx(96, resources)
|
|
||||||
val qrCode = QrCode.create(hexEncodedPublicKey, size)
|
|
||||||
qrCodeImageView.setImageBitmap(qrCode)
|
|
||||||
cancelButton.setOnClickListener { onCancel?.invoke() }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
|
||||||
|
|
||||||
import android.content.res.Configuration
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.support.v4.app.Fragment
|
|
||||||
import android.support.v7.app.AppCompatActivity
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import kotlinx.android.synthetic.main.fragment_scan_qr_code.*
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.thoughtcrime.securesms.qr.ScanListener
|
|
||||||
import org.thoughtcrime.securesms.qr.ScanningThread
|
|
||||||
|
|
||||||
class ScanQRCodeFragment : Fragment() {
|
|
||||||
private val scanningThread = ScanningThread()
|
|
||||||
private var viewCreated = false
|
|
||||||
var scanListener: ScanListener? = null
|
|
||||||
set(value) { field = value; scanningThread.setScanListener(scanListener) }
|
|
||||||
var mode: Mode = Mode.NewConversation
|
|
||||||
set(value) { field = value; updateDescription(); }
|
|
||||||
|
|
||||||
// region Types
|
|
||||||
enum class Mode { NewConversation, LinkDevice }
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
override fun onCreateView(layoutInflater: LayoutInflater, viewGroup: ViewGroup?, bundle: Bundle?): View? {
|
|
||||||
return layoutInflater.inflate(R.layout.fragment_scan_qr_code, viewGroup, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, bundle: Bundle?) {
|
|
||||||
super.onViewCreated(view, bundle)
|
|
||||||
viewCreated = true
|
|
||||||
when (resources.configuration.orientation) {
|
|
||||||
Configuration.ORIENTATION_LANDSCAPE -> overlayView.orientation = LinearLayout.HORIZONTAL
|
|
||||||
else -> overlayView.orientation = LinearLayout.VERTICAL
|
|
||||||
}
|
|
||||||
updateDescription()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
this.scanningThread.setScanListener(scanListener)
|
|
||||||
this.cameraView.onResume()
|
|
||||||
this.cameraView.setPreviewCallback(scanningThread)
|
|
||||||
this.scanningThread.start()
|
|
||||||
if (activity is AppCompatActivity) {
|
|
||||||
val activity = activity as AppCompatActivity
|
|
||||||
activity.supportActionBar?.setTitle(R.string.fragment_scan_qr_code_title)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
this.cameraView.onPause()
|
|
||||||
this.scanningThread.stopScanning()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfiguration: Configuration) {
|
|
||||||
super.onConfigurationChanged(newConfiguration)
|
|
||||||
this.cameraView.onPause()
|
|
||||||
when (newConfiguration.orientation) {
|
|
||||||
Configuration.ORIENTATION_LANDSCAPE -> overlayView.orientation = LinearLayout.HORIZONTAL
|
|
||||||
else -> overlayView.orientation = LinearLayout.VERTICAL
|
|
||||||
}
|
|
||||||
cameraView.onResume()
|
|
||||||
cameraView.setPreviewCallback(scanningThread)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateDescription() {
|
|
||||||
if (!viewCreated) { return }
|
|
||||||
val text = when (mode) {
|
|
||||||
Mode.NewConversation -> R.string.fragment_scan_qr_code_explanation_new_conversation
|
|
||||||
Mode.LinkDevice -> R.string.fragment_scan_qr_code_explanation_link_device
|
|
||||||
}
|
|
||||||
descriptionTextView.setText(text)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,273 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.AsyncTask
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.support.v4.app.FragmentManager
|
|
||||||
import android.view.View
|
|
||||||
import android.view.inputmethod.InputMethodManager
|
|
||||||
import android.widget.Toast
|
|
||||||
import kotlinx.android.synthetic.main.activity_seed.*
|
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
|
||||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
|
||||||
import org.thoughtcrime.securesms.ConversationListActivity
|
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
|
||||||
import org.thoughtcrime.securesms.database.Address
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
|
||||||
import org.thoughtcrime.securesms.database.IdentityDatabase
|
|
||||||
import org.thoughtcrime.securesms.logging.Log
|
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions
|
|
||||||
import org.thoughtcrime.securesms.qr.ScanListener
|
|
||||||
import org.thoughtcrime.securesms.util.Hex
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
|
||||||
import org.whispersystems.curve25519.Curve25519
|
|
||||||
import org.whispersystems.libsignal.util.KeyHelper
|
|
||||||
import org.whispersystems.signalservice.loki.api.PairingAuthorisation
|
|
||||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
|
||||||
import org.whispersystems.signalservice.loki.utilities.Analytics
|
|
||||||
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
|
|
||||||
import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey
|
|
||||||
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
|
|
||||||
class SeedActivity : BaseActionBarActivity(), DeviceLinkingDelegate, ScanListener {
|
|
||||||
private lateinit var languageFileDirectory: File
|
|
||||||
private var mode = Mode.Register
|
|
||||||
set(newValue) { field = newValue; updateUI() }
|
|
||||||
private var seed: ByteArray? = null
|
|
||||||
set(newValue) { field = newValue; updateMnemonic() }
|
|
||||||
private var mnemonic: String? = null
|
|
||||||
set(newValue) { field = newValue; updateMnemonicTextView() }
|
|
||||||
|
|
||||||
// region Types
|
|
||||||
enum class Mode { Register, Restore, Link }
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Lifecycle
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_seed)
|
|
||||||
setUpLanguageFileDirectory()
|
|
||||||
mnemonicEditText.input.imeOptions = mnemonicEditText.input.imeOptions or 16777216 // Always use incognito keyboard for this
|
|
||||||
updateSeed()
|
|
||||||
copyButton.setOnClickListener { copy() }
|
|
||||||
toggleRegisterModeButton.setOnClickListener { mode = Mode.Register }
|
|
||||||
toggleRestoreModeButton.setOnClickListener { mode = Mode.Restore }
|
|
||||||
toggleLinkModeButton.setOnClickListener { mode = Mode.Link }
|
|
||||||
mainButton.setOnClickListener { handleMainButtonTapped() }
|
|
||||||
scanQRButton.setOnClickListener {
|
|
||||||
Permissions.with(this)
|
|
||||||
.request(Manifest.permission.CAMERA)
|
|
||||||
.ifNecessary()
|
|
||||||
.withPermanentDenialDialog(getString(R.string.fragment_scan_qr_code_camera_permission_dialog_message))
|
|
||||||
.onAllGranted {
|
|
||||||
val fragment = ScanQRCodeFragment()
|
|
||||||
fragment.mode = ScanQRCodeFragment.Mode.LinkDevice
|
|
||||||
fragment.scanListener = this
|
|
||||||
supportFragmentManager.beginTransaction().replace(android.R.id.content, fragment).addToBackStack("QR").commitAllowingStateLoss()
|
|
||||||
publicKeyEditText.clearFocus()
|
|
||||||
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
|
||||||
inputMethodManager.hideSoftInputFromWindow(publicKeyEditText.windowToken, 0)
|
|
||||||
}
|
|
||||||
.onAnyDenied { Toast.makeText(this, R.string.fragment_scan_qr_code_camera_permission_dialog_message, Toast.LENGTH_SHORT).show() }
|
|
||||||
.execute()
|
|
||||||
}
|
|
||||||
Analytics.shared.track("Seed Screen Viewed")
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region General
|
|
||||||
private fun setUpLanguageFileDirectory() {
|
|
||||||
val languages = listOf( "english", "japanese", "portuguese", "spanish" )
|
|
||||||
val directory = File(applicationInfo.dataDir)
|
|
||||||
for (language in languages) {
|
|
||||||
val fileName = "$language.txt"
|
|
||||||
if (directory.list().contains(fileName)) { continue }
|
|
||||||
val inputStream = assets.open("mnemonic/$fileName")
|
|
||||||
val file = File(directory, fileName)
|
|
||||||
val outputStream = FileOutputStream(file)
|
|
||||||
val buffer = ByteArray(1024)
|
|
||||||
while (true) {
|
|
||||||
val count = inputStream.read(buffer)
|
|
||||||
if (count < 0) { break }
|
|
||||||
outputStream.write(buffer, 0, count)
|
|
||||||
}
|
|
||||||
inputStream.close()
|
|
||||||
outputStream.close()
|
|
||||||
}
|
|
||||||
languageFileDirectory = directory
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Updating
|
|
||||||
private fun updateSeed() {
|
|
||||||
val seed = Curve25519.getInstance(Curve25519.BEST).generateSeed(16)
|
|
||||||
try {
|
|
||||||
IdentityKeyUtil.generateIdentityKeyPair(this, seed + seed)
|
|
||||||
} catch (exception: Exception) {
|
|
||||||
return updateSeed()
|
|
||||||
}
|
|
||||||
this.seed = seed
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateUI() {
|
|
||||||
val registerModeVisibility = if (mode == Mode.Register) View.VISIBLE else View.GONE
|
|
||||||
val restoreModeVisibility = if (mode == Mode.Restore) View.VISIBLE else View.GONE
|
|
||||||
val linkModeVisibility = if (mode == Mode.Link) View.VISIBLE else View.GONE
|
|
||||||
seedExplanationTextView1.visibility = registerModeVisibility
|
|
||||||
mnemonicTextView.visibility = registerModeVisibility
|
|
||||||
copyButton.visibility = registerModeVisibility
|
|
||||||
seedExplanationTextView2.visibility = restoreModeVisibility
|
|
||||||
mnemonicEditText.visibility = restoreModeVisibility
|
|
||||||
linkExplanationTextView.visibility = linkModeVisibility
|
|
||||||
publicKeyEditText.visibility = linkModeVisibility
|
|
||||||
scanQRButton.visibility = linkModeVisibility
|
|
||||||
toggleRegisterModeButton.visibility = if (mode != Mode.Register) View.VISIBLE else View.GONE
|
|
||||||
toggleRestoreModeButton.visibility = if (mode != Mode.Restore) View.VISIBLE else View.GONE
|
|
||||||
toggleLinkModeButton.visibility = if (mode != Mode.Link) View.VISIBLE else View.GONE
|
|
||||||
val mainButtonTitleID = when (mode) {
|
|
||||||
Mode.Register -> R.string.activity_key_pair_main_button_title_1
|
|
||||||
Mode.Restore -> R.string.activity_key_pair_main_button_title_2
|
|
||||||
Mode.Link -> R.string.activity_key_pair_main_button_title_3
|
|
||||||
}
|
|
||||||
mainButton.setText(mainButtonTitleID)
|
|
||||||
if (mode == Mode.Restore) {
|
|
||||||
mnemonicEditText.requestFocus()
|
|
||||||
} else {
|
|
||||||
mnemonicEditText.clearFocus()
|
|
||||||
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
|
||||||
inputMethodManager.hideSoftInputFromWindow(mnemonicEditText.windowToken, 0)
|
|
||||||
}
|
|
||||||
if (mode == Mode.Link) {
|
|
||||||
publicKeyEditText.requestFocus()
|
|
||||||
} else {
|
|
||||||
publicKeyEditText.clearFocus()
|
|
||||||
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
|
||||||
inputMethodManager.hideSoftInputFromWindow(publicKeyEditText.windowToken, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateMnemonic() {
|
|
||||||
val hexEncodedSeed = Hex.toStringCondensed(seed)
|
|
||||||
mnemonic = MnemonicCodec(languageFileDirectory).encode(hexEncodedSeed)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateMnemonicTextView() {
|
|
||||||
mnemonicTextView.text = mnemonic!!
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Interaction
|
|
||||||
private fun copy() {
|
|
||||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
val clip = ClipData.newPlainText("Mnemonic", mnemonic)
|
|
||||||
clipboard.primaryClip = clip
|
|
||||||
Toast.makeText(this, R.string.activity_key_pair_mnemonic_copied_message, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleMainButtonTapped() {
|
|
||||||
var seed: ByteArray
|
|
||||||
when (mode) {
|
|
||||||
Mode.Register -> seed = this.seed!!
|
|
||||||
Mode.Restore -> {
|
|
||||||
val mnemonic = mnemonicEditText.text.toString()
|
|
||||||
try {
|
|
||||||
val hexEncodedSeed = MnemonicCodec(languageFileDirectory).decode(mnemonic)
|
|
||||||
seed = Hex.fromStringCondensed(hexEncodedSeed)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
val message = if (e is MnemonicCodec.DecodingError) e.description else MnemonicCodec.DecodingError.Generic.description
|
|
||||||
return Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Mode.Link -> {
|
|
||||||
val hexEncodedPublicKey = publicKeyEditText.text.trim().toString()
|
|
||||||
if (!PublicKeyValidation.isValid(hexEncodedPublicKey)) {
|
|
||||||
return Toast.makeText(this, "Invalid public key", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
seed = this.seed!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val hexEncodedSeed = Hex.toStringCondensed(seed)
|
|
||||||
IdentityKeyUtil.save(this, IdentityKeyUtil.lokiSeedKey, hexEncodedSeed)
|
|
||||||
if (seed.count() == 16) seed += seed
|
|
||||||
if (mode == Mode.Restore) {
|
|
||||||
IdentityKeyUtil.generateIdentityKeyPair(this, seed)
|
|
||||||
}
|
|
||||||
val keyPair = IdentityKeyUtil.getIdentityKeyPair(this)
|
|
||||||
val userHexEncodedPublicKey = keyPair.hexEncodedPublicKey
|
|
||||||
val registrationID = KeyHelper.generateRegistrationId(false)
|
|
||||||
TextSecurePreferences.setLocalRegistrationId(this, registrationID)
|
|
||||||
DatabaseFactory.getIdentityDatabase(this).saveIdentity(Address.fromSerialized(userHexEncodedPublicKey), keyPair.publicKey,
|
|
||||||
IdentityDatabase.VerifiedStatus.VERIFIED, true, System.currentTimeMillis(), true)
|
|
||||||
TextSecurePreferences.setLocalNumber(this, userHexEncodedPublicKey)
|
|
||||||
if (mode == Mode.Restore) {
|
|
||||||
TextSecurePreferences.setRestorationTime(this, System.currentTimeMillis())
|
|
||||||
}
|
|
||||||
when (mode) {
|
|
||||||
Mode.Register -> Analytics.shared.track("Seed Created")
|
|
||||||
Mode.Restore -> Analytics.shared.track("Seed Restored")
|
|
||||||
Mode.Link -> Analytics.shared.track("Device Linking Attempted")
|
|
||||||
}
|
|
||||||
if (mode == Mode.Link) {
|
|
||||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
|
|
||||||
TextSecurePreferences.setPromptedPushRegistration(this, true)
|
|
||||||
val masterHexEncodedPublicKey = publicKeyEditText.text.trim().toString()
|
|
||||||
val authorisation = PairingAuthorisation(masterHexEncodedPublicKey, userHexEncodedPublicKey).sign(PairingAuthorisation.Type.REQUEST, keyPair.privateKey.serialize())
|
|
||||||
if (authorisation == null) {
|
|
||||||
Log.d("Loki", "Failed to sign pairing request.")
|
|
||||||
resetForRegistration()
|
|
||||||
return Toast.makeText(application, "Couldn't start device linking process.", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
val application = ApplicationContext.getInstance(this)
|
|
||||||
application.startLongPollingIfNeeded()
|
|
||||||
application.setUpP2PAPI()
|
|
||||||
application.setUpStorageAPIIfNeeded()
|
|
||||||
DeviceLinkingDialog.show(this, DeviceLinkingView.Mode.Slave, this)
|
|
||||||
AsyncTask.execute {
|
|
||||||
retryIfNeeded(8) {
|
|
||||||
sendPairingAuthorisationMessage(this@SeedActivity, authorisation.primaryDevicePublicKey, authorisation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
startActivity(Intent(this, DisplayNameActivity::class.java))
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleDeviceLinkAuthorized(pairingAuthorisation: PairingAuthorisation) {
|
|
||||||
Analytics.shared.track("Device Linked Successfully")
|
|
||||||
if (pairingAuthorisation.secondaryDevicePublicKey == TextSecurePreferences.getLocalNumber(this)) {
|
|
||||||
TextSecurePreferences.setMasterHexEncodedPublicKey(this, pairingAuthorisation.primaryDevicePublicKey)
|
|
||||||
}
|
|
||||||
startActivity(Intent(this, ConversationListActivity::class.java))
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleDeviceLinkingDialogDismissed() {
|
|
||||||
resetForRegistration()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resetForRegistration() {
|
|
||||||
IdentityKeyUtil.delete(this, IdentityKeyUtil.lokiSeedKey)
|
|
||||||
TextSecurePreferences.removeLocalNumber(this)
|
|
||||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, false)
|
|
||||||
TextSecurePreferences.setPromptedPushRegistration(this, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onQrDataFound(data: String?) {
|
|
||||||
runOnUiThread {
|
|
||||||
if (data != null && PublicKeyValidation.isValid(data.trim())) {
|
|
||||||
publicKeyEditText.setText(data.trim())
|
|
||||||
supportFragmentManager.popBackStackImmediate("QR", FragmentManager.POP_BACK_STACK_INCLUSIVE)
|
|
||||||
handleMainButtonTapped()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ package org.thoughtcrime.securesms.loki.redesign.activities
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.devicelist.Device
|
import org.thoughtcrime.securesms.devicelist.Device
|
||||||
import org.thoughtcrime.securesms.loki.MnemonicUtilities
|
import org.thoughtcrime.securesms.loki.redesign.utilities.MnemonicUtilities
|
||||||
import org.thoughtcrime.securesms.util.AsyncLoader
|
import org.thoughtcrime.securesms.util.AsyncLoader
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.signalservice.loki.api.LokiStorageAPI
|
import org.whispersystems.signalservice.loki.api.LokiStorageAPI
|
||||||
|
@ -12,7 +12,7 @@ import android.widget.LinearLayout
|
|||||||
import kotlinx.android.synthetic.main.dialog_link_device_master_mode.view.*
|
import kotlinx.android.synthetic.main.dialog_link_device_master_mode.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.loki.MnemonicUtilities
|
import org.thoughtcrime.securesms.loki.redesign.utilities.MnemonicUtilities
|
||||||
import org.thoughtcrime.securesms.loki.redesign.utilities.QRCodeUtilities
|
import org.thoughtcrime.securesms.loki.redesign.utilities.QRCodeUtilities
|
||||||
import org.thoughtcrime.securesms.loki.toPx
|
import org.thoughtcrime.securesms.loki.toPx
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
|
@ -12,7 +12,7 @@ import android.view.View
|
|||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import kotlinx.android.synthetic.main.dialog_link_device_slave_mode.view.*
|
import kotlinx.android.synthetic.main.dialog_link_device_slave_mode.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.loki.MnemonicUtilities
|
import org.thoughtcrime.securesms.loki.redesign.utilities.MnemonicUtilities
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.thoughtcrime.securesms.util.Util
|
import org.thoughtcrime.securesms.util.Util
|
||||||
import org.whispersystems.signalservice.loki.api.DeviceLinkingSession
|
import org.whispersystems.signalservice.loki.api.DeviceLinkingSession
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
package org.thoughtcrime.securesms.loki.redesign.messaging
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
@ -1,4 +1,4 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
package org.thoughtcrime.securesms.loki.redesign.messaging
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
@ -1,4 +1,4 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
package org.thoughtcrime.securesms.loki.redesign.messaging
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
@ -1,4 +1,4 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
package org.thoughtcrime.securesms.loki.redesign.messaging
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Handler
|
import android.os.Handler
|
@ -1,4 +1,4 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
package org.thoughtcrime.securesms.loki.redesign.utilities
|
||||||
|
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import net.sqlcipher.Cursor
|
import net.sqlcipher.Cursor
|
@ -1,4 +1,4 @@
|
|||||||
package org.thoughtcrime.securesms.loki
|
package org.thoughtcrime.securesms.loki.redesign.utilities
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
@ -9,7 +9,7 @@ import android.widget.LinearLayout
|
|||||||
import kotlinx.android.synthetic.main.view_conversation.view.*
|
import kotlinx.android.synthetic.main.view_conversation.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
import org.thoughtcrime.securesms.loki.LokiAPIUtilities.populateUserHexEncodedPublicKeyCacheIfNeeded
|
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIUtilities.populateUserHexEncodedPublicKeyCacheIfNeeded
|
||||||
import org.thoughtcrime.securesms.loki.redesign.utilities.MentionUtilities.highlightMentions
|
import org.thoughtcrime.securesms.loki.redesign.utilities.MentionUtilities.highlightMentions
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.util.DateUtils
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
|
@ -20,10 +20,8 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
|
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
|
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
import org.thoughtcrime.securesms.loki.MnemonicUtilities;
|
import org.thoughtcrime.securesms.loki.redesign.utilities.MnemonicUtilities;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
Loading…
Reference in New Issue
Block a user