Merge branch 'dev' of github.com:loki-project/loki-messenger-android into private-group-chat

pull/60/head
Niels Andriesse 5 years ago
commit 155c7f2b12

@ -6,7 +6,6 @@ buildscript {
ext.kovenant_version = "3.3.0" ext.kovenant_version = "3.3.0"
ext.identicon_version = "v11" ext.identicon_version = "v11"
ext.rss_parser_version = "2.0.4" ext.rss_parser_version = "2.0.4"
ext.mixpanel_version = "5.+"
ext.crashlytics_version = "2.10.1" ext.crashlytics_version = "2.10.1"
repositories { repositories {
@ -196,7 +195,6 @@ dependencies {
implementation "nl.komponents.kovenant:kovenant-android:$kovenant_version" implementation "nl.komponents.kovenant:kovenant-android:$kovenant_version"
implementation "com.github.lelloman:android-identicons:$identicon_version" implementation "com.github.lelloman:android-identicons:$identicon_version"
implementation "com.prof.rssparser:rssparser:$rss_parser_version" implementation "com.prof.rssparser:rssparser:$rss_parser_version"
implementation "com.mixpanel.android:mixpanel-android:$mixpanel_version"
implementation("com.crashlytics.sdk.android:crashlytics:$crashlytics_version@aar") { implementation("com.crashlytics.sdk.android:crashlytics:$crashlytics_version@aar") {
transitive = true transitive = true
} }
@ -237,10 +235,10 @@ android {
project.ext.set("archivesBaseName", "Signal") project.ext.set("archivesBaseName", "Signal")
buildConfigField "long", "BUILD_TIMESTAMP", getLastCommitTimestamp() + "L" buildConfigField "long", "BUILD_TIMESTAMP", getLastCommitTimestamp() + "L"
buildConfigField "String", "SIGNAL_URL", "\"https://textsecure-service.whispersystems.org\"" buildConfigField "String", "SIGNAL_URL", "\"\""
buildConfigField "String", "SIGNAL_CDN_URL", "\"https://cdn.signal.org\"" buildConfigField "String", "SIGNAL_CDN_URL", "\"\""
buildConfigField "String", "SIGNAL_CONTACT_DISCOVERY_URL", "\"https://api.directory.signal.org\"" buildConfigField "String", "SIGNAL_CONTACT_DISCOVERY_URL", "\"\""
buildConfigField "String", "SIGNAL_SERVICE_STATUS_URL", "\"uptime.signal.org\"" buildConfigField "String", "SIGNAL_SERVICE_STATUS_URL", "\"\""
buildConfigField "String", "CONTENT_PROXY_HOST", "\"contentproxy.signal.org\"" buildConfigField "String", "CONTENT_PROXY_HOST", "\"contentproxy.signal.org\""
buildConfigField "int", "CONTENT_PROXY_PORT", "443" buildConfigField "int", "CONTENT_PROXY_PORT", "443"
buildConfigField "String", "USER_AGENT", "\"OWA\"" buildConfigField "String", "USER_AGENT", "\"OWA\""

@ -40,7 +40,19 @@
android:id="@+id/joinPublicChatButton" android:id="@+id/joinPublicChatButton"
android:layout_width="196dp" android:layout_width="196dp"
android:layout_height="@dimen/medium_button_height" android:layout_height="@dimen/medium_button_height"
android:layout_marginBottom="@dimen/medium_spacing"
android:text="Next" /> android:text="Next" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/large_spacing"
android:layout_marginTop="@dimen/medium_spacing"
android:layout_marginRight="@dimen/large_spacing"
android:layout_marginBottom="@dimen/medium_spacing"
android:textSize="@dimen/very_small_font_size"
android:textColor="@color/text"
android:alpha="0.6"
android:textAlignment="center"
android:text="Open groups can be joined by anyone and do not provide full metadata protection" />
</LinearLayout> </LinearLayout>

@ -104,7 +104,7 @@
android:indeterminate="false" android:indeterminate="false"
android:progress="80" /> android:progress="80" />
<org.thoughtcrime.securesms.loki.SessionRestoreBannerView <org.thoughtcrime.securesms.loki.redesign.views.SessionRestoreBannerView
android:id="@+id/sessionRestoreBannerView" android:id="@+id/sessionRestoreBannerView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />

@ -22,7 +22,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/large_spacing" android:layout_marginLeft="@dimen/large_spacing"
android:layout_marginTop="@dimen/medium_spacing" android:layout_marginTop="@dimen/small_spacing"
android:layout_marginRight="@dimen/large_spacing" android:layout_marginRight="@dimen/large_spacing"
android:textSize="@dimen/small_font_size" android:textSize="@dimen/small_font_size"
android:textColor="@color/text" android:textColor="@color/text"
@ -40,7 +40,19 @@
android:id="@+id/joinPublicChatButton" android:id="@+id/joinPublicChatButton"
android:layout_width="196dp" android:layout_width="196dp"
android:layout_height="@dimen/medium_button_height" android:layout_height="@dimen/medium_button_height"
android:layout_marginBottom="@dimen/medium_spacing"
android:text="Next" /> android:text="Next" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/large_spacing"
android:layout_marginTop="@dimen/small_spacing"
android:layout_marginRight="@dimen/large_spacing"
android:layout_marginBottom="@dimen/small_spacing"
android:textSize="@dimen/very_small_font_size"
android:textColor="@color/text"
android:alpha="0.6"
android:textAlignment="center"
android:text="Open groups can be joined by anyone and do not provide full metadata protection" />
</LinearLayout> </LinearLayout>

@ -33,7 +33,6 @@ import android.support.multidex.MultiDexApplication;
import com.crashlytics.android.Crashlytics; import com.crashlytics.android.Crashlytics;
import com.google.android.gms.security.ProviderInstaller; import com.google.android.gms.security.ProviderInstaller;
import com.mixpanel.android.mpmetrics.MixpanelAPI;
import org.conscrypt.Conscrypt; import org.conscrypt.Conscrypt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -66,14 +65,14 @@ 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.redesign.messaging.BackgroundPollWorker; import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.redesign.messaging.BackgroundPublicChatPollWorker;
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.redesign.messaging.LokiRSSFeedPoller;
import org.thoughtcrime.securesms.loki.LokiUserDatabase; import org.thoughtcrime.securesms.loki.redesign.messaging.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity; import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;
import org.thoughtcrime.securesms.loki.redesign.messaging.BackgroundPollWorker;
import org.thoughtcrime.securesms.loki.redesign.messaging.BackgroundPublicChatPollWorker;
import org.thoughtcrime.securesms.loki.redesign.utilities.Broadcaster; import org.thoughtcrime.securesms.loki.redesign.utilities.Broadcaster;
import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.notifications.NotificationChannels; import org.thoughtcrime.securesms.notifications.NotificationChannels;
@ -106,11 +105,9 @@ import org.whispersystems.signalservice.loki.api.LokiPublicChat;
import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI; import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI;
import org.whispersystems.signalservice.loki.api.LokiRSSFeed; import org.whispersystems.signalservice.loki.api.LokiRSSFeed;
import org.whispersystems.signalservice.loki.api.LokiStorageAPI; import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
import org.whispersystems.signalservice.loki.utilities.Analytics;
import java.security.Security; import java.security.Security;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -119,7 +116,6 @@ import java.util.concurrent.TimeUnit;
import dagger.ObjectGraph; import dagger.ObjectGraph;
import io.fabric.sdk.android.Fabric; import io.fabric.sdk.android.Fabric;
import kotlin.Unit; import kotlin.Unit;
import kotlin.jvm.functions.Function1;
import network.loki.messenger.BuildConfig; import network.loki.messenger.BuildConfig;
import okhttp3.Cache; import okhttp3.Cache;
@ -155,7 +151,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
private LokiPublicChatAPI lokiPublicChatAPI = null; private LokiPublicChatAPI lokiPublicChatAPI = null;
public Broadcaster broadcaster = null; public Broadcaster broadcaster = null;
public SignalCommunicationModule communicationModule; public SignalCommunicationModule communicationModule;
public MixpanelAPI mixpanel;
private volatile boolean isAppVisible; private volatile boolean isAppVisible;
@ -195,14 +190,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
if (!BuildConfig.DEBUG) { if (!BuildConfig.DEBUG) {
Fabric.with(this, new Crashlytics()); Fabric.with(this, new Crashlytics());
} }
mixpanel = MixpanelAPI.getInstance(this, "59040b6707e5a1725f3fb6730fefca92");
Analytics.Companion.getShared().trackImplementation = (Function1<String, Unit>) event -> {
HashMap<String, Object> properties = new HashMap();
String configuration = BuildConfig.DEBUG ? "debug" : "production";
properties.put("configuration", configuration);
mixpanel.trackMap(event, properties);
return Unit.INSTANCE;
};
// Loki - Set the cache // Loki - Set the cache
LokiDotNetAPI.setCache(new Cache(this.getCacheDir(), OK_HTTP_CACHE_SIZE)); LokiDotNetAPI.setCache(new Cache(this.getCacheDir(), OK_HTTP_CACHE_SIZE));
// Loki - Update device mappings // Loki - Update device mappings
@ -529,7 +516,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
} }
private LokiRSSFeed lokiMessengerUpdatesFeed() { private LokiRSSFeed lokiMessengerUpdatesFeed() {
return new LokiRSSFeed("loki.network.messenger-updates.feed", "https://loki.network/category/messenger-updates/feed", "Loki Messenger Updates", false); return new LokiRSSFeed("loki.network.messenger-updates.feed", "https://loki.network/category/messenger-updates/feed", "Session Updates", false);
} }
public void createDefaultPublicChatsIfNeeded() { public void createDefaultPublicChatsIfNeeded() {
@ -576,7 +563,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
lokiNewsFeedPoller = null; lokiNewsFeedPoller = null;
}); });
} }
// The user can't delete the Loki Messenger Updates RSS feed // The user can't delete the Session Updates RSS feed
if (lokiMessengerUpdatesFeedPoller == null) { if (lokiMessengerUpdatesFeedPoller == null) {
lokiMessengerUpdatesFeedPoller = new LokiRSSFeedPoller(this, lokiMessengerUpdatesFeed()); lokiMessengerUpdatesFeedPoller = new LokiRSSFeedPoller(this, lokiMessengerUpdatesFeed());
} }

@ -51,7 +51,6 @@ import org.thoughtcrime.securesms.util.DynamicLanguage;
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.whispersystems.signalservice.loki.crypto.MnemonicCodec; import org.whispersystems.signalservice.loki.crypto.MnemonicCodec;
import org.whispersystems.signalservice.loki.utilities.Analytics;
import org.whispersystems.signalservice.loki.utilities.SerializationKt; import org.whispersystems.signalservice.loki.utilities.SerializationKt;
import java.io.File; import java.io.File;
@ -101,7 +100,6 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
if (getIntent() != null && getIntent().getCategories() != null && getIntent().getCategories().contains("android.intent.category.NOTIFICATION_PREFERENCES")) { if (getIntent() != null && getIntent().getCategories() != null && getIntent().getCategories().contains("android.intent.category.NOTIFICATION_PREFERENCES")) {
initFragment(android.R.id.content, new NotificationsPreferenceFragment()); initFragment(android.R.id.content, new NotificationsPreferenceFragment());
} else if (icicle == null) { } else if (icicle == null) {
Analytics.Companion.getShared().track("Settings Opened");
initFragment(android.R.id.content, new ApplicationPreferenceFragment()); initFragment(android.R.id.content, new ApplicationPreferenceFragment());
} }
} }
@ -325,7 +323,6 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
break; break;
*/ */
case PREFERENCE_CATEGORY_PUBLIC_KEY: case PREFERENCE_CATEGORY_PUBLIC_KEY:
Analytics.Companion.getShared().track("Public Key Shared");
String hexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(getContext()); String hexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(getContext());
if (hexEncodedPublicKey == null) { if (hexEncodedPublicKey == null) {
hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(getContext()); hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(getContext());
@ -339,7 +336,6 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
case PREFERENCE_CATEGORY_QR_CODE: break; case PREFERENCE_CATEGORY_QR_CODE: break;
case PREFERENCE_CATEGORY_LINKED_DEVICES: break; case PREFERENCE_CATEGORY_LINKED_DEVICES: break;
case PREFERENCE_CATEGORY_SEED: case PREFERENCE_CATEGORY_SEED:
Analytics.Companion.getShared().track("Seed Modal Shown");
File languageFileDirectory = new File(getContext().getApplicationInfo().dataDir); File languageFileDirectory = new File(getContext().getApplicationInfo().dataDir);
try { try {
String hexEncodedSeed = IdentityKeyUtil.retrieve(getContext(), IdentityKeyUtil.lokiSeedKey); String hexEncodedSeed = IdentityKeyUtil.retrieve(getContext(), IdentityKeyUtil.lokiSeedKey);

@ -60,7 +60,6 @@ import org.whispersystems.signalservice.api.util.StreamDetails;
import org.whispersystems.signalservice.loki.api.LokiDotNetAPI; import org.whispersystems.signalservice.loki.api.LokiDotNetAPI;
import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI; import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI;
import org.whispersystems.signalservice.loki.api.LokiStorageAPI; import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
import org.whispersystems.signalservice.loki.utilities.Analytics;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
@ -119,8 +118,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
initializeProfileAvatar(getIntent().getBooleanExtra(EXCLUDE_SYSTEM, false)); initializeProfileAvatar(getIntent().getBooleanExtra(EXCLUDE_SYSTEM, false));
ApplicationContext.getInstance(this).injectDependencies(this); ApplicationContext.getInstance(this).injectDependencies(this);
Analytics.Companion.getShared().track("Display Name Screen Viewed");
} }
@Override @Override
@ -386,8 +383,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
protected Boolean doInBackground(Void... params) { protected Boolean doInBackground(Void... params) {
Context context = CreateProfileActivity.this; Context context = CreateProfileActivity.this;
Analytics.Companion.getShared().track("Display Name Updated");
TextSecurePreferences.setProfileName(context, name); TextSecurePreferences.setProfileName(context, name);
LokiPublicChatAPI publicChatAPI = ApplicationContext.getInstance(context).getLokiPublicChatAPI(); LokiPublicChatAPI publicChatAPI = ApplicationContext.getInstance(context).getLokiPublicChatAPI();
if (publicChatAPI != null) { if (publicChatAPI != null) {

@ -25,7 +25,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.loaders.DeviceListLoader; 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.redesign.views.DeviceEditingOptionsBottomSheet;
import org.thoughtcrime.securesms.loki.redesign.utilities.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;
@ -140,7 +140,7 @@ public class DeviceListFragment extends ListFragment
final String deviceName = ((DeviceListItem)view).getDeviceName(); final String deviceName = ((DeviceListItem)view).getDeviceName();
final String deviceId = ((DeviceListItem)view).getDeviceId(); final String deviceId = ((DeviceListItem)view).getDeviceId();
DeviceListBottomSheetFragment bottomSheet = new DeviceListBottomSheetFragment(); DeviceEditingOptionsBottomSheet bottomSheet = new DeviceEditingOptionsBottomSheet();
bottomSheet.setOnEditTapped(() -> { bottomSheet.setOnEditTapped(() -> {
bottomSheet.dismiss(); bottomSheet.dismiss();
EditText deviceNameEditText = new EditText(getContext()); EditText deviceNameEditText = new EditText(getContext());

@ -149,7 +149,7 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM
Collections.sort(users); // Sort to provide a level of stability Collections.sort(users); // Sort to provide a level of stability
profilePictureView.setHexEncodedPublicKey(users.size() > 0 ? users.get(0) : ""); profilePictureView.setHexEncodedPublicKey(users.size() > 0 ? users.get(0) : "");
profilePictureView.setAdditionalHexEncodedPublicKey(users.size() > 1 ? users.get(1) : ""); profilePictureView.setAdditionalHexEncodedPublicKey(users.size() > 1 ? users.get(1) : "");
profilePictureView.setRSSFeed(name.equals("Loki News") || name.equals("Loki Messenger Updates")); profilePictureView.setRSSFeed(name.equals("Loki News") || name.equals("Session Updates"));
} else { } else {
profilePictureView.setHexEncodedPublicKey(this.number); profilePictureView.setHexEncodedPublicKey(this.number);
profilePictureView.setAdditionalHexEncodedPublicKey(null); profilePictureView.setAdditionalHexEncodedPublicKey(null);

@ -157,16 +157,16 @@ 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.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;
import org.thoughtcrime.securesms.loki.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.loki.SessionRestoreBannerView;
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity; import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIUtilities;
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.redesign.views.FriendRequestViewDelegate; import org.thoughtcrime.securesms.loki.redesign.views.FriendRequestViewDelegate;
import org.thoughtcrime.securesms.loki.redesign.views.MentionCandidateSelectionView; import org.thoughtcrime.securesms.loki.redesign.views.MentionCandidateSelectionView;
import org.thoughtcrime.securesms.loki.redesign.views.SessionRestoreBannerView;
import org.thoughtcrime.securesms.mediasend.Media; import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.mediasend.MediaSendActivity; import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
import org.thoughtcrime.securesms.mms.AttachmentManager; import org.thoughtcrime.securesms.mms.AttachmentManager;
@ -658,9 +658,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
break; break;
case PICK_GIF: case PICK_GIF:
setMedia(data.getData(), setMedia(data.getData(),
MediaType.GIF, MediaType.GIF,
data.getIntExtra(GiphyActivity.EXTRA_WIDTH, 0), data.getIntExtra(GiphyActivity.EXTRA_WIDTH, 0),
data.getIntExtra(GiphyActivity.EXTRA_HEIGHT, 0)); data.getIntExtra(GiphyActivity.EXTRA_HEIGHT, 0));
break; break;
case SMS_DEFAULT: case SMS_DEFAULT:
initializeSecurity(isSecureText, isDefaultSms); initializeSecurity(isSecureText, isDefaultSms);
@ -1935,7 +1935,16 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
case AttachmentTypeSelector.TAKE_PHOTO: case AttachmentTypeSelector.TAKE_PHOTO:
attachmentManager.capturePhoto(this, TAKE_PHOTO); break; attachmentManager.capturePhoto(this, TAKE_PHOTO); break;
case AttachmentTypeSelector.ADD_GIF: case AttachmentTypeSelector.ADD_GIF:
AttachmentManager.selectGif(this, PICK_GIF, !isSecureText); break; AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Search GIFs?");
builder.setMessage("You will not have full metadata protection when sending GIFs.");
builder.setPositiveButton("OK", (dialog, which) -> {
AttachmentManager.selectGif(this, PICK_GIF, !isSecureText);
dialog.dismiss();
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss() );
builder.create().show();
break;
} }
} }
@ -3182,7 +3191,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} else if (recipient.isMuted()) { } else if (recipient.isMuted()) {
muteIndicatorImageView.setVisibility(View.VISIBLE); muteIndicatorImageView.setVisibility(View.VISIBLE);
actionBarSubtitleTextView.setText("Muted until " + DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault())); actionBarSubtitleTextView.setText("Muted until " + DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault()));
} else if (recipient.isGroupRecipient() && recipient.getName() != null && !recipient.getName().equals("Loki Messenger Updates") && !recipient.getName().equals("Loki News")) { } else if (recipient.isGroupRecipient() && recipient.getName() != null && !recipient.getName().equals("Session Updates") && !recipient.getName().equals("Loki News")) {
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId); LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
if (publicChat != null) { if (publicChat != null) {
Integer userCount = DatabaseFactory.getLokiAPIDatabase(this).getUserCount(publicChat.getChannel(), publicChat.getServer()); Integer userCount = DatabaseFactory.getLokiAPIDatabase(this).getUserCount(publicChat.getChannel(), publicChat.getServer());

@ -801,7 +801,7 @@ public class ConversationItem extends LinearLayout
int groupThreadMargin = (int)(getResources().getDimension(R.dimen.large_spacing) + getResources().getDimension(R.dimen.small_profile_picture_size)); int groupThreadMargin = (int)(getResources().getDimension(R.dimen.large_spacing) + getResources().getDimension(R.dimen.small_profile_picture_size));
int defaultMargin = 0; int defaultMargin = 0;
String threadName = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(messageRecord.getThreadId()).getName(); String threadName = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(messageRecord.getThreadId()).getName();
boolean isRSSFeed = threadName != null && (threadName.equals("Loki News") || threadName.equals("Loki Messenger Updates")); boolean isRSSFeed = threadName != null && (threadName.equals("Loki News") || threadName.equals("Session Updates"));
layoutParams.setMarginStart((groupThread && !isRSSFeed) ? groupThreadMargin : defaultMargin); layoutParams.setMarginStart((groupThread && !isRSSFeed) ? groupThreadMargin : defaultMargin);
bodyBubble.setLayoutParams(layoutParams); bodyBubble.setLayoutParams(layoutParams);
if (profilePictureView == null) return; if (profilePictureView == null) return;
@ -983,7 +983,7 @@ public class ConversationItem extends LinearLayout
private void setAuthor(@NonNull MessageRecord current, @NonNull Optional<MessageRecord> previous, @NonNull Optional<MessageRecord> next, boolean isGroupThread) { private void setAuthor(@NonNull MessageRecord current, @NonNull Optional<MessageRecord> previous, @NonNull Optional<MessageRecord> next, boolean isGroupThread) {
String threadName = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(current.getThreadId()).getName(); String threadName = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(current.getThreadId()).getName();
boolean isRSSFeed = threadName != null && (threadName.equals("Loki News") || threadName.equals("Loki Messenger Updates")); boolean isRSSFeed = threadName != null && (threadName.equals("Loki News") || threadName.equals("Session Updates"));
if (isGroupThread && !isRSSFeed && !current.isOutgoing()) { if (isGroupThread && !isRSSFeed && !current.isOutgoing()) {
contactPhotoHolder.setVisibility(VISIBLE); contactPhotoHolder.setVisibility(VISIBLE);

@ -32,6 +32,10 @@ import org.thoughtcrime.securesms.database.helpers.ClassicOpenHelper;
import org.thoughtcrime.securesms.database.helpers.SQLCipherMigrationHelper; import org.thoughtcrime.securesms.database.helpers.SQLCipherMigrationHelper;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.loki.*; import org.thoughtcrime.securesms.loki.*;
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiPreKeyBundleDatabase;
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiPreKeyRecordDatabase;
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiUserDatabase;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
public class DatabaseFactory { public class DatabaseFactory {

@ -35,12 +35,12 @@ import org.thoughtcrime.securesms.database.StickerDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob; import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.LokiMessageDatabase; import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase;
import org.thoughtcrime.securesms.loki.LokiThreadDatabase; import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
import org.thoughtcrime.securesms.loki.LokiUserDatabase; import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiPreKeyBundleDatabase;
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiPreKeyRecordDatabase;
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiUserDatabase;
import org.thoughtcrime.securesms.notifications.NotificationChannels; import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.GroupUtil;

@ -9,9 +9,7 @@ import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DirectoryHelper;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import java.io.IOException; import java.io.IOException;
@ -67,11 +65,11 @@ public class DirectoryRefreshJob extends BaseJob {
public void onRun() throws IOException { public void onRun() throws IOException {
Log.i(TAG, "DirectoryRefreshJob.onRun()"); Log.i(TAG, "DirectoryRefreshJob.onRun()");
if (recipient == null) { // if (recipient == null) {
DirectoryHelper.refreshDirectory(context, notifyOfNewUsers); // DirectoryHelper.refreshDirectory(context, notifyOfNewUsers);
} else { // } else {
DirectoryHelper.refreshDirectoryFor(context, recipient); // DirectoryHelper.refreshDirectoryFor(context, recipient);
} // }
} }
@Override @Override

@ -70,8 +70,8 @@ import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.FriendRequestHandler; import org.thoughtcrime.securesms.loki.FriendRequestHandler;
import org.thoughtcrime.securesms.loki.redesign.messaging.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.redesign.messaging.LokiPreKeyBundleDatabase;
import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase; import org.thoughtcrime.securesms.loki.redesign.messaging.LokiPreKeyRecordDatabase;
import org.thoughtcrime.securesms.loki.LokiThreadDatabase; import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity; import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;

@ -9,7 +9,6 @@ import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
@ -56,10 +55,11 @@ public class RotateCertificateJob extends BaseJob implements InjectableType {
@Override @Override
public void onRun() throws IOException { public void onRun() throws IOException {
synchronized (RotateCertificateJob.class) { // Loki - Do nothing
byte[] certificate = accountManager.getSenderCertificate(); // synchronized (RotateCertificateJob.class) {
TextSecurePreferences.setUnidentifiedAccessCertificate(context, certificate); // byte[] certificate = accountManager.getSenderCertificate();
} // TextSecurePreferences.setUnidentifiedAccessCertificate(context, certificate);
// }
} }
@Override @Override

@ -7,11 +7,7 @@ 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.*
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
@ -67,7 +63,6 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
override fun setFriendRequestStatus(threadID: Long, friendRequestStatus: LokiThreadFriendRequestStatus) { override fun setFriendRequestStatus(threadID: Long, friendRequestStatus: LokiThreadFriendRequestStatus) {
if (threadID < 0) { return } if (threadID < 0) { return }
val database = databaseHelper.writableDatabase val database = databaseHelper.writableDatabase
val contentValues = ContentValues(2) val contentValues = ContentValues(2)
contentValues.put(Companion.threadID, threadID) contentValues.put(Companion.threadID, threadID)
@ -152,7 +147,6 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
databaseHelper.writableDatabase.delete(publicChatTableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) databaseHelper.writableDatabase.delete(publicChatTableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
} }
// region Session Restore
fun addSessionRestoreDevice(threadID: Long, hexEncodedPublicKey: String) { fun addSessionRestoreDevice(threadID: Long, hexEncodedPublicKey: String) {
val devices = getSessionRestoreDevices(threadID).toMutableSet() val devices = getSessionRestoreDevices(threadID).toMutableSet()
if (devices.add(hexEncodedPublicKey)) { if (devices.add(hexEncodedPublicKey)) {
@ -172,5 +166,4 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
TextSecurePreferences.setStringPreference(context, "session_restore_devices_$threadID", "") TextSecurePreferences.setStringPreference(context, "session_restore_devices_$threadID", "")
delegate?.handleSessionRestoreDevicesChanged(threadID) delegate?.handleSessionRestoreDevicesChanged(threadID)
} }
// endregion
} }

@ -6,12 +6,10 @@ import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.all import nl.komponents.kovenant.all
import nl.komponents.kovenant.functional.bind import nl.komponents.kovenant.functional.bind
import nl.komponents.kovenant.functional.map import nl.komponents.kovenant.functional.map
import nl.komponents.kovenant.then
import nl.komponents.kovenant.toFailVoid import nl.komponents.kovenant.toFailVoid
import nl.komponents.kovenant.ui.successUi import nl.komponents.kovenant.ui.successUi
import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.crypto.PreKeyUtil
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
import org.thoughtcrime.securesms.database.Address import org.thoughtcrime.securesms.database.Address
@ -20,14 +18,11 @@ import org.thoughtcrime.securesms.logging.Log
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.sms.MessageSender import org.thoughtcrime.securesms.sms.MessageSender
import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.libsignal.util.guava.Optional
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
import org.whispersystems.signalservice.api.push.SignalServiceAddress 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.api.PairingAuthorisation import org.whispersystems.signalservice.loki.api.PairingAuthorisation
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
import org.whispersystems.signalservice.loki.utilities.Analytics
import org.whispersystems.signalservice.loki.utilities.recover import org.whispersystems.signalservice.loki.utilities.recover
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
import java.util.* import java.util.*
@ -44,7 +39,6 @@ fun checkForRevocation(context: Context) {
DatabaseFactory.getLokiAPIDatabase(context).removePairingAuthorisations(ourDevice) DatabaseFactory.getLokiAPIDatabase(context).removePairingAuthorisations(ourDevice)
LokiStorageAPI.shared.updateUserDeviceMappings() LokiStorageAPI.shared.updateUserDeviceMappings()
}.successUi { }.successUi {
Analytics.shared.track("Secondary Device Unlinked")
TextSecurePreferences.setNeedsRevocationCheck(context, false) TextSecurePreferences.setNeedsRevocationCheck(context, false)
ApplicationContext.getInstance(context).clearData() ApplicationContext.getInstance(context).clearData()
}.fail { error -> }.fail { error ->

@ -15,7 +15,7 @@ import network.loki.messenger.R
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
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.DeviceListBottomSheetFragment import org.thoughtcrime.securesms.loki.redesign.views.DeviceEditingOptionsBottomSheet
import org.thoughtcrime.securesms.loki.redesign.dialogs.EditDeviceNameDialog import org.thoughtcrime.securesms.loki.redesign.dialogs.EditDeviceNameDialog
import org.thoughtcrime.securesms.loki.redesign.dialogs.EditDeviceNameDialogDelegate import org.thoughtcrime.securesms.loki.redesign.dialogs.EditDeviceNameDialogDelegate
import org.thoughtcrime.securesms.loki.redesign.dialogs.LinkDeviceMasterModeDialog import org.thoughtcrime.securesms.loki.redesign.dialogs.LinkDeviceMasterModeDialog
@ -104,7 +104,7 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager
} }
override fun onDeviceClick(device: Device) { override fun onDeviceClick(device: Device) {
val bottomSheet = DeviceListBottomSheetFragment() val bottomSheet = DeviceEditingOptionsBottomSheet()
bottomSheet.onEditTapped = { bottomSheet.onEditTapped = {
bottomSheet.dismiss() bottomSheet.dismiss()
val editDeviceNameDialog = EditDeviceNameDialog() val editDeviceNameDialog = EditDeviceNameDialog()

@ -12,7 +12,7 @@ import network.loki.messenger.R
import org.thoughtcrime.securesms.qr.ScanListener import org.thoughtcrime.securesms.qr.ScanListener
import org.thoughtcrime.securesms.qr.ScanningThread import org.thoughtcrime.securesms.qr.ScanningThread
class ScanQRCodeFragmentV2 : Fragment() { class ScanQRCodeFragment : Fragment() {
private val scanningThread = ScanningThread() private val scanningThread = ScanningThread()
var scanListener: ScanListener? = null var scanListener: ScanListener? = null
set(value) { field = value; scanningThread.setScanListener(scanListener) } set(value) { field = value; scanningThread.setScanListener(scanListener) }

@ -28,7 +28,7 @@ class ScanQRCodeWrapperFragment : Fragment(), ScanQRCodePlaceholderFragmentDeleg
private fun update() { private fun update() {
val fragment: Fragment val fragment: Fragment
if (ContextCompat.checkSelfPermission(activity!!, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(activity!!, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
val scanQRCodeFragment = ScanQRCodeFragmentV2() val scanQRCodeFragment = ScanQRCodeFragment()
scanQRCodeFragment.scanListener = this scanQRCodeFragment.scanListener = this
scanQRCodeFragment.message = message scanQRCodeFragment.message = message
fragment = scanQRCodeFragment fragment = scanQRCodeFragment

@ -10,7 +10,6 @@ import org.thoughtcrime.securesms.service.PersistentAlarmManagerListener
import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope
import org.whispersystems.signalservice.loki.api.LokiAPI import org.whispersystems.signalservice.loki.api.LokiAPI
import org.whispersystems.signalservice.loki.utilities.Analytics
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class BackgroundPollWorker : PersistentAlarmManagerListener() { class BackgroundPollWorker : PersistentAlarmManagerListener() {
@ -30,7 +29,6 @@ class BackgroundPollWorker : PersistentAlarmManagerListener() {
override fun onAlarm(context: Context, scheduledTime: Long): Long { override fun onAlarm(context: Context, scheduledTime: Long): Long {
if (scheduledTime != 0L) { if (scheduledTime != 0L) {
Analytics.shared.track("Performed Background Fetch")
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context) val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
val lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(context) val lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(context)
try { try {

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki package org.thoughtcrime.securesms.loki.redesign.messaging
import android.content.ContentValues import android.content.ContentValues
import android.content.Context import android.content.Context
@ -88,7 +88,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
} }
string string
} }
val row = wrap(mapOf( Companion.hexEncodedPublicKey to hexEncodedPublicKey, swarm to swarmAsString )) val row = wrap(mapOf(Companion.hexEncodedPublicKey to hexEncodedPublicKey, swarm to swarmAsString))
database.insertOrUpdate(swarmCache, row, "${Companion.hexEncodedPublicKey} = ?", wrap(hexEncodedPublicKey)) database.insertOrUpdate(swarmCache, row, "${Companion.hexEncodedPublicKey} = ?", wrap(hexEncodedPublicKey))
} }
@ -101,7 +101,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
override fun setLastMessageHashValue(target: LokiAPITarget, newValue: String) { override fun setLastMessageHashValue(target: LokiAPITarget, newValue: String) {
val database = databaseHelper.writableDatabase val database = databaseHelper.writableDatabase
val row = wrap(mapOf( Companion.target to target.address, lastMessageHashValue to newValue )) val row = wrap(mapOf(Companion.target to target.address, lastMessageHashValue to newValue))
database.insertOrUpdate(lastMessageHashValueCache, row, "${Companion.target} = ?", wrap(target.address)) database.insertOrUpdate(lastMessageHashValueCache, row, "${Companion.target} = ?", wrap(target.address))
} }
@ -116,7 +116,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
override fun setReceivedMessageHashValues(newValue: Set<String>) { override fun setReceivedMessageHashValues(newValue: Set<String>) {
val database = databaseHelper.writableDatabase val database = databaseHelper.writableDatabase
val receivedMessageHashValuesAsString = newValue.joinToString(", ") val receivedMessageHashValuesAsString = newValue.joinToString(", ")
val row = wrap(mapOf( userID to userPublicKey, receivedMessageHashValues to receivedMessageHashValuesAsString )) val row = wrap(mapOf(userID to userPublicKey, receivedMessageHashValues to receivedMessageHashValuesAsString))
database.insertOrUpdate(receivedMessageHashValuesCache, row, "$userID = ?", wrap(userPublicKey)) database.insertOrUpdate(receivedMessageHashValuesCache, row, "$userID = ?", wrap(userPublicKey))
} }
@ -148,7 +148,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
override fun setLastMessageServerID(group: Long, server: String, newValue: Long) { override fun setLastMessageServerID(group: Long, server: String, newValue: Long) {
val database = databaseHelper.writableDatabase val database = databaseHelper.writableDatabase
val index = "$server.$group" val index = "$server.$group"
val row = wrap(mapOf( lastMessageServerIDCacheIndex to index, lastMessageServerID to newValue.toString() )) val row = wrap(mapOf(lastMessageServerIDCacheIndex to index, lastMessageServerID to newValue.toString()))
database.insertOrUpdate(lastMessageServerIDCache, row, "$lastMessageServerIDCacheIndex = ?", wrap(index)) database.insertOrUpdate(lastMessageServerIDCache, row, "$lastMessageServerIDCacheIndex = ?", wrap(index))
} }
@ -169,7 +169,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
override fun setLastDeletionServerID(group: Long, server: String, newValue: Long) { override fun setLastDeletionServerID(group: Long, server: String, newValue: Long) {
val database = databaseHelper.writableDatabase val database = databaseHelper.writableDatabase
val index = "$server.$group" val index = "$server.$group"
val row = wrap(mapOf( lastDeletionServerIDCacheIndex to index, lastDeletionServerID to newValue.toString() )) val row = wrap(mapOf(lastDeletionServerIDCacheIndex to index, lastDeletionServerID to newValue.toString()))
database.insertOrUpdate(lastDeletionServerIDCache, row, "$lastDeletionServerIDCacheIndex = ?", wrap(index)) database.insertOrUpdate(lastDeletionServerIDCache, row, "$lastDeletionServerIDCacheIndex = ?", wrap(index))
} }
@ -221,7 +221,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
override fun setUserCount(userCount: Int, group: Long, server: String) { override fun setUserCount(userCount: Int, group: Long, server: String) {
val database = databaseHelper.writableDatabase val database = databaseHelper.writableDatabase
val index = "$server.$group" val index = "$server.$group"
val row = wrap(mapOf( publicChatID to index, LokiAPIDatabase.userCount to userCount.toString() )) val row = wrap(mapOf(publicChatID to index, Companion.userCount to userCount.toString()))
database.insertOrUpdate(userCountCache, row, "$publicChatID = ?", wrap(index)) database.insertOrUpdate(userCountCache, row, "$publicChatID = ?", wrap(index))
} }
} }

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki package org.thoughtcrime.securesms.loki.redesign.messaging
import android.content.ContentValues import android.content.ContentValues
import android.content.Context import android.content.Context

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki package org.thoughtcrime.securesms.loki.redesign.messaging
import android.content.ContentValues import android.content.ContentValues
import android.content.Context import android.content.Context

@ -120,33 +120,33 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
val attachments = message.attachments.mapNotNull { attachment -> val attachments = message.attachments.mapNotNull { attachment ->
if (attachment.kind != LokiPublicChatMessage.Attachment.Kind.Attachment) { return@mapNotNull null } if (attachment.kind != LokiPublicChatMessage.Attachment.Kind.Attachment) { return@mapNotNull null }
SignalServiceAttachmentPointer( SignalServiceAttachmentPointer(
attachment.serverID, attachment.serverID,
attachment.contentType, attachment.contentType,
ByteArray(0), ByteArray(0),
Optional.of(attachment.size), Optional.of(attachment.size),
Optional.absent(), Optional.absent(),
attachment.width, attachment.height, attachment.width, attachment.height,
Optional.absent(), Optional.absent(),
Optional.of(attachment.fileName), Optional.of(attachment.fileName),
false, false,
Optional.fromNullable(attachment.caption), Optional.fromNullable(attachment.caption),
attachment.url) attachment.url)
} }
val linkPreview = message.attachments.firstOrNull { it.kind == LokiPublicChatMessage.Attachment.Kind.LinkPreview } val linkPreview = message.attachments.firstOrNull { it.kind == LokiPublicChatMessage.Attachment.Kind.LinkPreview }
val signalLinkPreviews = mutableListOf<SignalServiceDataMessage.Preview>() val signalLinkPreviews = mutableListOf<SignalServiceDataMessage.Preview>()
if (linkPreview != null) { if (linkPreview != null) {
val attachment = SignalServiceAttachmentPointer( val attachment = SignalServiceAttachmentPointer(
linkPreview.serverID, linkPreview.serverID,
linkPreview.contentType, linkPreview.contentType,
ByteArray(0), ByteArray(0),
Optional.of(linkPreview.size), Optional.of(linkPreview.size),
Optional.absent(), Optional.absent(),
linkPreview.width, linkPreview.height, linkPreview.width, linkPreview.height,
Optional.absent(), Optional.absent(),
Optional.of(linkPreview.fileName), Optional.of(linkPreview.fileName),
false, false,
Optional.fromNullable(linkPreview.caption), Optional.fromNullable(linkPreview.caption),
linkPreview.url) linkPreview.url)
signalLinkPreviews.add(SignalServiceDataMessage.Preview(linkPreview.linkPreviewURL!!, linkPreview.linkPreviewTitle!!, Optional.of(attachment))) signalLinkPreviews.add(SignalServiceDataMessage.Preview(linkPreview.linkPreviewURL!!, linkPreview.linkPreviewTitle!!, Optional.of(attachment)))
} }
val body = if (message.body == message.timestamp.toString()) "" else message.body // Workaround for the fact that the back-end doesn't accept messages without a body val body = if (message.body == message.timestamp.toString()) "" else message.body // Workaround for the fact that the back-end doesn't accept messages without a body
@ -161,7 +161,6 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
val senderDisplayName = "${message.displayName} (...${message.hexEncodedPublicKey.takeLast(8)})" val senderDisplayName = "${message.displayName} (...${message.hexEncodedPublicKey.takeLast(8)})"
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.hexEncodedPublicKey, senderDisplayName) DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.hexEncodedPublicKey, senderDisplayName)
} }
val senderPublicKey = primaryDevice ?: message.hexEncodedPublicKey val senderPublicKey = primaryDevice ?: message.hexEncodedPublicKey
val serviceDataMessage = getDataMessage(message) val serviceDataMessage = getDataMessage(message)
val serviceContent = SignalServiceContent(serviceDataMessage, senderPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.timestamp, false, false) val serviceContent = SignalServiceContent(serviceDataMessage, senderPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.timestamp, false, false)
@ -170,7 +169,6 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
} else { } else {
PushDecryptJob(context).handleTextMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID)) PushDecryptJob(context).handleTextMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
} }
// Update profile avatar if needed // Update profile avatar if needed
val senderRecipient = Recipient.from(context, Address.fromSerialized(senderPublicKey), false) val senderRecipient = Recipient.from(context, Address.fromSerialized(senderPublicKey), false)
if (message.avatar != null && message.avatar!!.url.isNotEmpty()) { if (message.avatar != null && message.avatar!!.url.isNotEmpty()) {
@ -204,8 +202,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
} else { } else {
PushDecryptJob(context).handleSynchronizeSentTextMessage(transcript) PushDecryptJob(context).handleSynchronizeSentTextMessage(transcript)
} }
// If we got a message from our master device then make sure our mappings stay in sync
// Loki - If we got a message from our master device then make sure our mappings stay in sync
val recipient = Recipient.from(context, Address.fromSerialized(message.hexEncodedPublicKey), false) val recipient = Recipient.from(context, Address.fromSerialized(message.hexEncodedPublicKey), false)
if (recipient.isOurMasterDevice && message.avatar != null) { if (recipient.isOurMasterDevice && message.avatar != null) {
val profileKey = message.avatar!!.profileKey val profileKey = message.avatar!!.profileKey

@ -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.messaging
import android.content.ContentValues import android.content.ContentValues
import android.content.Context import android.content.Context
@ -18,7 +18,6 @@ class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database
companion object { companion object {
// Shared // Shared
private val displayName = "display_name" private val displayName = "display_name"
private val profileAvatarUrl = "profile_avatar_url"
// Display name cache // Display name cache
private val displayNameTable = "loki_user_display_name_database" private val displayNameTable = "loki_user_display_name_database"
private val hexEncodedPublicKey = "hex_encoded_public_key" private val hexEncodedPublicKey = "hex_encoded_public_key"
@ -70,7 +69,7 @@ class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database
} }
} }
override fun getProfileAvatarUrl(hexEncodedPublicKey: String): String? { override fun getProfilePictureURL(hexEncodedPublicKey: String): String? {
return if (hexEncodedPublicKey == TextSecurePreferences.getLocalNumber(context)) { return if (hexEncodedPublicKey == TextSecurePreferences.getLocalNumber(context)) {
TextSecurePreferences.getProfileAvatarUrl(context) TextSecurePreferences.getProfileAvatarUrl(context)
} else { } else {

@ -53,7 +53,7 @@ class ConversationView : LinearLayout {
val randomUsers = users.sorted() // Sort to provide a level of stability val randomUsers = users.sorted() // Sort to provide a level of stability
profilePictureView.hexEncodedPublicKey = randomUsers.getOrNull(0) ?: "" profilePictureView.hexEncodedPublicKey = randomUsers.getOrNull(0) ?: ""
profilePictureView.additionalHexEncodedPublicKey = randomUsers.getOrNull(1) ?: "" profilePictureView.additionalHexEncodedPublicKey = randomUsers.getOrNull(1) ?: ""
profilePictureView.isRSSFeed = thread.recipient.name == "Loki News" || thread.recipient.name == "Loki Messenger Updates" profilePictureView.isRSSFeed = thread.recipient.name == "Loki News" || thread.recipient.name == "Session Updates"
} else { } else {
profilePictureView.hexEncodedPublicKey = thread.recipient.address.toString() profilePictureView.hexEncodedPublicKey = thread.recipient.address.toString()
profilePictureView.additionalHexEncodedPublicKey = null profilePictureView.additionalHexEncodedPublicKey = null

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki package org.thoughtcrime.securesms.loki.redesign.views
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.BottomSheetDialogFragment import android.support.design.widget.BottomSheetDialogFragment
@ -8,7 +8,7 @@ import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_device_list_bottom_sheet.* 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 DeviceEditingOptionsBottomSheet : BottomSheetDialogFragment() {
var onEditTapped: (() -> Unit)? = null var onEditTapped: (() -> Unit)? = null
var onUnlinkTapped: (() -> Unit)? = null var onUnlinkTapped: (() -> Unit)? = null

@ -61,7 +61,7 @@ class ProfilePictureView : RelativeLayout {
glide.clear(imageView) glide.clear(imageView)
if (hexEncodedPublicKey.isNotEmpty()) { if (hexEncodedPublicKey.isNotEmpty()) {
val signalProfilePicture = Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false).contactPhoto val signalProfilePicture = Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false).contactPhoto
if (signalProfilePicture != null && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "0") { if (signalProfilePicture != null && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "0" && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "") {
glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView) glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView)
} else { } else {
val size = resources.getDimensionPixelSize(sizeID) val size = resources.getDimensionPixelSize(sizeID)

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki package org.thoughtcrime.securesms.loki.redesign.views
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet

@ -24,7 +24,6 @@ import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.CommunicationActions; import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.loki.utilities.Analytics;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -127,12 +126,6 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean enabled = (Boolean)newValue; boolean enabled = (Boolean)newValue;
if (enabled) {
Analytics.Companion.getShared().track("Screen Lock Enabled");
} else {
Analytics.Companion.getShared().track("Screen Lock Disabled");
}
TextSecurePreferences.setScreenLockEnabled(getContext(), enabled); TextSecurePreferences.setScreenLockEnabled(getContext(), enabled);
Intent intent = new Intent(getContext(), KeyCachingService.class); Intent intent = new Intent(getContext(), KeyCachingService.class);
@ -203,12 +196,6 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean enabled = (boolean)newValue; boolean enabled = (boolean)newValue;
if (enabled) {
Analytics.Companion.getShared().track("Typing Indicators Enabled");
} else {
Analytics.Companion.getShared().track("Typing Indicators Disabled");
}
ApplicationContext.getInstance(getContext()) ApplicationContext.getInstance(getContext())
.getJobManager() .getJobManager()
.add(new MultiDeviceConfigurationUpdateJob(TextSecurePreferences.isReadReceiptsEnabled(requireContext()), .add(new MultiDeviceConfigurationUpdateJob(TextSecurePreferences.isReadReceiptsEnabled(requireContext()),
@ -230,9 +217,22 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
boolean enabled = (boolean)newValue; boolean enabled = (boolean)newValue;
if (enabled) { if (enabled) {
Analytics.Companion.getShared().track("Link Previews Enabled"); AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
} else { builder.setTitle("Enable Link Previews?");
Analytics.Companion.getShared().track("Link Previews Disabled"); builder.setMessage("You will not have full metadata protection when sending or receiving link previews.");
builder.setPositiveButton("OK", (dialog, which) -> dialog.dismiss());
builder.setNegativeButton("Cancel", (dialog, which) -> {
TextSecurePreferences.setLinkPreviewsEnabled(requireContext(), false);
((SwitchPreferenceCompat)AppProtectionPreferenceFragment.this.findPreference(TextSecurePreferences.LINK_PREVIEWS)).setChecked(false);
ApplicationContext.getInstance(requireContext())
.getJobManager()
.add(new MultiDeviceConfigurationUpdateJob(TextSecurePreferences.isReadReceiptsEnabled(requireContext()),
TextSecurePreferences.isTypingIndicatorsEnabled(requireContext()),
TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(requireContext()),
false));
dialog.dismiss();
});
builder.create().show();
} }
ApplicationContext.getInstance(requireContext()) ApplicationContext.getInstance(requireContext())

@ -11,7 +11,6 @@ import org.thoughtcrime.securesms.BaseActionBarActivity;
import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.util.CommunicationActions; import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.loki.utilities.Analytics;
import network.loki.messenger.R; import network.loki.messenger.R;
@ -23,7 +22,6 @@ public class WelcomeActivity extends BaseActionBarActivity {
setContentView(R.layout.registration_welcome_activity); setContentView(R.layout.registration_welcome_activity);
findViewById(R.id.welcome_terms_button).setOnClickListener(v -> onTermsClicked()); findViewById(R.id.welcome_terms_button).setOnClickListener(v -> onTermsClicked());
findViewById(R.id.welcome_continue_button).setOnClickListener(v -> onContinueClicked()); findViewById(R.id.welcome_continue_button).setOnClickListener(v -> onContinueClicked());
Analytics.Companion.getShared().track("Landing Screen Viewed");
} }
@Override @Override

@ -367,7 +367,11 @@ public class TextSecurePreferences {
} }
public static boolean isLinkPreviewsEnabled(Context context) { public static boolean isLinkPreviewsEnabled(Context context) {
return getBooleanPreference(context, LINK_PREVIEWS, true); return getBooleanPreference(context, LINK_PREVIEWS, false);
}
public static void setLinkPreviewsEnabled(Context context, boolean enabled) {
setBooleanPreference(context, LINK_PREVIEWS, enabled);
} }
public static boolean isGifSearchInGridLayout(Context context) { public static boolean isGifSearchInGridLayout(Context context) {

Loading…
Cancel
Save