mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-22 07:57:30 +00:00
Merge branch 'dev'
This commit is contained in:
commit
4001714705
1
.gitignore
vendored
1
.gitignore
vendored
@ -26,3 +26,4 @@ jni/libspeex/.deps/
|
||||
pkcs11.password
|
||||
fabric.properties
|
||||
play
|
||||
google-services.json
|
||||
|
@ -16,12 +16,6 @@
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth"
|
||||
android:required="false" />
|
||||
<!--
|
||||
Loki - Enable again once we have location sharing
|
||||
<uses-feature android:name="android.hardware.location" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.location.network" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.location.gps" android:required="false"/>
|
||||
-->
|
||||
<uses-feature
|
||||
android:name="android.hardware.microphone"
|
||||
android:required="false" />
|
||||
@ -56,8 +50,6 @@
|
||||
<!-- For conversation 'shortcuts' on the desktop -->
|
||||
<uses-permission android:name="android.permission.INSTALL_SHORTCUT" />
|
||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||
<!-- Set image as wallpaper -->
|
||||
<uses-permission android:name="android.permission.SET_WALLPAPER" />
|
||||
|
||||
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
|
||||
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
||||
@ -96,62 +88,62 @@
|
||||
|
||||
<!-- Session -->
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.LandingActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.LandingActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.RegisterActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.RegisterActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.RestoreActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.RestoreActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.LinkDeviceActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.LinkDeviceActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.DisplayNameActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.DisplayNameActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.PNModeActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.PNModeActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.HomeActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/Session.DarkTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.SettingsActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.SettingsActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Session.DarkTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.QRCodeActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.QRCodeActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.CreatePrivateChatActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.CreatePrivateChatActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.CreateClosedGroupActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.CreateClosedGroupActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.JoinPublicChatActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.JoinPublicChatActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.SeedActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.SeedActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.PrivacySettingsActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.PrivacySettingsActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.NotificationSettingsActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.NotificationSettingsActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.ChatSettingsActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.ChatSettingsActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.LinkedDevicesActivity"
|
||||
android:name="org.thoughtcrime.securesms.loki.activities.LinkedDevicesActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<!-- Session -->
|
||||
<activity
|
||||
@ -166,7 +158,7 @@
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.InviteActivity"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||
android:parentActivityName="org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity"
|
||||
android:parentActivityName="org.thoughtcrime.securesms.loki.activities.HomeActivity"
|
||||
android:theme="@style/TextSecure.HighlightTheme"
|
||||
android:windowSoftInputMode="stateHidden">
|
||||
<meta-data
|
||||
@ -225,7 +217,7 @@
|
||||
<activity-alias
|
||||
android:name=".RoutingActivity"
|
||||
android:exported="true"
|
||||
android:targetActivity="org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity">
|
||||
android:targetActivity="org.thoughtcrime.securesms.loki.activities.HomeActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@ -264,7 +256,7 @@
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||
android:label="@string/AndroidManifest_archived_conversations"
|
||||
android:launchMode="singleTask"
|
||||
android:parentActivityName="org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity">
|
||||
android:parentActivityName="org.thoughtcrime.securesms.loki.activities.HomeActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="PsiClass:HomeActivity" />
|
||||
@ -275,7 +267,7 @@
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Session.DarkTheme.NoActionBar"
|
||||
android:parentActivityName="org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity"
|
||||
android:parentActivityName="org.thoughtcrime.securesms.loki.activities.HomeActivity"
|
||||
android:windowSoftInputMode="stateUnchanged">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
@ -514,7 +506,7 @@
|
||||
android:exported="true"
|
||||
android:theme="@style/TextSecure.LightNoActionBar" />
|
||||
<service
|
||||
android:name="org.thoughtcrime.securesms.service.PushNotificationService"
|
||||
android:name="org.thoughtcrime.securesms.loki.api.PushNotificationService"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
@ -673,12 +665,12 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<!-- Session -->
|
||||
<receiver android:name="org.thoughtcrime.securesms.loki.redesign.messaging.BackgroundPollWorker">
|
||||
<receiver android:name="org.thoughtcrime.securesms.loki.api.BackgroundPollWorker">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name="org.thoughtcrime.securesms.loki.redesign.messaging.BackgroundOpenGroupPollWorker">
|
||||
<receiver android:name="org.thoughtcrime.securesms.loki.api.BackgroundOpenGroupPollWorker">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
|
@ -190,8 +190,8 @@ dependencies {
|
||||
implementation "com.github.ybq:Android-SpinKit:1.4.0"
|
||||
}
|
||||
|
||||
def canonicalVersionCode = 49
|
||||
def canonicalVersionName = "1.1.0"
|
||||
def canonicalVersionCode = 50
|
||||
def canonicalVersionName = "1.2.0"
|
||||
|
||||
def postFixSize = 10
|
||||
def abiPostFix = ['armeabi-v7a' : 1,
|
||||
|
@ -21,7 +21,7 @@
|
||||
android:textColor="@color/text"
|
||||
android:text="Your Session begins here..." />
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.FakeChatView
|
||||
<org.thoughtcrime.securesms.loki.views.FakeChatView
|
||||
android:id="@+id/fakeChatView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/fake_chat_view_height"
|
||||
|
@ -7,7 +7,7 @@
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.SeedReminderView
|
||||
<org.thoughtcrime.securesms.loki.views.SeedReminderView
|
||||
android:id="@+id/seedReminderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
@ -30,7 +30,7 @@
|
||||
android:textAlignment="center"
|
||||
android:text="Users can share their Session ID by going into their account settings and tapping "Share Session ID", or by sharing their QR code." />
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.LabeledSeparatorView
|
||||
<org.thoughtcrime.securesms.loki.views.LabeledSeparatorView
|
||||
android:id="@+id/separatorView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="32dp"
|
||||
|
75
res/layout-sw400dp/view_seed_reminder.xml
Normal file
75
res/layout-sw400dp/view_seed_reminder.xml
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/cell_background"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ProgressBar
|
||||
style="@android:style/Widget.ProgressBar.Horizontal"
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/accent_line_thickness"
|
||||
android:paddingLeft="-2dp"
|
||||
android:paddingRight="-2dp"
|
||||
android:progressTint="@color/accent"
|
||||
android:progressBackgroundTint="@color/progress_bar_background"
|
||||
android:progress="80" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="@dimen/medium_spacing"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/titleTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/text"
|
||||
android:textSize="@dimen/small_font_size"
|
||||
android:textStyle="bold"
|
||||
android:text="You're almost finished! 80%" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subtitleTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textColor="@color/text"
|
||||
android:textSize="@dimen/very_small_font_size"
|
||||
android:alpha="0.6"
|
||||
android:text="Secure your account by saving your recovery phrase" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginLeft="4dp" />
|
||||
|
||||
<Button
|
||||
style="@style/MediumProminentOutlineButton"
|
||||
android:id="@+id/button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:textStyle="normal"
|
||||
android:text="Continue" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/separator" />
|
||||
|
||||
</LinearLayout>
|
@ -25,7 +25,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginRight="@dimen/very_large_spacing"
|
||||
android:textSize="@dimen/small_font_size"
|
||||
android:textColor="@color/text"
|
||||
@ -37,7 +37,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="@dimen/very_large_spacing"
|
||||
android:hint="Enter a display name" />
|
||||
|
||||
|
@ -21,11 +21,11 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.ProfilePictureView
|
||||
<org.thoughtcrime.securesms.loki.views.ProfilePictureView
|
||||
android:id="@+id/profileButton"
|
||||
android:layout_width="@dimen/small_profile_picture_size"
|
||||
android:layout_height="@dimen/small_profile_picture_size"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginLeft="9dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true" />
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
|
||||
</android.support.v7.widget.Toolbar>
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.SeedReminderView
|
||||
<org.thoughtcrime.securesms.loki.views.SeedReminderView
|
||||
android:id="@+id/seedReminderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
@ -66,13 +66,39 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/home_activity_gradient" />
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.NewConversationButtonSetView
|
||||
<org.thoughtcrime.securesms.loki.views.NewConversationButtonSetView
|
||||
android:id="@+id/newConversationButtonSet"
|
||||
android:layout_width="252dp"
|
||||
android:layout_height="212dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_alignParentBottom="true" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/emptyStateContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="32dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:layout_centerInParent="true">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/medium_font_size"
|
||||
android:textColor="@color/text"
|
||||
android:text="You don't have any contacts yet" />
|
||||
|
||||
<Button
|
||||
style="@style/MediumProminentOutlineButton"
|
||||
android:id="@+id/createNewPrivateChatButton"
|
||||
android:layout_width="196dp"
|
||||
android:layout_height="@dimen/medium_button_height"
|
||||
android:layout_marginTop="@dimen/medium_spacing"
|
||||
android:text="Start a Session" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
@ -21,7 +21,7 @@
|
||||
android:textColor="@color/text"
|
||||
android:text="Your Session begins here..." />
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.FakeChatView
|
||||
<org.thoughtcrime.securesms.loki.views.FakeChatView
|
||||
android:id="@+id/fakeChatView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/fake_chat_view_height"
|
||||
|
@ -31,7 +31,7 @@
|
||||
android:layout_width="196dp"
|
||||
android:layout_height="@dimen/medium_button_height"
|
||||
android:layout_marginTop="@dimen/medium_spacing"
|
||||
android:text="Link a Device" />
|
||||
android:text="Link a Device (Beta)" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginRight="@dimen/very_large_spacing"
|
||||
android:textSize="@dimen/small_font_size"
|
||||
android:textColor="@color/text"
|
||||
@ -38,7 +38,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="18dp"
|
||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="@dimen/very_large_spacing"
|
||||
android:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginRight="@dimen/very_large_spacing"
|
||||
android:textSize="@dimen/small_font_size"
|
||||
android:textColor="@color/text"
|
||||
@ -37,7 +37,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="@dimen/very_large_spacing"
|
||||
android:hint="Enter your recovery phrase" />
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.SeedReminderView
|
||||
<org.thoughtcrime.securesms.loki.views.SeedReminderView
|
||||
android:id="@+id/seedReminderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
@ -22,7 +22,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||
android:layout_marginRight="@dimen/very_large_spacing"
|
||||
android:textSize="@dimen/large_font_size"
|
||||
android:textSize="19sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text"
|
||||
android:text="Meet your recovery phrase" />
|
||||
@ -31,9 +31,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginRight="@dimen/very_large_spacing"
|
||||
android:textSize="@dimen/medium_font_size"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/text"
|
||||
android:text="Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don’t give it to anyone. To restore your Session ID, launch Session and tap Continue your Session." />
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||
android:layout_marginTop="@dimen/medium_spacing"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="@dimen/very_large_spacing"
|
||||
android:gravity="center"
|
||||
android:textSize="@dimen/medium_font_size"
|
||||
@ -54,9 +54,9 @@
|
||||
android:id="@+id/revealButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="@dimen/medium_font_size"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/text"
|
||||
android:alpha="0.6"
|
||||
android:text="Hold to reveal" />
|
||||
|
@ -70,7 +70,7 @@
|
||||
|
||||
</android.support.v7.widget.Toolbar>
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.ProfilePictureView
|
||||
<org.thoughtcrime.securesms.loki.views.ProfilePictureView
|
||||
android:id="@+id/profilePictureView"
|
||||
android:layout_width="@dimen/large_profile_picture_size"
|
||||
android:layout_height="@dimen/large_profile_picture_size"
|
||||
@ -107,7 +107,7 @@
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.LabeledSeparatorView
|
||||
<org.thoughtcrime.securesms.loki.views.LabeledSeparatorView
|
||||
android:id="@+id/separatorView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="32dp"
|
||||
|
@ -19,6 +19,6 @@
|
||||
<fragment android:id="@+id/contact_selection_list_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment" />
|
||||
android:name="org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment" />
|
||||
|
||||
</LinearLayout>
|
@ -1,92 +1,53 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical">
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
<TextView android:id="@android:id/empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center|center_vertical"
|
||||
android:layout_marginTop="15dp"
|
||||
android:text="@string/contact_selection_group_activity__finding_contacts"
|
||||
android:textSize="20sp" />
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
<org.thoughtcrime.securesms.components.RecyclerViewFastScroller
|
||||
android:id="@+id/fast_scroller"
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:id="@+id/emptyStateContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="end"/>
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout android:id="@+id/show_contacts_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="You don't have any contacts yet"
|
||||
android:textColor="@color/text"
|
||||
android:textSize="@dimen/medium_font_size" />
|
||||
|
||||
<FrameLayout
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/mainContentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
<com.pnikosis.materialishprogress.ProgressWheel
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="invisible"
|
||||
app:matProg_circleRadius="145dp"
|
||||
app:matProg_barWidth="6dp"
|
||||
app:matProg_rimColor="@color/signal_primary"
|
||||
app:matProg_barColor="@color/signal_primary_dark"
|
||||
app:matProg_progressIndeterminate="true"
|
||||
tools:visibility="visible"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/loadingTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/text"
|
||||
android:text="@string/contact_selection_group_activity__finding_contacts"
|
||||
android:textSize="@dimen/large_font_size" />
|
||||
|
||||
<ImageView android:layout_gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/no_contacts"/>
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView android:id="@+id/show_contacts_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginStart="50dp"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:textSize="15sp"
|
||||
android:lineSpacingMultiplier="1.3"
|
||||
android:gravity="center"
|
||||
android:text="@string/contact_selection_list_fragment__signal_needs_access_to_your_contacts_in_order_to_display_them"/>
|
||||
|
||||
<Button android:id="@+id/show_contacts_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:background="@color/signal_primary"
|
||||
android:textColor="@color/white"
|
||||
android:padding="10dp"
|
||||
android:text="@string/contact_selection_list_fragment__show_contacts"/>
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<org.thoughtcrime.securesms.contacts.ContactSelectionListItem
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:focusable="true"
|
||||
android:background="@drawable/conversation_item_background"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.ProfilePictureView
|
||||
android:id="@+id/profilePictureView"
|
||||
android:layout_width="@dimen/medium_profile_picture_size"
|
||||
android:layout_height="@dimen/medium_profile_picture_size" />
|
||||
|
||||
<LinearLayout android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:textSize="@dimen/medium_font_size"
|
||||
android:textColor="@color/text"
|
||||
android:textStyle="bold"
|
||||
tools:text="Frieeeeeeedrich Nieeeeeeeeeetzsche" />
|
||||
|
||||
<LinearLayout android:id="@+id/number_container"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView android:id="@+id/number"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textDirection="ltr"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="sans-serif-light"
|
||||
tools:text="+1 (555) 555-5555" />
|
||||
|
||||
<TextView android:id="@+id/label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="10dip"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:fontFamily="sans-serif-light"
|
||||
tools:text="Mobile" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<CheckBox android:id="@+id/check_box"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:focusable="false"
|
||||
android:clickable="false" />
|
||||
|
||||
</org.thoughtcrime.securesms.contacts.ContactSelectionListItem>
|
@ -104,7 +104,7 @@
|
||||
android:indeterminate="false"
|
||||
android:progress="0" />
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.SessionRestoreBannerView
|
||||
<org.thoughtcrime.securesms.loki.views.SessionRestoreBannerView
|
||||
android:id="@+id/sessionRestoreBannerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
@ -28,7 +28,7 @@
|
||||
android:layout_height="42dp"
|
||||
android:layout_alignParentStart="true">
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.ProfilePictureView
|
||||
<org.thoughtcrime.securesms.loki.views.ProfilePictureView
|
||||
android:id="@+id/profilePictureView"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_width="@dimen/small_profile_picture_size"
|
||||
@ -208,7 +208,7 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.FriendRequestView
|
||||
<org.thoughtcrime.securesms.loki.views.FriendRequestView
|
||||
android:id="@+id/friend_request_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -18,7 +18,7 @@
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/large_spacing"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false">
|
||||
|
||||
@ -161,7 +161,7 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.FriendRequestView
|
||||
<org.thoughtcrime.securesms.loki.views.FriendRequestView
|
||||
android:id="@+id/friend_request_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -4,7 +4,7 @@
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/large_spacing"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="@dimen/small_spacing"
|
||||
android:gravity="center_vertical">
|
||||
|
@ -3,6 +3,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="@drawable/default_dialog_background_inset"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
@ -12,6 +13,7 @@
|
||||
android:paddingBottom="@dimen/medium_spacing">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/qrCodeImageViewContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/small_spacing"
|
||||
@ -24,6 +26,15 @@
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<com.github.ybq.android.spinkit.SpinKitView
|
||||
style="@style/SpinKitView.DoubleBounce"
|
||||
android:id="@+id/spinner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="gone"
|
||||
app:SpinKit_Color="@color/text" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/titleTextView"
|
||||
android:layout_width="wrap_content"
|
||||
@ -56,6 +67,7 @@
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/buttonContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/large_spacing"
|
||||
|
@ -18,7 +18,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_centerInParent="true"
|
||||
app:SpinKit_Color="@color/text" />
|
||||
|
||||
<TextView
|
||||
|
@ -30,7 +30,7 @@
|
||||
android:textAlignment="center"
|
||||
android:text="Users can share their Session ID by going into their account settings and tapping "Share Session ID", or by sharing their QR code." />
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.LabeledSeparatorView
|
||||
<org.thoughtcrime.securesms.loki.views.LabeledSeparatorView
|
||||
android:id="@+id/separatorView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="32dp"
|
||||
|
@ -26,7 +26,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/large_spacing"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginRight="@dimen/large_spacing"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/text"
|
||||
@ -38,7 +38,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/large_spacing"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="@dimen/large_spacing"
|
||||
android:hint="Enter your session ID" />
|
||||
|
||||
|
@ -94,7 +94,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment"
|
||||
android:name="org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment"
|
||||
tools:layout="@layout/contact_selection_list_fragment"/>
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
|
@ -49,7 +49,7 @@
|
||||
android:layout_below="@id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment" />
|
||||
android:name="org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.SearchToolbar
|
||||
android:id="@+id/search_toolbar"
|
||||
|
@ -13,7 +13,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/accent" />
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.ProfilePictureView
|
||||
<org.thoughtcrime.securesms.loki.views.ProfilePictureView
|
||||
android:id="@+id/profilePictureView"
|
||||
android:layout_width="@dimen/medium_profile_picture_size"
|
||||
android:layout_height="@dimen/medium_profile_picture_size"
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.MentionCandidateView
|
||||
<org.thoughtcrime.securesms.loki.views.MentionCandidateView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="44dp"
|
||||
@ -13,7 +13,7 @@
|
||||
android:layout_width="26dp"
|
||||
android:layout_height="32dp">
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.ProfilePictureView
|
||||
<org.thoughtcrime.securesms.loki.views.ProfilePictureView
|
||||
android:id="@+id/profilePictureView"
|
||||
android:layout_width="@dimen/very_small_profile_picture_size"
|
||||
android:layout_height="@dimen/very_small_profile_picture_size"
|
||||
@ -39,4 +39,4 @@
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end" />
|
||||
|
||||
</org.thoughtcrime.securesms.loki.redesign.views.MentionCandidateView>
|
||||
</org.thoughtcrime.securesms.loki.views.MentionCandidateView>
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.MentionCandidateSelectionView
|
||||
<org.thoughtcrime.securesms.loki.views.MentionCandidateSelectionView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/userSelectionView"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/cell_background"
|
||||
@ -39,11 +40,12 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subtitleTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="224dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textColor="@color/text"
|
||||
android:textSize="@dimen/very_small_font_size"
|
||||
android:lines="2"
|
||||
android:alpha="0.6"
|
||||
android:text="Secure your account by saving your recovery phrase" />
|
||||
|
||||
@ -52,14 +54,15 @@
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
android:layout_weight="1"
|
||||
android:layout_marginLeft="4dp" />
|
||||
|
||||
<Button
|
||||
style="@style/MediumProminentOutlineButton"
|
||||
android:id="@+id/button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="27dp"
|
||||
android:layout_marginLeft="@dimen/small_spacing"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:textStyle="normal"
|
||||
android:text="Continue" />
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
android:gravity="center_vertical"
|
||||
android:padding="@dimen/medium_spacing">
|
||||
|
||||
<org.thoughtcrime.securesms.loki.redesign.views.ProfilePictureView
|
||||
<org.thoughtcrime.securesms.loki.views.ProfilePictureView
|
||||
android:id="@+id/profilePictureView"
|
||||
android:layout_width="@dimen/medium_profile_picture_size"
|
||||
android:layout_height="@dimen/medium_profile_picture_size" />
|
||||
|
@ -1663,13 +1663,14 @@
|
||||
<string name="session_restore_banner_dismiss_button_title">Dismiss</string>
|
||||
<string name="session_restore_banner_restore_button_title">Restore</string>
|
||||
|
||||
<!-- Loki -->
|
||||
|
||||
<!-- Session -->
|
||||
<string name="activity_register_public_key_copied_message">Copied to clipboard</string>
|
||||
<string name="activity_home_leave_group_dialog_message">Are you sure you want to leave this group?</string>
|
||||
<string name="activity_home_delete_conversation_dialog_message">Are you sure you want to delete this conversation?</string>
|
||||
<string name="activity_home_conversation_deleted_message">Conversation deleted</string>
|
||||
<string name="fragment_contact_selection_contacts_title">Contacts</string>
|
||||
<string name="fragment_contact_selection_closed_groups_title">Closed Groups</string>
|
||||
<string name="fragment_contact_selection_open_groups_title">Open Groups</string>
|
||||
<string name="activity_pn_mode_title">Push Notifications</string>
|
||||
<string name="activity_pn_mode_explanation">There are two ways Session can handle push notifications. Make sure to read the descriptions carefully before you choose.</string>
|
||||
<string name="activity_pn_mode_fcm_option_title">Firebase Cloud Messaging</string>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">149.56.148.124</domain>
|
||||
<domain includeSubdomains="true">144.76.164.202</domain>
|
||||
<domain includeSubdomains="true">storage.seed1.loki.network</domain>
|
||||
<domain includeSubdomains="true">storage.seed2.loki.network</domain>
|
||||
<domain includeSubdomains="true">public.loki.foundation</domain>
|
||||
|
@ -19,10 +19,8 @@ package org.thoughtcrime.securesms;
|
||||
import android.arch.lifecycle.DefaultLifecycleObserver;
|
||||
import android.arch.lifecycle.LifecycleOwner;
|
||||
import android.arch.lifecycle.ProcessLifecycleOwner;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
@ -41,12 +39,10 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseContentProviders;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.dependencies.AxolotlStorageModule;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
import org.thoughtcrime.securesms.jobmanager.DependencyInjector;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer;
|
||||
@ -62,16 +58,18 @@ import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.logging.PersistentLogger;
|
||||
import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger;
|
||||
import org.thoughtcrime.securesms.loki.LokiPublicChatManager;
|
||||
import org.thoughtcrime.securesms.loki.LokiPushNotificationManager;
|
||||
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.loki.redesign.messaging.BackgroundOpenGroupPollWorker;
|
||||
import org.thoughtcrime.securesms.loki.redesign.messaging.BackgroundPollWorker;
|
||||
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIDatabase;
|
||||
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiRSSFeedPoller;
|
||||
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiUserDatabase;
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.Broadcaster;
|
||||
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.loki.api.BackgroundOpenGroupPollWorker;
|
||||
import org.thoughtcrime.securesms.loki.api.BackgroundPollWorker;
|
||||
import org.thoughtcrime.securesms.loki.api.LokiPublicChatManager;
|
||||
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||
import org.thoughtcrime.securesms.loki.protocol.EphemeralMessage;
|
||||
import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.loki.protocol.PushEphemeralMessageSendJob;
|
||||
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
@ -86,6 +84,7 @@ import org.thoughtcrime.securesms.service.RotateSenderCertificateListener;
|
||||
import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener;
|
||||
import org.thoughtcrime.securesms.service.UpdateApkRefreshListener;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
|
||||
import org.webrtc.PeerConnectionFactory;
|
||||
import org.webrtc.PeerConnectionFactory.InitializationOptions;
|
||||
@ -96,25 +95,29 @@ import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPI;
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPIDatabaseProtocol;
|
||||
import org.whispersystems.signalservice.loki.api.LokiP2PAPI;
|
||||
import org.whispersystems.signalservice.loki.api.LokiP2PAPIDelegate;
|
||||
import org.whispersystems.signalservice.loki.api.LokiPoller;
|
||||
import org.whispersystems.signalservice.loki.api.LokiPushNotificationAcknowledgement;
|
||||
import org.whispersystems.signalservice.loki.api.LokiSwarmAPI;
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
||||
import org.whispersystems.signalservice.loki.api.publicchats.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.api.publicchats.LokiPublicChatAPI;
|
||||
import org.whispersystems.signalservice.loki.api.rssfeeds.LokiRSSFeed;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
||||
import org.whispersystems.signalservice.loki.api.p2p.LokiP2PAPI;
|
||||
import org.whispersystems.signalservice.loki.api.p2p.LokiP2PAPIDelegate;
|
||||
import org.whispersystems.signalservice.loki.database.LokiAPIDatabaseProtocol;
|
||||
import org.whispersystems.signalservice.loki.protocol.friendrequests.FriendRequestProtocol;
|
||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
|
||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink;
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol;
|
||||
import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocol;
|
||||
import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocolDelegate;
|
||||
import org.whispersystems.signalservice.loki.protocol.syncmessages.SyncMessagesProtocol;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Security;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import dagger.ObjectGraph;
|
||||
@ -132,7 +135,7 @@ import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate {
|
||||
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate, SessionManagementProtocolDelegate {
|
||||
|
||||
private static final String TAG = ApplicationContext.class.getSimpleName();
|
||||
private final static int OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10 MB
|
||||
@ -146,10 +149,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
private PersistentLogger persistentLogger;
|
||||
|
||||
// Loki
|
||||
private LokiPoller lokiPoller = null;
|
||||
private LokiRSSFeedPoller lokiNewsFeedPoller = null;
|
||||
private LokiRSSFeedPoller lokiMessengerUpdatesFeedPoller = null;
|
||||
private LokiPublicChatManager lokiPublicChatManager = null;
|
||||
public LokiPoller lokiPoller = null;
|
||||
public LokiPublicChatManager lokiPublicChatManager = null;
|
||||
private LokiPublicChatAPI lokiPublicChatAPI = null;
|
||||
public Broadcaster broadcaster = null;
|
||||
public SignalCommunicationModule communicationModule;
|
||||
@ -164,13 +165,42 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Log.i(TAG, "onCreate()");
|
||||
broadcaster = new Broadcaster(this);
|
||||
checkNeedsDatabaseReset();
|
||||
startKovenant();
|
||||
initializeSecurityProvider();
|
||||
initializeLogging();
|
||||
initializeCrashHandling();
|
||||
initializeDependencyInjection();
|
||||
NotificationChannels.create(this);
|
||||
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
|
||||
// Loki
|
||||
// ========
|
||||
broadcaster = new Broadcaster(this);
|
||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(this);
|
||||
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
LokiSessionResetImplementation sessionResetImpl = new LokiSessionResetImplementation(this);
|
||||
if (userPublicKey != null) {
|
||||
FriendRequestProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
||||
SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||
SyncMessagesProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||
}
|
||||
MultiDeviceProtocol.Companion.configureIfNeeded(apiDB);
|
||||
SessionManagementProtocol.Companion.configureIfNeeded(sessionResetImpl, threadDB, this);
|
||||
setUpP2PAPIIfNeeded();
|
||||
LokiPushNotificationAcknowledgement.Companion.configureIfNeeded(BuildConfig.DEBUG);
|
||||
if (setUpStorageAPIIfNeeded()) {
|
||||
if (userPublicKey != null) {
|
||||
Set<DeviceLink> deviceLinks = DatabaseFactory.getLokiAPIDatabase(this).getDeviceLinks(userPublicKey);
|
||||
LokiFileServerAPI.shared.setDeviceLinks(deviceLinks);
|
||||
}
|
||||
}
|
||||
resubmitProfilePictureIfNeeded();
|
||||
lokiPublicChatManager = new LokiPublicChatManager(this);
|
||||
updateOpenGroupProfilePicturesIfNeeded();
|
||||
registerForFCMIfNeeded(false);
|
||||
// ========
|
||||
initializeJobManager();
|
||||
initializeMessageRetrieval();
|
||||
initializeExpiringMessageManager();
|
||||
@ -182,30 +212,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
initializePendingMessages();
|
||||
initializeUnidentifiedDeliveryAbilityRefresh();
|
||||
initializeBlobProvider();
|
||||
NotificationChannels.create(this);
|
||||
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
|
||||
// Loki - Set up P2P API if needed
|
||||
setUpP2PAPI();
|
||||
// Loki - Set up push notification acknowledgement
|
||||
LokiPushNotificationAcknowledgement.Companion.configureIfNeeded(BuildConfig.DEBUG);
|
||||
// Loki - Update device mappings
|
||||
if (setUpStorageAPIIfNeeded()) {
|
||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userHexEncodedPublicKey != null) {
|
||||
if (TextSecurePreferences.getNeedsIsRevokedSlaveDeviceCheck(this)) {
|
||||
MultiDeviceUtilities.checkIsRevokedSlaveDevice(this);
|
||||
} else {
|
||||
// We always update our current device links onto the server in case we failed to do so upon linking
|
||||
MultiDeviceUtilities.updateDeviceLinksOnServer(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Loki - Resubmit profile picture if needed
|
||||
resubmitProfilePictureIfNeeded();
|
||||
// Loki - Set up public chat manager
|
||||
lokiPublicChatManager = new LokiPublicChatManager(this);
|
||||
updatePublicChatProfilePictureIfNeeded();
|
||||
registerForFCMIfNeeded(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -214,9 +220,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
Log.i(TAG, "App is now visible.");
|
||||
executePendingContactSync();
|
||||
KeyCachingService.onAppForegrounded(this);
|
||||
// Loki - Start polling if needed
|
||||
// Loki
|
||||
startPollingIfNeeded();
|
||||
// Loki - Start open group polling if needed
|
||||
lokiPublicChatManager.startPollersIfNeeded();
|
||||
}
|
||||
|
||||
@ -226,14 +231,14 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
Log.i(TAG, "App is no longer visible.");
|
||||
KeyCachingService.onAppBackgrounded(this);
|
||||
MessageNotifier.setVisibleThread(-1);
|
||||
// Loki - Stop polling if needed
|
||||
// Loki
|
||||
if (lokiPoller != null) { lokiPoller.stopIfNeeded(); }
|
||||
if (lokiPublicChatManager != null) { lokiPublicChatManager.stopPollers(); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
stopKovenant();
|
||||
stopKovenant(); // Loki
|
||||
super.onTerminate();
|
||||
}
|
||||
|
||||
@ -268,20 +273,15 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
return persistentLogger;
|
||||
}
|
||||
|
||||
public LokiPublicChatManager getLokiPublicChatManager() {
|
||||
return lokiPublicChatManager;
|
||||
}
|
||||
|
||||
// Loki
|
||||
public @Nullable LokiPublicChatAPI getLokiPublicChatAPI() {
|
||||
if (lokiPublicChatAPI == null && IdentityKeyUtil.hasIdentityKey(this)) {
|
||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userHexEncodedPublicKey != null) {
|
||||
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
||||
LokiAPIDatabase apiDatabase = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
LokiUserDatabase userDatabase = DatabaseFactory.getLokiUserDatabase(this);
|
||||
lokiPublicChatAPI = new LokiPublicChatAPI(userHexEncodedPublicKey, userPrivateKey, apiDatabase, userDatabase);
|
||||
}
|
||||
}
|
||||
if (lokiPublicChatAPI != null || !IdentityKeyUtil.hasIdentityKey(this)) { return lokiPublicChatAPI; }
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userPublicKey== null) { return lokiPublicChatAPI; }
|
||||
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
||||
lokiPublicChatAPI = new LokiPublicChatAPI(userPublicKey, userPrivateKey, apiDB, userDB);
|
||||
return lokiPublicChatAPI;
|
||||
}
|
||||
|
||||
@ -363,8 +363,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
RotateSignedPreKeyListener.schedule(this);
|
||||
LocalBackupListener.schedule(this);
|
||||
RotateSenderCertificateListener.schedule(this);
|
||||
BackgroundPollWorker.schedule(this); // Session
|
||||
BackgroundOpenGroupPollWorker.schedule(this); // Session
|
||||
BackgroundPollWorker.schedule(this); // Loki
|
||||
BackgroundOpenGroupPollWorker.schedule(this); // Loki
|
||||
|
||||
if (BuildConfig.PLAY_STORE_DISABLED) {
|
||||
UpdateApkRefreshListener.schedule(this);
|
||||
@ -442,18 +442,16 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
|
||||
// region Loki
|
||||
public boolean setUpStorageAPIIfNeeded() {
|
||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userHexEncodedPublicKey != null && IdentityKeyUtil.hasIdentityKey(this)) {
|
||||
boolean isDebugMode = BuildConfig.DEBUG;
|
||||
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
||||
LokiAPIDatabaseProtocol database = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
LokiFileServerAPI.Companion.configure(isDebugMode, userHexEncodedPublicKey, userPrivateKey, database);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userPublicKey == null || !IdentityKeyUtil.hasIdentityKey(this)) { return false; }
|
||||
boolean isDebugMode = BuildConfig.DEBUG;
|
||||
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
||||
LokiAPIDatabaseProtocol apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
LokiFileServerAPI.Companion.configure(isDebugMode, userPublicKey, userPrivateKey, apiDB);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setUpP2PAPI() {
|
||||
public void setUpP2PAPIIfNeeded() {
|
||||
String hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (hexEncodedPublicKey == null) { return; }
|
||||
LokiP2PAPI.Companion.configure(hexEncodedPublicKey, (isOnline, contactPublicKey) -> {
|
||||
@ -470,10 +468,10 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
return;
|
||||
}
|
||||
String token = task.getResult().getToken();
|
||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context);
|
||||
if (userHexEncodedPublicKey == null) return;
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(context);
|
||||
if (userPublicKey == null) return;
|
||||
if (TextSecurePreferences.isUsingFCM(this)) {
|
||||
LokiPushNotificationManager.register(token, userHexEncodedPublicKey, context, force);
|
||||
LokiPushNotificationManager.register(token, userPublicKey, context, force);
|
||||
} else {
|
||||
LokiPushNotificationManager.unregister(token, context);
|
||||
}
|
||||
@ -487,15 +485,15 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
|
||||
private void setUpPollingIfNeeded() {
|
||||
if (lokiPoller != null) return;
|
||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userHexEncodedPublicKey == null) return;
|
||||
LokiAPIDatabase lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userPublicKey == null) return;
|
||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
Context context = this;
|
||||
LokiSwarmAPI.Companion.configureIfNeeded(lokiAPIDatabase);
|
||||
LokiAPI.Companion.configureIfNeeded(userHexEncodedPublicKey, lokiAPIDatabase, broadcaster);
|
||||
lokiPoller = new LokiPoller(userHexEncodedPublicKey, lokiAPIDatabase, protos -> {
|
||||
LokiSwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||
LokiAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||
lokiPoller = new LokiPoller(userPublicKey, apiDB, protos -> {
|
||||
for (SignalServiceProtos.Envelope proto : protos) {
|
||||
new PushContentReceiveJob(context).processEnvelope(new SignalServiceEnvelope(proto));
|
||||
new PushContentReceiveJob(context).processEnvelope(new SignalServiceEnvelope(proto), false);
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
@ -506,94 +504,9 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
if (lokiPoller != null) { lokiPoller.startIfNeeded(); }
|
||||
}
|
||||
|
||||
private LokiRSSFeed lokiNewsFeed() {
|
||||
return new LokiRSSFeed("loki.network.feed", "https://loki.network/feed/", "Loki News", true);
|
||||
}
|
||||
|
||||
private LokiRSSFeed lokiMessengerUpdatesFeed() {
|
||||
return new LokiRSSFeed("loki.network.messenger-updates.feed", "https://loki.network/category/messenger-updates/feed", "Session Updates", false);
|
||||
}
|
||||
|
||||
public void createDefaultPublicChatsIfNeeded() {
|
||||
List<LokiPublicChat> defaultPublicChats = LokiPublicChatAPI.Companion.getDefaultChats(BuildConfig.DEBUG);
|
||||
for (LokiPublicChat publicChat : defaultPublicChats) {
|
||||
long threadID = GroupManager.getPublicChatThreadId(publicChat.getId(), this);
|
||||
String migrationKey = publicChat.getId() + "_migrated";
|
||||
boolean isChatMigrated = TextSecurePreferences.getBooleanPreference(this, migrationKey, false);
|
||||
boolean isChatSetUp = TextSecurePreferences.isChatSetUp(this, publicChat.getId());
|
||||
if (!isChatSetUp || !publicChat.isDeletable()) {
|
||||
lokiPublicChatManager.addChat(publicChat.getServer(), publicChat.getChannel(), publicChat.getDisplayName());
|
||||
TextSecurePreferences.markChatSetUp(this, publicChat.getId());
|
||||
TextSecurePreferences.setBooleanPreference(this, migrationKey, true);
|
||||
} else if (threadID > -1 && !isChatMigrated) {
|
||||
// Migrate the old public chats
|
||||
DatabaseFactory.getLokiThreadDatabase(this).setPublicChat(publicChat, threadID);
|
||||
TextSecurePreferences.setBooleanPreference(this, migrationKey, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void createRSSFeedsIfNeeded() {
|
||||
ArrayList<LokiRSSFeed> feeds = new ArrayList<>();
|
||||
// feeds.add(lokiNewsFeed());
|
||||
feeds.add(lokiMessengerUpdatesFeed());
|
||||
for (LokiRSSFeed feed : feeds) {
|
||||
boolean isFeedSetUp = TextSecurePreferences.isChatSetUp(this, feed.getId());
|
||||
if (!isFeedSetUp || !feed.isDeletable()) {
|
||||
GroupManager.createRSSFeedGroup(feed.getId(), this, null, feed.getDisplayName());
|
||||
TextSecurePreferences.markChatSetUp(this, feed.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createRSSFeedPollersIfNeeded() {
|
||||
// Only create the RSS feed pollers if their threads aren't deleted
|
||||
LokiRSSFeed lokiNewsFeed = lokiNewsFeed();
|
||||
long lokiNewsFeedThreadID = GroupManager.getRSSFeedThreadId(lokiNewsFeed.getId(), this);
|
||||
if (lokiNewsFeedThreadID >= 0 && lokiNewsFeedPoller == null) {
|
||||
lokiNewsFeedPoller = new LokiRSSFeedPoller(this, lokiNewsFeed);
|
||||
// Set up deletion listeners if needed
|
||||
setUpThreadDeletionListeners(lokiNewsFeedThreadID, () -> {
|
||||
if (lokiNewsFeedPoller != null) lokiNewsFeedPoller.stop();
|
||||
lokiNewsFeedPoller = null;
|
||||
});
|
||||
}
|
||||
// The user can't delete the Session Updates RSS feed
|
||||
if (lokiMessengerUpdatesFeedPoller == null) {
|
||||
lokiMessengerUpdatesFeedPoller = new LokiRSSFeedPoller(this, lokiMessengerUpdatesFeed());
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpThreadDeletionListeners(long threadID, Runnable onDelete) {
|
||||
if (threadID < 0) { return; }
|
||||
ContentObserver observer = new ContentObserver(null) {
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
super.onChange(selfChange);
|
||||
// Stop the poller if thread is deleted
|
||||
try {
|
||||
if (!DatabaseFactory.getThreadDatabase(getApplicationContext()).hasThread(threadID)) {
|
||||
onDelete.run();
|
||||
getContentResolver().unregisterContentObserver(this);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// TODO: Handle
|
||||
}
|
||||
}
|
||||
};
|
||||
this.getContentResolver().registerContentObserver(DatabaseContentProviders.Conversation.getUriForThread(threadID), true, observer);
|
||||
}
|
||||
|
||||
public void startRSSFeedPollersIfNeeded() {
|
||||
createRSSFeedPollersIfNeeded();
|
||||
if (lokiNewsFeedPoller != null) lokiNewsFeedPoller.startIfNeeded();
|
||||
if (lokiMessengerUpdatesFeedPoller != null) lokiMessengerUpdatesFeedPoller.startIfNeeded();
|
||||
}
|
||||
|
||||
private void resubmitProfilePictureIfNeeded() {
|
||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userHexEncodedPublicKey == null) return;
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userPublicKey == null) return;
|
||||
long now = new Date().getTime();
|
||||
long lastProfilePictureUpload = TextSecurePreferences.getLastProfilePictureUpload(this);
|
||||
if (now - lastProfilePictureUpload <= 14 * 24 * 60 * 60 * 1000) return;
|
||||
@ -601,7 +514,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
String encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this);
|
||||
byte[] profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(encodedProfileKey);
|
||||
try {
|
||||
File profilePicture = AvatarHelper.getAvatarFile(this, Address.fromSerialized(userHexEncodedPublicKey));
|
||||
File profilePicture = AvatarHelper.getAvatarFile(this, Address.fromSerialized(userPublicKey));
|
||||
StreamDetails stream = new StreamDetails(new FileInputStream(profilePicture), "image/jpeg", profilePicture.length());
|
||||
LokiFileServerAPI.shared.uploadProfilePicture(LokiFileServerAPI.shared.getServer(), profileKey, stream, () -> {
|
||||
TextSecurePreferences.setLastProfilePictureUpload(this, new Date().getTime());
|
||||
@ -615,7 +528,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
});
|
||||
}
|
||||
|
||||
public void updatePublicChatProfilePictureIfNeeded() {
|
||||
public void updateOpenGroupProfilePicturesIfNeeded() {
|
||||
AsyncTask.execute(() -> {
|
||||
LokiPublicChatAPI publicChatAPI = null;
|
||||
try {
|
||||
@ -623,48 +536,46 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
} catch (Exception e) {
|
||||
// Do nothing
|
||||
}
|
||||
if (publicChatAPI != null) {
|
||||
byte[] profileKey = ProfileKeyUtil.getProfileKey(this);
|
||||
String url = TextSecurePreferences.getProfileAvatarUrl(this);
|
||||
String ourMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(this);
|
||||
if (ourMasterDevice != null) {
|
||||
Recipient masterDevice = Recipient.from(this, Address.fromSerialized(ourMasterDevice), false).resolve();
|
||||
profileKey = masterDevice.getProfileKey();
|
||||
url = masterDevice.getProfileAvatar();
|
||||
}
|
||||
Set<String> servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers();
|
||||
for (String server : servers) {
|
||||
if (profileKey != null) {
|
||||
publicChatAPI.setProfilePicture(server, profileKey, url);
|
||||
}
|
||||
if (publicChatAPI == null) { return; }
|
||||
byte[] profileKey = ProfileKeyUtil.getProfileKey(this);
|
||||
String url = TextSecurePreferences.getProfilePictureURL(this);
|
||||
String userMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(this);
|
||||
if (userMasterDevice != null) {
|
||||
Recipient userMasterDeviceAsRecipient = Recipient.from(this, Address.fromSerialized(userMasterDevice), false).resolve();
|
||||
profileKey = userMasterDeviceAsRecipient.getProfileKey();
|
||||
url = userMasterDeviceAsRecipient.getProfileAvatar();
|
||||
}
|
||||
Set<String> servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers();
|
||||
for (String server : servers) {
|
||||
if (profileKey != null) {
|
||||
publicChatAPI.setProfilePicture(server, profileKey, url);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void checkNeedsDatabaseReset() {
|
||||
if (TextSecurePreferences.resetDatabase(this)) {
|
||||
boolean wasUnlinked = TextSecurePreferences.databaseResetFromUnpair(this);
|
||||
TextSecurePreferences.clearAll(this);
|
||||
TextSecurePreferences.setDatabaseResetFromUnpair(this, wasUnlinked); // Loki - Re-set the preference so we can use it in the starting screen to determine whether device was unlinked or not
|
||||
MasterSecretUtil.clear(this);
|
||||
if (this.deleteDatabase("signal.db")) {
|
||||
Log.d("Loki", "Deleted database");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearData() {
|
||||
TextSecurePreferences.setResetDatabase(this, true);
|
||||
new Handler().postDelayed(this::restartApplication, 200);
|
||||
boolean wasUnlinked = TextSecurePreferences.getWasUnlinked(this);
|
||||
TextSecurePreferences.clearAll(this);
|
||||
TextSecurePreferences.setWasUnlinked(this, wasUnlinked);
|
||||
MasterSecretUtil.clear(this);
|
||||
if (!deleteDatabase("signal.db")) {
|
||||
Log.d("Loki", "Failed to delete database.");
|
||||
}
|
||||
Util.runOnMain(() -> new Handler().postDelayed(ApplicationContext.this::restartApplication, 200));
|
||||
}
|
||||
|
||||
public void restartApplication() {
|
||||
Intent intent = new Intent(this, HomeActivity.class);
|
||||
ComponentName componentName = intent.getComponent();
|
||||
Intent mainIntent = Intent.makeRestartActivityTask(componentName);
|
||||
this.startActivity(mainIntent);
|
||||
startActivity(Intent.makeRestartActivityTask(intent.getComponent()));
|
||||
Runtime.getRuntime().exit(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSessionRequest(@NotNull String publicKey) {
|
||||
DatabaseFactory.getLokiAPIDatabase(this).setSessionRequestTimestamp(publicKey, new Date().getTime());
|
||||
EphemeralMessage sessionRequest = EphemeralMessage.createSessionRequest(publicKey);
|
||||
jobManager.add(new PushEphemeralMessageSendJob(sessionRequest));
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
|
||||
import org.thoughtcrime.securesms.preferences.ChatsPreferenceFragment;
|
||||
import org.thoughtcrime.securesms.preferences.CorrectedPreferenceFragment;
|
||||
@ -345,16 +345,16 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
||||
}
|
||||
String seed = new MnemonicCodec(languageFileDirectory).encode(hexEncodedSeed, MnemonicCodec.Language.Configuration.Companion.getEnglish());
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle(R.string.activity_settings_seed_dialog_title)
|
||||
.setMessage(seed)
|
||||
.setPositiveButton(R.string.activity_settings_seed_dialog_copy_button_title, (DialogInterface.OnClickListener) (dialog, which) -> {
|
||||
ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText("seed", seed);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
Toast.makeText(getContext(), R.string.activity_settings_seed_copied_message, Toast.LENGTH_SHORT).show();
|
||||
})
|
||||
.setNeutralButton(R.string.activity_settings_seed_dialog_ok_button_title, null)
|
||||
.show();
|
||||
.setTitle(R.string.activity_settings_seed_dialog_title)
|
||||
.setMessage(seed)
|
||||
.setPositiveButton(R.string.activity_settings_seed_dialog_copy_button_title, (DialogInterface.OnClickListener) (dialog, which) -> {
|
||||
ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText("seed", seed);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
Toast.makeText(getContext(), R.string.activity_settings_seed_copied_message, Toast.LENGTH_SHORT).show();
|
||||
})
|
||||
.setNeutralButton(R.string.activity_settings_seed_dialog_ok_button_title, null)
|
||||
.show();
|
||||
} catch (Exception e) {
|
||||
Log.d("Loki", e.getMessage());
|
||||
}
|
||||
|
@ -20,11 +20,11 @@ import android.os.Bundle;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.components.ContactFilterToolbar;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment;
|
||||
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
@ -36,8 +36,8 @@ import network.loki.messenger.R;
|
||||
*
|
||||
*/
|
||||
public abstract class ContactSelectionActivity extends PassphraseRequiredActionBarActivity
|
||||
implements SwipeRefreshLayout.OnRefreshListener,
|
||||
ContactSelectionListFragment.OnContactSelectedListener
|
||||
implements SwipeRefreshLayout.OnRefreshListener,
|
||||
ContactSelectionListFragment.OnContactSelectedListener
|
||||
{
|
||||
private static final String TAG = ContactSelectionActivity.class.getSimpleName();
|
||||
|
||||
@ -57,9 +57,7 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActionB
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle, boolean ready) {
|
||||
if (!getIntent().hasExtra(ContactSelectionListFragment.DISPLAY_MODE)) {
|
||||
int displayMode = TextSecurePreferences.isSmsEnabled(this) ? DisplayMode.FLAG_ALL
|
||||
: DisplayMode.FLAG_PUSH | DisplayMode.FLAG_GROUPS;
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, displayMode);
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_ALL);
|
||||
}
|
||||
|
||||
setContentView(R.layout.contact_selection_activity);
|
||||
|
@ -1,303 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.database.Cursor;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.pnikosis.materialishprogress.ProgressWheel;
|
||||
|
||||
import org.thoughtcrime.securesms.components.RecyclerViewFastScroller;
|
||||
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter;
|
||||
import org.thoughtcrime.securesms.contacts.ContactSelectionListItem;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
/**
|
||||
* Fragment for selecting a one or more contacts from a list.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
public class ContactSelectionListFragment extends Fragment
|
||||
implements LoaderManager.LoaderCallbacks<Cursor>
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = ContactSelectionListFragment.class.getSimpleName();
|
||||
|
||||
public static final String DISPLAY_MODE = "display_mode";
|
||||
public static final String MULTI_SELECT = "multi_select";
|
||||
public static final String REFRESHABLE = "refreshable";
|
||||
public static final String RECENTS = "recents";
|
||||
|
||||
private TextView emptyText;
|
||||
private Set<String> selectedContacts;
|
||||
private OnContactSelectedListener onContactSelectedListener;
|
||||
private SwipeRefreshLayout swipeRefresh;
|
||||
private View showContactsLayout;
|
||||
private Button showContactsButton;
|
||||
private TextView showContactsDescription;
|
||||
private ProgressWheel showContactsProgress;
|
||||
private String cursorFilter;
|
||||
private RecyclerView recyclerView;
|
||||
private RecyclerViewFastScroller fastScroller;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle icicle) {
|
||||
super.onActivityCreated(icicle);
|
||||
|
||||
initializeCursor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
handleContactPermissionGranted();
|
||||
|
||||
// Permissions.with(this)
|
||||
// .request(Manifest.permission.WRITE_CONTACTS, Manifest.permission.READ_CONTACTS)
|
||||
// .ifNecessary()
|
||||
// .onAllGranted(() -> {
|
||||
// if (!TextSecurePreferences.hasSuccessfullyRetrievedDirectory(getActivity())) {
|
||||
// handleContactPermissionGranted();
|
||||
// } else {
|
||||
// this.getLoaderManager().initLoader(0, null, this);
|
||||
// }
|
||||
// })
|
||||
// .onAnyDenied(() -> {
|
||||
// getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
|
||||
//
|
||||
// if (getActivity().getIntent().getBooleanExtra(RECENTS, false)) {
|
||||
// getLoaderManager().initLoader(0, null, ContactSelectionListFragment.this);
|
||||
// } else {
|
||||
// initializeNoContactsPermission();
|
||||
// }
|
||||
// })
|
||||
// .execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.contact_selection_list_fragment, container, false);
|
||||
|
||||
emptyText = ViewUtil.findById(view, android.R.id.empty);
|
||||
recyclerView = ViewUtil.findById(view, R.id.recycler_view);
|
||||
swipeRefresh = ViewUtil.findById(view, R.id.swipe_refresh);
|
||||
fastScroller = ViewUtil.findById(view, R.id.fast_scroller);
|
||||
showContactsLayout = view.findViewById(R.id.show_contacts_container);
|
||||
showContactsButton = view.findViewById(R.id.show_contacts_button);
|
||||
showContactsDescription = view.findViewById(R.id.show_contacts_description);
|
||||
showContactsProgress = view.findViewById(R.id.progress);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
|
||||
swipeRefresh.setEnabled(getActivity().getIntent().getBooleanExtra(REFRESHABLE, true));
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
public @NonNull List<String> getSelectedContacts() {
|
||||
List<String> selected = new LinkedList<>();
|
||||
if (selectedContacts != null) {
|
||||
selected.addAll(selectedContacts);
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
private boolean isMulti() {
|
||||
return getActivity().getIntent().getBooleanExtra(MULTI_SELECT, false);
|
||||
}
|
||||
|
||||
private void initializeCursor() {
|
||||
ContactSelectionListAdapter adapter = new ContactSelectionListAdapter(getActivity(),
|
||||
GlideApp.with(this),
|
||||
null,
|
||||
new ListClickListener(),
|
||||
isMulti());
|
||||
selectedContacts = adapter.getSelectedContacts();
|
||||
recyclerView.setAdapter(adapter);
|
||||
recyclerView.addItemDecoration(new StickyHeaderDecoration(adapter, true, true));
|
||||
}
|
||||
|
||||
private void initializeNoContactsPermission() {
|
||||
swipeRefresh.setVisibility(View.GONE);
|
||||
|
||||
showContactsLayout.setVisibility(View.VISIBLE);
|
||||
showContactsProgress.setVisibility(View.INVISIBLE);
|
||||
showContactsDescription.setText(R.string.contact_selection_list_fragment__signal_needs_access_to_your_contacts_in_order_to_display_them);
|
||||
showContactsButton.setVisibility(View.VISIBLE);
|
||||
|
||||
/*
|
||||
showContactsButton.setOnClickListener(v -> {
|
||||
Permissions.with(this)
|
||||
.request(Manifest.permission.WRITE_CONTACTS, Manifest.permission.READ_CONTACTS)
|
||||
.ifNecessary()
|
||||
.withPermanentDenialDialog(getString(R.string.ContactSelectionListFragment_signal_requires_the_contacts_permission_in_order_to_display_your_contacts))
|
||||
.onSomeGranted(permissions -> {
|
||||
if (permissions.contains(Manifest.permission.WRITE_CONTACTS)) {
|
||||
handleContactPermissionGranted();
|
||||
}
|
||||
})
|
||||
.execute();
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
public void setQueryFilter(String filter) {
|
||||
this.cursorFilter = filter;
|
||||
this.getLoaderManager().restartLoader(0, null, this);
|
||||
}
|
||||
|
||||
public void resetQueryFilter() {
|
||||
setQueryFilter(null);
|
||||
swipeRefresh.setRefreshing(false);
|
||||
}
|
||||
|
||||
public void setRefreshing(boolean refreshing) {
|
||||
swipeRefresh.setRefreshing(refreshing);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
selectedContacts.clear();
|
||||
|
||||
if (!isDetached() && !isRemoving() && getActivity() != null && !getActivity().isFinishing()) {
|
||||
getLoaderManager().restartLoader(0, null, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
return new ContactsCursorLoader(getActivity(),
|
||||
getActivity().getIntent().getIntExtra(DISPLAY_MODE, DisplayMode.FLAG_ALL),
|
||||
cursorFilter, getActivity().getIntent().getBooleanExtra(RECENTS, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {
|
||||
swipeRefresh.setVisibility(View.VISIBLE);
|
||||
showContactsLayout.setVisibility(View.GONE);
|
||||
|
||||
((CursorRecyclerViewAdapter) recyclerView.getAdapter()).changeCursor(data);
|
||||
emptyText.setText(R.string.contact_selection_group_activity__no_contacts);
|
||||
boolean useFastScroller = (recyclerView.getAdapter().getItemCount() > 20);
|
||||
recyclerView.setVerticalScrollBarEnabled(!useFastScroller);
|
||||
if (useFastScroller) {
|
||||
fastScroller.setVisibility(View.VISIBLE);
|
||||
fastScroller.setRecyclerView(recyclerView);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(@NonNull Loader<Cursor> loader) {
|
||||
((CursorRecyclerViewAdapter) recyclerView.getAdapter()).changeCursor(null);
|
||||
fastScroller.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private void handleContactPermissionGranted() {
|
||||
new AsyncTask<Void, Void, Boolean>() {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
swipeRefresh.setVisibility(View.GONE);
|
||||
showContactsLayout.setVisibility(View.VISIBLE);
|
||||
showContactsButton.setVisibility(View.INVISIBLE);
|
||||
showContactsDescription.setText(R.string.ConversationListFragment_loading);
|
||||
showContactsProgress.setVisibility(View.VISIBLE);
|
||||
showContactsProgress.spin();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
if (result) {
|
||||
showContactsLayout.setVisibility(View.GONE);
|
||||
swipeRefresh.setVisibility(View.VISIBLE);
|
||||
reset();
|
||||
} else {
|
||||
Toast.makeText(getContext(), R.string.ContactSelectionListFragment_error_retrieving_contacts_check_your_network_connection, Toast.LENGTH_LONG).show();
|
||||
initializeNoContactsPermission();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private class ListClickListener implements ContactSelectionListAdapter.ItemClickListener {
|
||||
@Override
|
||||
public void onItemClick(ContactSelectionListItem contact) {
|
||||
if (!isMulti() || !selectedContacts.contains(contact.getNumber())) {
|
||||
selectedContacts.add(contact.getNumber());
|
||||
contact.setChecked(true);
|
||||
if (onContactSelectedListener != null) onContactSelectedListener.onContactSelected(contact.getNumber());
|
||||
} else {
|
||||
selectedContacts.remove(contact.getNumber());
|
||||
contact.setChecked(false);
|
||||
if (onContactSelectedListener != null) onContactSelectedListener.onContactDeselected(contact.getNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnContactSelectedListener(OnContactSelectedListener onContactSelectedListener) {
|
||||
this.onContactSelectedListener = onContactSelectedListener;
|
||||
}
|
||||
|
||||
public void setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener onRefreshListener) {
|
||||
this.swipeRefresh.setOnRefreshListener(onRefreshListener);
|
||||
}
|
||||
|
||||
public interface OnContactSelectedListener {
|
||||
void onContactSelected(String number);
|
||||
void onContactDeselected(String number);
|
||||
}
|
||||
|
||||
}
|
@ -49,8 +49,8 @@ import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.lock.RegistrationLockDialog;
|
||||
import org.thoughtcrime.securesms.loki.RecipientAvatarModifiedEvent;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.JoinPublicChatActivity;
|
||||
import org.thoughtcrime.securesms.loki.utilities.ProfilePictureModifiedEvent;
|
||||
import org.thoughtcrime.securesms.loki.activities.JoinPublicChatActivity;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
@ -86,13 +86,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
protected void onPreCreate() {
|
||||
dynamicTheme.onCreate(this);
|
||||
dynamicLanguage.onCreate(this);
|
||||
if (TextSecurePreferences.getLocalNumber(this) != null) {
|
||||
ApplicationContext application = ApplicationContext.getInstance(this);
|
||||
application.createDefaultPublicChatsIfNeeded();
|
||||
application.createRSSFeedsIfNeeded();
|
||||
application.getLokiPublicChatManager().startPollersIfNeeded();
|
||||
application.startRSSFeedPollersIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -330,9 +323,9 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onAvatarModified(RecipientAvatarModifiedEvent event) {
|
||||
public void onAvatarModified(ProfilePictureModifiedEvent event) {
|
||||
Recipient recipient = event.getRecipient();
|
||||
if (recipient.isLocalNumber() || recipient.isOurMasterDevice()) {
|
||||
if (recipient.isLocalNumber() || recipient.isUserMasterDevice()) {
|
||||
initializeProfileIcon(recipient);
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.database.loaders.ConversationListLoader;
|
||||
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
|
||||
import org.thoughtcrime.securesms.jobs.ServiceOutageDetectionJob;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.CreatePrivateChatActivity;
|
||||
import org.thoughtcrime.securesms.loki.activities.CreatePrivateChatActivity;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
|
@ -37,8 +37,8 @@ import org.thoughtcrime.securesms.components.FromTextView;
|
||||
import org.thoughtcrime.securesms.components.ThumbnailView;
|
||||
import org.thoughtcrime.securesms.components.TypingIndicatorView;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIUtilities;
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.MentionUtilities;
|
||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
||||
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
@ -272,7 +272,7 @@ public class ConversationListItem extends RelativeLayout
|
||||
}
|
||||
|
||||
private @NonNull CharSequence getTrimmedSnippet(@NonNull CharSequence snippet) {
|
||||
LokiAPIUtilities.INSTANCE.populateUserHexEncodedPublicKeyCacheIfNeeded(threadId, getContext()); // TODO: Terrible place to do this, but okay for now
|
||||
MentionManagerUtilities.INSTANCE.populateUserHexEncodedPublicKeyCacheIfNeeded(threadId, getContext()); // TODO: Terrible place to do this, but okay for now
|
||||
snippet = MentionUtilities.highlightMentions(snippet, threadId, getContext());
|
||||
return snippet.length() <= MAX_SNIPPET_LENGTH ? snippet : snippet.subSequence(0, MAX_SNIPPET_LENGTH);
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ import org.whispersystems.signalservice.api.crypto.ProfileCipher;
|
||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||
import org.whispersystems.signalservice.loki.api.LokiDotNetAPI;
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
||||
import org.whispersystems.signalservice.loki.api.publicchats.LokiPublicChatAPI;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
@ -406,7 +406,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
||||
String newProfileKey = ProfileKeyUtil.generateEncodedProfileKey(context);
|
||||
byte[] profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(newProfileKey);
|
||||
|
||||
//Loki - Upload the profile photo here
|
||||
// Loki - Upload the profile photo here
|
||||
if (avatar != null) {
|
||||
Log.d("Loki", "Start uploading profile photo");
|
||||
LokiFileServerAPI storageAPI = LokiFileServerAPI.shared;
|
||||
@ -415,9 +415,9 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
Log.d("Loki", "Profile photo uploaded, the url is " + result.getUrl());
|
||||
TextSecurePreferences.setProfileAvatarUrl(context, result.getUrl());
|
||||
TextSecurePreferences.setProfilePictureURL(context, result.getUrl());
|
||||
} else {
|
||||
TextSecurePreferences.setProfileAvatarUrl(context, null);
|
||||
TextSecurePreferences.setProfilePictureURL(context, null);
|
||||
}
|
||||
|
||||
AvatarHelper.setAvatar(context, Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)), avatarBytes);
|
||||
@ -427,7 +427,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
||||
ProfileKeyUtil.setEncodedProfileKey(context, newProfileKey);
|
||||
|
||||
// Update profile key on the public chat server
|
||||
ApplicationContext.getInstance(context).updatePublicChatProfilePictureIfNeeded();
|
||||
ApplicationContext.getInstance(context).updateOpenGroupProfilePicturesIfNeeded();
|
||||
} catch (Exception e) {
|
||||
Log.d("Loki", "Failed to upload profile photo: " + e);
|
||||
return false;
|
||||
|
@ -18,7 +18,7 @@ import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.thoughtcrime.securesms.database.SmsMigrator.ProgressDescription;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.service.ApplicationMigrationService;
|
||||
import org.thoughtcrime.securesms.service.ApplicationMigrationService.ImportState;
|
||||
|
||||
|
@ -25,8 +25,8 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.loaders.DeviceListLoader;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.devicelist.Device;
|
||||
import org.thoughtcrime.securesms.loki.redesign.dialogs.DeviceEditingOptionsBottomSheet;
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.MnemonicUtilities;
|
||||
import org.thoughtcrime.securesms.loki.dialogs.DeviceEditingOptionsBottomSheet;
|
||||
import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.whispersystems.libsignal.util.guava.Function;
|
||||
@ -39,7 +39,7 @@ import kotlin.Pair;
|
||||
import kotlin.Unit;
|
||||
import network.loki.messenger.R;
|
||||
|
||||
import static org.thoughtcrime.securesms.loki.GeneralUtilitiesKt.toPx;
|
||||
import static org.thoughtcrime.securesms.loki.utilities.GeneralUtilitiesKt.toPx;
|
||||
|
||||
public class DeviceListFragment extends ListFragment
|
||||
implements LoaderManager.LoaderCallbacks<List<Device>>,
|
||||
|
@ -19,7 +19,7 @@ import com.nineoldandroids.animation.ArgbEvaluator;
|
||||
|
||||
import org.thoughtcrime.securesms.IntroPagerAdapter.IntroPage;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
@ -43,7 +43,6 @@ import com.bumptech.glide.request.transition.Transition;
|
||||
import org.thoughtcrime.securesms.avatar.AvatarSelection;
|
||||
import org.thoughtcrime.securesms.components.PushRecipientsPanel;
|
||||
import org.thoughtcrime.securesms.components.PushRecipientsPanel.RecipientsPanelChangedListener;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.contacts.RecipientsEditor;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
|
||||
@ -57,6 +56,8 @@ import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager.GroupActionResult;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment;
|
||||
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
@ -321,11 +322,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(GroupCreateActivity.this, PushContactSelectionActivity.class);
|
||||
if (groupToUpdate.isPresent()) {
|
||||
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_PUSH);
|
||||
} else {
|
||||
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_PUSH | DisplayMode.FLAG_SMS);
|
||||
}
|
||||
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_FRIENDS);
|
||||
startActivityForResult(intent, PICK_CONTACT);
|
||||
}
|
||||
}
|
||||
|
@ -26,9 +26,10 @@ import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.components.ContactFilterToolbar;
|
||||
import org.thoughtcrime.securesms.components.ContactFilterToolbar.OnFilterChangedListener;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment;
|
||||
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
@ -40,7 +41,7 @@ import java.util.concurrent.ExecutionException;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
public class InviteActivity extends PassphraseRequiredActionBarActivity implements ContactSelectionListFragment.OnContactSelectedListener {
|
||||
public class InviteActivity extends PassphraseRequiredActionBarActivity {
|
||||
|
||||
private ContactSelectionListFragment contactsFragment;
|
||||
private EditText inviteText;
|
||||
@ -52,7 +53,7 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState, boolean ready) {
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_SMS);
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_FRIENDS);
|
||||
getIntent().putExtra(ContactSelectionListFragment.MULTI_SELECT, true);
|
||||
getIntent().putExtra(ContactSelectionListFragment.REFRESHABLE, false);
|
||||
|
||||
@ -84,7 +85,6 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||
heart.getViewTreeObserver().addOnPreDrawListener(new HeartPreDrawListener());
|
||||
}
|
||||
contactsFragment.setOnContactSelectedListener(this);
|
||||
shareButton.setOnClickListener(new ShareClickListener());
|
||||
smsButton.setOnClickListener(new SmsClickListener());
|
||||
smsCancelButton.setOnClickListener(new SmsCancelClickListener());
|
||||
@ -99,12 +99,10 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
return animation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContactSelected(String number) {
|
||||
updateSmsButtonText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContactDeselected(String number) {
|
||||
updateSmsButtonText();
|
||||
}
|
||||
@ -132,7 +130,6 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
}
|
||||
|
||||
private void cancelSmsSelection() {
|
||||
contactsFragment.reset();
|
||||
updateSmsButtonText();
|
||||
ViewUtil.animateOut(smsSendFrame, slideOutAnimation, View.GONE);
|
||||
}
|
||||
@ -241,7 +238,6 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
ViewUtil.animateOut(smsSendFrame, slideOutAnimation, View.GONE).addListener(new Listener<Boolean>() {
|
||||
@Override
|
||||
public void onSuccess(Boolean result) {
|
||||
contactsFragment.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -47,7 +47,7 @@ import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.loaders.MessageDetailsLoader;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
|
@ -13,9 +13,9 @@ import android.support.v4.app.Fragment;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.LandingActivity;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.SeedActivity;
|
||||
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.loki.activities.LandingActivity;
|
||||
import org.thoughtcrime.securesms.loki.activities.SeedActivity;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
@ -19,6 +19,8 @@ package org.thoughtcrime.securesms;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -618,7 +618,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif
|
||||
unidentifiedAccessKey, universalUnidentifiedAccess);
|
||||
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(RegistrationActivity.this);
|
||||
List<PreKeyRecord> records = PreKeyUtil.generatePreKeys(RegistrationActivity.this);
|
||||
List<PreKeyRecord> records = PreKeyUtil.generatePreKeyRecords(RegistrationActivity.this);
|
||||
SignedPreKeyRecord signedPreKey = PreKeyUtil.generateSignedPreKey(RegistrationActivity.this, identityKey, true);
|
||||
|
||||
accountManager.setPreKeys(identityKey.getPublicKey(), signedPreKey, records);
|
||||
|
@ -29,19 +29,19 @@ import android.os.Process;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.thoughtcrime.securesms.components.SearchToolbar;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
|
||||
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.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment;
|
||||
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.mediasend.Media;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
@ -52,7 +52,6 @@ import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.FileUtils;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
@ -68,7 +67,7 @@ import network.loki.messenger.R;
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
implements ContactSelectionListFragment.OnContactSelectedListener, SwipeRefreshLayout.OnRefreshListener
|
||||
implements ContactSelectionListFragment.OnContactSelectedListener
|
||||
{
|
||||
private static final String TAG = ShareActivity.class.getSimpleName();
|
||||
|
||||
@ -96,14 +95,10 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle, boolean ready) {
|
||||
if (!getIntent().hasExtra(ContactSelectionListFragment.DISPLAY_MODE)) {
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE,
|
||||
TextSecurePreferences.isSmsEnabled(this)
|
||||
? DisplayMode.FLAG_ALL
|
||||
: DisplayMode.FLAG_PUSH | DisplayMode.FLAG_GROUPS);
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_ALL);
|
||||
}
|
||||
|
||||
getIntent().putExtra(ContactSelectionListFragment.REFRESHABLE, false);
|
||||
getIntent().putExtra(ContactSelectionListFragment.RECENTS, true);
|
||||
|
||||
setContentView(R.layout.share_activity);
|
||||
|
||||
@ -170,7 +165,6 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
searchAction = findViewById(R.id.search_action);
|
||||
contactsFragment = (ContactSelectionListFragment) getSupportFragmentManager().findFragmentById(R.id.contact_selection_list_fragment);
|
||||
contactsFragment.setOnContactSelectedListener(this);
|
||||
contactsFragment.setOnRefreshListener(this);
|
||||
}
|
||||
|
||||
private void initializeSearch() {
|
||||
@ -281,12 +275,6 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
public void onContactDeselected(String number) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
|
@ -11,7 +11,7 @@ import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions;
|
||||
|
||||
|
@ -80,7 +80,7 @@ public class AvatarImageView extends AppCompatImageView {
|
||||
setOutlineProvider(new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
outline.setOval(0, 0, view.getWidth(), view.getHeight());
|
||||
outline.setOval(0, 0, view.getWidth(), view.getHeight());
|
||||
}
|
||||
});
|
||||
setClipToOutline(true);
|
||||
@ -132,11 +132,11 @@ public class AvatarImageView extends AppCompatImageView {
|
||||
|
||||
if (photo.contactPhoto != null) {
|
||||
requestManager.load(photo.contactPhoto)
|
||||
.fallback(fallbackContactPhotoDrawable)
|
||||
.error(fallbackContactPhotoDrawable)
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.circleCrop()
|
||||
.into(this);
|
||||
.fallback(fallbackContactPhotoDrawable)
|
||||
.error(fallbackContactPhotoDrawable)
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.circleCrop()
|
||||
.into(this);
|
||||
} else {
|
||||
setImageDrawable(fallbackContactPhotoDrawable);
|
||||
}
|
||||
@ -184,9 +184,9 @@ public class AvatarImageView extends AppCompatImageView {
|
||||
if (other == null) return false;
|
||||
|
||||
return other.recipient.equals(recipient) &&
|
||||
other.recipient.getColor().equals(recipient.getColor()) &&
|
||||
other.ready == ready &&
|
||||
Objects.equals(other.contactPhoto, contactPhoto);
|
||||
other.recipient.getColor().equals(recipient.getColor()) &&
|
||||
other.ready == ready &&
|
||||
Objects.equals(other.contactPhoto, contactPhoto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import org.thoughtcrime.securesms.conversation.ConversationStickerSuggestionAdap
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.MentionUtilities;
|
||||
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.QuoteModel;
|
||||
|
@ -75,7 +75,6 @@ public class LinkPreviewView extends FrameLayout {
|
||||
container.setBackgroundColor(Color.TRANSPARENT);
|
||||
container.setPadding(0, 0, 0, 0);
|
||||
divider.setVisibility(VISIBLE);
|
||||
// closeButton.setVisibility(VISIBLE);
|
||||
|
||||
closeButton.setOnClickListener(v -> {
|
||||
if (closeClickedListener != null) {
|
||||
|
@ -31,7 +31,7 @@ import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.loki.api.publicchats.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -108,11 +108,7 @@ public class SendButton extends AppCompatImageButton
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
// if (isEnabled() && transportOptions.getEnabledTransports().size() > 1) {
|
||||
// getTransportOptionsPopup().display(transportOptions.getEnabledTransports());
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// Loki - Do nothing
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -200,7 +200,6 @@ public class TransferControlView extends FrameLayout {
|
||||
|
||||
if (view != null) {
|
||||
view.setVisibility(VISIBLE);
|
||||
// setVisibility(VISIBLE);
|
||||
} else {
|
||||
setVisibility(GONE);
|
||||
}
|
||||
|
@ -9,17 +9,16 @@ import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.jobs.TypingSendJob;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.loki.api.multidevice.LokiDeviceLinkUtilities;
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
@SuppressLint("UseSparseArrays")
|
||||
public class TypingStatusSender {
|
||||
|
||||
@ -82,24 +81,17 @@ public class TypingStatusSender {
|
||||
}
|
||||
|
||||
private void sendTyping(long threadId, boolean typingStarted) {
|
||||
LokiFileServerAPI storageAPI = LokiFileServerAPI.Companion.getShared();
|
||||
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||
Recipient recipient = threadDatabase.getRecipientForThreadId(threadId);
|
||||
|
||||
if (recipient == null) {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new TypingSendJob(threadId, typingStarted));
|
||||
return;
|
||||
// Loki - Check whether we want to send a typing indicator to this user
|
||||
if (!SessionMetaProtocol.shouldSendTypingIndicator(recipient, context)) { return; }
|
||||
// Loki - Take into account multi device
|
||||
Set<String> linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(recipient.getAddress().serialize());
|
||||
for (String device : linkedDevices) {
|
||||
Recipient deviceAsRecipient = Recipient.from(context, Address.fromSerialized(device), false);
|
||||
long deviceThreadID = threadDatabase.getThreadIdFor(deviceAsRecipient);
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new TypingSendJob(deviceThreadID, typingStarted));
|
||||
}
|
||||
LokiDeviceLinkUtilities.INSTANCE.getAllLinkedDeviceHexEncodedPublicKeys(recipient.getAddress().serialize()).success(devices -> {
|
||||
for (String device : devices) {
|
||||
Recipient deviceRecipient = Recipient.from(context, Address.fromSerialized(device), false);
|
||||
long deviceThreadID = threadDatabase.getThreadIdIfExistsFor(deviceRecipient);
|
||||
if (deviceThreadID > -1) {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new TypingSendJob(deviceThreadID, typingStarted));
|
||||
}
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
|
||||
private class StartRunnable implements Runnable {
|
||||
|
@ -8,9 +8,9 @@ import android.provider.Telephony;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
public class DefaultSmsReminder extends Reminder {
|
||||
|
||||
@ -40,14 +40,5 @@ public class DefaultSmsReminder extends Reminder {
|
||||
|
||||
public static boolean isEligible(Context context) {
|
||||
return false;
|
||||
// Loki - Original code
|
||||
// ========
|
||||
// final boolean isDefault = Util.isDefaultSmsProvider(context);
|
||||
// if (isDefault) {
|
||||
// TextSecurePreferences.setPromptedDefaultSmsProvider(context, false);
|
||||
// }
|
||||
//
|
||||
// return !isDefault && !TextSecurePreferences.hasPromptedDefaultSmsProvider(context);
|
||||
// ========
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.View.OnClickListener;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
import org.thoughtcrime.securesms.RegistrationActivity;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
public class PushRegistrationReminder extends Reminder {
|
||||
|
||||
@ -30,9 +30,5 @@ public class PushRegistrationReminder extends Reminder {
|
||||
|
||||
public static boolean isEligible(Context context) {
|
||||
return false;
|
||||
// Loki - Original code
|
||||
// ========
|
||||
// return !TextSecurePreferences.isPushRegistered(context);
|
||||
// ========
|
||||
}
|
||||
}
|
||||
|
@ -1,271 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.contacts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.database.Cursor;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
import org.thoughtcrime.securesms.components.RecyclerViewFastScroller.FastScrollAdapter;
|
||||
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter.HeaderViewHolder;
|
||||
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter.ViewHolder;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.util.StickyHeaderDecoration.StickyHeaderAdapter;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* List adapter to display all contacts and their related information
|
||||
*
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewHolder>
|
||||
implements FastScrollAdapter,
|
||||
StickyHeaderAdapter<HeaderViewHolder>
|
||||
{
|
||||
private final static String TAG = ContactSelectionListAdapter.class.getSimpleName();
|
||||
|
||||
private static final int VIEW_TYPE_CONTACT = 0;
|
||||
private static final int VIEW_TYPE_DIVIDER = 1;
|
||||
|
||||
private final static int STYLE_ATTRIBUTES[] = new int[]{R.attr.contact_selection_push_user,
|
||||
R.attr.contact_selection_lay_user};
|
||||
|
||||
private final boolean multiSelect;
|
||||
private final LayoutInflater li;
|
||||
private final TypedArray drawables;
|
||||
private final ItemClickListener clickListener;
|
||||
private final GlideRequests glideRequests;
|
||||
|
||||
private final Set<String> selectedContacts = new HashSet<>();
|
||||
|
||||
public abstract static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
public abstract void bind(@NonNull GlideRequests glideRequests, int type, String name, String number, String label, int color, boolean multiSelect);
|
||||
public abstract void unbind(@NonNull GlideRequests glideRequests);
|
||||
public abstract void setChecked(boolean checked);
|
||||
}
|
||||
|
||||
public static class ContactViewHolder extends ViewHolder {
|
||||
ContactViewHolder(@NonNull final View itemView,
|
||||
@Nullable final ItemClickListener clickListener)
|
||||
{
|
||||
super(itemView);
|
||||
itemView.setOnClickListener(v -> {
|
||||
if (clickListener != null) clickListener.onItemClick(getView());
|
||||
});
|
||||
}
|
||||
|
||||
public ContactSelectionListItem getView() {
|
||||
return (ContactSelectionListItem) itemView;
|
||||
}
|
||||
|
||||
public void bind(@NonNull GlideRequests glideRequests, int type, String name, String number, String label, int color, boolean multiSelect) {
|
||||
getView().set(glideRequests, type, name, number, label, color, multiSelect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind(@NonNull GlideRequests glideRequests) {
|
||||
getView().unbind(glideRequests);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChecked(boolean checked) {
|
||||
getView().setChecked(checked);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DividerViewHolder extends ViewHolder {
|
||||
|
||||
private final TextView label;
|
||||
|
||||
DividerViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
this.label = itemView.findViewById(R.id.label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(@NonNull GlideRequests glideRequests, int type, String name, String number, String label, int color, boolean multiSelect) {
|
||||
this.label.setText(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind(@NonNull GlideRequests glideRequests) {}
|
||||
|
||||
@Override
|
||||
public void setChecked(boolean checked) {}
|
||||
}
|
||||
|
||||
static class HeaderViewHolder extends RecyclerView.ViewHolder {
|
||||
HeaderViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
public ContactSelectionListAdapter(@NonNull Context context,
|
||||
@NonNull GlideRequests glideRequests,
|
||||
@Nullable Cursor cursor,
|
||||
@Nullable ItemClickListener clickListener,
|
||||
boolean multiSelect)
|
||||
{
|
||||
super(context, cursor);
|
||||
this.li = LayoutInflater.from(context);
|
||||
this.glideRequests = glideRequests;
|
||||
this.drawables = context.obtainStyledAttributes(STYLE_ATTRIBUTES);
|
||||
this.multiSelect = multiSelect;
|
||||
this.clickListener = clickListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getHeaderId(int i) {
|
||||
if (!isActiveCursor()) return -1;
|
||||
|
||||
int contactType = getContactType(i);
|
||||
|
||||
if (contactType == ContactsDatabase.DIVIDER_TYPE) return -1;
|
||||
return Util.hashCode(getHeaderString(i), getContactType(i));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
|
||||
if (viewType == VIEW_TYPE_CONTACT) {
|
||||
return new ContactViewHolder(li.inflate(R.layout.contact_selection_list_item, parent, false), clickListener);
|
||||
} else {
|
||||
return new DividerViewHolder(li.inflate(R.layout.contact_selection_list_divider, parent, false));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindItemViewHolder(ViewHolder viewHolder, @NonNull Cursor cursor) {
|
||||
int contactType = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN));
|
||||
String name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN));
|
||||
String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_COLUMN));
|
||||
int numberType = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_TYPE_COLUMN));
|
||||
String label = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.LABEL_COLUMN));
|
||||
String labelText = ContactsContract.CommonDataKinds.Phone.getTypeLabel(getContext().getResources(),
|
||||
numberType, label).toString();
|
||||
|
||||
int color = (contactType == ContactsDatabase.PUSH_TYPE) ? drawables.getColor(0, 0xa0000000) :
|
||||
drawables.getColor(1, 0xff000000);
|
||||
|
||||
viewHolder.unbind(glideRequests);
|
||||
viewHolder.bind(glideRequests, contactType, name, number, labelText, color, multiSelect);
|
||||
viewHolder.setChecked(selectedContacts.contains(number));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(@NonNull Cursor cursor) {
|
||||
if (cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN)) == ContactsDatabase.DIVIDER_TYPE) {
|
||||
return VIEW_TYPE_DIVIDER;
|
||||
} else {
|
||||
return VIEW_TYPE_CONTACT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent) {
|
||||
return new HeaderViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.contact_selection_recyclerview_header, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindHeaderViewHolder(HeaderViewHolder viewHolder, int position) {
|
||||
((TextView)viewHolder.itemView).setText(getSpannedHeaderString(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemViewRecycled(ViewHolder holder) {
|
||||
holder.unbind(glideRequests);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getBubbleText(int position) {
|
||||
return getHeaderString(position);
|
||||
}
|
||||
|
||||
public Set<String> getSelectedContacts() {
|
||||
return selectedContacts;
|
||||
}
|
||||
|
||||
private CharSequence getSpannedHeaderString(int position) {
|
||||
final String headerString = getHeaderString(position);
|
||||
if (isPush(position)) {
|
||||
SpannableString spannable = new SpannableString(headerString);
|
||||
spannable.setSpan(new ForegroundColorSpan(getContext().getResources().getColor(R.color.signal_primary)), 0, headerString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return spannable;
|
||||
} else {
|
||||
return headerString;
|
||||
}
|
||||
}
|
||||
|
||||
private @NonNull String getHeaderString(int position) {
|
||||
int contactType = getContactType(position);
|
||||
|
||||
if (contactType == ContactsDatabase.RECENT_TYPE || contactType == ContactsDatabase.DIVIDER_TYPE) {
|
||||
return " ";
|
||||
}
|
||||
|
||||
Cursor cursor = getCursorAtPositionOrThrow(position);
|
||||
String letter = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN));
|
||||
|
||||
if (!TextUtils.isEmpty(letter)) {
|
||||
String firstChar = letter.trim().substring(0, 1).toUpperCase();
|
||||
if (Character.isLetterOrDigit(firstChar.codePointAt(0))) {
|
||||
return firstChar;
|
||||
}
|
||||
}
|
||||
|
||||
return "#";
|
||||
}
|
||||
|
||||
private int getContactType(int position) {
|
||||
final Cursor cursor = getCursorAtPositionOrThrow(position);
|
||||
return cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN));
|
||||
}
|
||||
|
||||
private boolean isPush(int position) {
|
||||
return getContactType(position) == ContactsDatabase.PUSH_TYPE;
|
||||
}
|
||||
|
||||
public interface ItemClickListener {
|
||||
void onItemClick(ContactSelectionListItem item);
|
||||
}
|
||||
}
|
@ -1,161 +0,0 @@
|
||||
package org.thoughtcrime.securesms.contacts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.ProfilePictureView;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPI;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
public class ContactSelectionListItem extends LinearLayout implements RecipientModifiedListener {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = ContactSelectionListItem.class.getSimpleName();
|
||||
|
||||
private ProfilePictureView profilePictureView;
|
||||
private TextView numberView;
|
||||
private TextView nameView;
|
||||
private TextView labelView;
|
||||
private CheckBox checkBox;
|
||||
|
||||
private String number;
|
||||
private Recipient recipient;
|
||||
private GlideRequests glideRequests;
|
||||
private long threadID;
|
||||
|
||||
public ContactSelectionListItem(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public ContactSelectionListItem(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
this.profilePictureView = findViewById(R.id.profilePictureView);
|
||||
this.numberView = findViewById(R.id.number);
|
||||
this.labelView = findViewById(R.id.label);
|
||||
this.nameView = findViewById(R.id.name);
|
||||
this.checkBox = findViewById(R.id.check_box);
|
||||
|
||||
ViewUtil.setTextViewGravityStart(this.nameView, getContext());
|
||||
}
|
||||
|
||||
public void set(@NonNull GlideRequests glideRequests, int type, String name, String number, String label, int color, boolean multiSelect) {
|
||||
this.glideRequests = glideRequests;
|
||||
this.number = number;
|
||||
|
||||
if (type == ContactsDatabase.NEW_TYPE) {
|
||||
this.recipient = null;
|
||||
} else if (!TextUtils.isEmpty(number)) {
|
||||
Address address = Address.fromExternal(getContext(), number);
|
||||
this.recipient = Recipient.from(getContext(), address, true);
|
||||
this.recipient.addListener(this);
|
||||
|
||||
if (this.recipient.getName() != null) {
|
||||
name = this.recipient.getName();
|
||||
}
|
||||
}
|
||||
|
||||
threadID = DatabaseFactory.getThreadDatabase(getContext()).getThreadIdFor(recipient);
|
||||
|
||||
this.numberView.setTextColor(color);
|
||||
updateProfilePicture(glideRequests, name, threadID);
|
||||
|
||||
if (!multiSelect && recipient != null && recipient.isLocalNumber()) {
|
||||
name = getContext().getString(R.string.note_to_self);
|
||||
}
|
||||
|
||||
setText(type, name, number, label);
|
||||
|
||||
if (multiSelect) this.checkBox.setVisibility(View.VISIBLE);
|
||||
else this.checkBox.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void setChecked(boolean selected) {
|
||||
this.checkBox.setChecked(selected);
|
||||
}
|
||||
|
||||
public void unbind(GlideRequests glideRequests) {
|
||||
if (recipient != null) {
|
||||
recipient.removeListener(this);
|
||||
recipient = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setText(int type, String name, String number, String label) {
|
||||
if (number == null || number.isEmpty() || GroupUtil.isEncodedGroup(number)) {
|
||||
this.nameView.setEnabled(false);
|
||||
this.numberView.setText("");
|
||||
this.labelView.setVisibility(View.GONE);
|
||||
} else if (type == ContactsDatabase.PUSH_TYPE) {
|
||||
this.numberView.setText(number);
|
||||
this.nameView.setEnabled(true);
|
||||
this.labelView.setVisibility(View.GONE);
|
||||
} else {
|
||||
this.numberView.setText(number);
|
||||
this.nameView.setEnabled(true);
|
||||
this.labelView.setText(label);
|
||||
this.labelView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
this.nameView.setText(name);
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(final Recipient recipient) {
|
||||
if (this.recipient == recipient) {
|
||||
Util.runOnMain(() -> {
|
||||
threadID = DatabaseFactory.getThreadDatabase(getContext()).getThreadIdFor(recipient);
|
||||
updateProfilePicture(glideRequests, recipient.getName(), threadID);
|
||||
nameView.setText(recipient.toShortString());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateProfilePicture(GlideRequests glide, String name, long threadID) {
|
||||
if (this.recipient.isGroupRecipient()) {
|
||||
Set<String> usersAsSet = LokiAPI.Companion.getUserHexEncodedPublicKeyCache().get(threadID);
|
||||
if (usersAsSet == null) {
|
||||
usersAsSet = new HashSet<>();
|
||||
}
|
||||
ArrayList<String> users = new ArrayList<>(usersAsSet);
|
||||
Collections.sort(users); // Sort to provide a level of stability
|
||||
profilePictureView.setHexEncodedPublicKey(users.size() > 0 ? users.get(0) : "");
|
||||
profilePictureView.setAdditionalHexEncodedPublicKey(users.size() > 1 ? users.get(1) : "");
|
||||
profilePictureView.setRSSFeed(name.equals("Loki News") || name.equals("Session Updates"));
|
||||
} else {
|
||||
profilePictureView.setHexEncodedPublicKey(this.number);
|
||||
profilePictureView.setAdditionalHexEncodedPublicKey(null);
|
||||
profilePictureView.setRSSFeed(false);
|
||||
}
|
||||
profilePictureView.glide = glide;
|
||||
profilePictureView.update();
|
||||
}
|
||||
}
|
@ -139,7 +139,6 @@ import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns.Types;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.database.identity.IdentityRecordList;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
@ -155,16 +154,17 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
|
||||
import org.thoughtcrime.securesms.loki.LokiThreadDatabaseDelegate;
|
||||
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
|
||||
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.MentionCandidateSelectionView;
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.SessionRestoreBannerView;
|
||||
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabaseDelegate;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.FriendRequestProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
||||
import org.thoughtcrime.securesms.loki.views.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.loki.views.MentionCandidateSelectionView;
|
||||
import org.thoughtcrime.securesms.loki.views.SessionRestoreBannerView;
|
||||
import org.thoughtcrime.securesms.mediasend.Media;
|
||||
import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentManager;
|
||||
@ -214,7 +214,6 @@ import org.thoughtcrime.securesms.util.Dialogs;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||
@ -228,13 +227,12 @@ import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
|
||||
import org.thoughtcrime.securesms.util.views.Stub;
|
||||
import org.whispersystems.libsignal.InvalidMessageException;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.loki.api.multidevice.DeviceLink;
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPI;
|
||||
import org.whispersystems.signalservice.loki.api.multidevice.LokiDeviceLinkUtilities;
|
||||
import org.whispersystems.signalservice.loki.api.publicchats.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus;
|
||||
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus;
|
||||
import org.whispersystems.signalservice.loki.messaging.Mention;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.protocol.mentions.Mention;
|
||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
|
||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol;
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus;
|
||||
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -242,7 +240,6 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -326,7 +323,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private MenuItem searchViewItem;
|
||||
private ProgressBar messageStatusProgressBar;
|
||||
private ImageView muteIndicatorImageView;
|
||||
private TextView subtitleTextView;
|
||||
private TextView subtitleTextView;
|
||||
|
||||
private AttachmentTypeSelector attachmentTypeSelector;
|
||||
private AttachmentManager attachmentManager;
|
||||
@ -357,7 +354,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private final DynamicNoActionBarTheme dynamicTheme = new DynamicNoActionBarTheme();
|
||||
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||
|
||||
// Message Status Bar
|
||||
// Message status bar
|
||||
private ArrayList<BroadcastReceiver> broadcastReceivers = new ArrayList<>();
|
||||
private String messageStatus = null;
|
||||
|
||||
@ -368,9 +365,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private ArrayList<Mention> mentions = new ArrayList<>();
|
||||
private String oldText = "";
|
||||
|
||||
// Multi Device
|
||||
private boolean isFriendsWithAnyDevice = false;
|
||||
|
||||
// Restoration
|
||||
protected SessionRestoreBannerView sessionRestoreBannerView;
|
||||
|
||||
@ -458,7 +452,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
});
|
||||
|
||||
sessionRestoreBannerView.setOnRestore(() -> {
|
||||
this.restoreSession();
|
||||
SessionManagementProtocol.startSessionReset(this, recipient, threadId);
|
||||
updateSessionRestoreBanner();
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
sessionRestoreBannerView.setOnDismiss(() -> {
|
||||
@ -468,7 +463,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
|
||||
LokiAPIUtilities.INSTANCE.populateUserHexEncodedPublicKeyCacheIfNeeded(threadId, this);
|
||||
MentionManagerUtilities.INSTANCE.populateUserHexEncodedPublicKeyCacheIfNeeded(threadId, this);
|
||||
|
||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||
if (publicChat != null) {
|
||||
@ -559,6 +554,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
markThreadAsRead();
|
||||
|
||||
DatabaseFactory.getLokiThreadDatabase(this).setDelegate(this);
|
||||
|
||||
updateInputPanel();
|
||||
|
||||
updateSessionRestoreBanner();
|
||||
@ -665,9 +661,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
*/
|
||||
case PICK_GIF:
|
||||
setMedia(data.getData(),
|
||||
MediaType.GIF,
|
||||
data.getIntExtra(GiphyActivity.EXTRA_WIDTH, 0),
|
||||
data.getIntExtra(GiphyActivity.EXTRA_HEIGHT, 0));
|
||||
MediaType.GIF,
|
||||
data.getIntExtra(GiphyActivity.EXTRA_WIDTH, 0),
|
||||
data.getIntExtra(GiphyActivity.EXTRA_HEIGHT, 0));
|
||||
break;
|
||||
case SMS_DEFAULT:
|
||||
initializeSecurity(isSecureText, isDefaultSms);
|
||||
@ -747,7 +743,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
MenuInflater inflater = this.getMenuInflater();
|
||||
menu.clear();
|
||||
|
||||
boolean isOpenGroupOrRSSFeed = recipient.getAddress().isPublicChat() || recipient.getAddress().isRSSFeed();
|
||||
boolean isOpenGroupOrRSSFeed = recipient.getAddress().isOpenGroup() || recipient.getAddress().isRSSFeed();
|
||||
|
||||
if (isSecureText && !isOpenGroupOrRSSFeed) {
|
||||
if (recipient.getExpireMessages() > 0) {
|
||||
@ -887,7 +883,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
case R.id.menu_invite: handleInviteLink(); return true;
|
||||
case R.id.menu_mute_notifications: handleMuteNotifications(); return true;
|
||||
case R.id.menu_unmute_notifications: handleUnmuteNotifications(); return true;
|
||||
// case R.id.menu_conversation_settings: handleConversationSettings(); return true;
|
||||
// case R.id.menu_conversation_settings: handleConversationSettings(); return true;
|
||||
case R.id.menu_expiring_messages_off:
|
||||
case R.id.menu_expiring_messages: handleSelectMessageExpiration(); return true;
|
||||
case android.R.id.home: handleReturnToConversationList(); return true;
|
||||
@ -1154,7 +1150,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
builder.setMessage(getString(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group));
|
||||
builder.setPositiveButton(R.string.yes, (dialog, which) -> {
|
||||
Recipient groupRecipient = getRecipient();
|
||||
if (GroupUtil.leaveGroup(this, groupRecipient)) {
|
||||
if (ClosedGroupsProtocol.leaveGroup(this, groupRecipient)) {
|
||||
initializeEnabledCheck();
|
||||
} else {
|
||||
Toast.makeText(this, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show();
|
||||
@ -1240,11 +1236,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private boolean handleDisplayQuickContact() {
|
||||
return !recipient.getAddress().isGroup();
|
||||
|
||||
// if (recipient.getContactUri() != null) {
|
||||
// ContactsContract.QuickContact.showQuickContact(ConversationActivity.this, titleView, recipient.getContactUri(), ContactsContract.QuickContact.MODE_LARGE, null);
|
||||
// } else {
|
||||
// handleAddToContacts();
|
||||
// }
|
||||
/*
|
||||
if (recipient.getContactUri() != null) {
|
||||
ContactsContract.QuickContact.showQuickContact(ConversationActivity.this, titleView, recipient.getContactUri(), ContactsContract.QuickContact.MODE_LARGE, null);
|
||||
} else {
|
||||
handleAddToContacts();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private void handleAddAttachment() {
|
||||
@ -1531,7 +1529,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateSessionRestoreBanner() {
|
||||
private void updateSessionRestoreBanner() {
|
||||
Set<String> devices = DatabaseFactory.getLokiThreadDatabase(this).getSessionRestoreDevices(threadId);
|
||||
if (devices.size() > 0) {
|
||||
sessionRestoreBannerView.update(recipient);
|
||||
@ -1617,30 +1615,30 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void initializeViews() {
|
||||
titleTextView = findViewById(R.id.titleTextView);
|
||||
buttonToggle = ViewUtil.findById(this, R.id.button_toggle);
|
||||
sendButton = ViewUtil.findById(this, R.id.send_button);
|
||||
attachButton = ViewUtil.findById(this, R.id.attach_button);
|
||||
composeText = ViewUtil.findById(this, R.id.embedded_text_editor);
|
||||
charactersLeft = ViewUtil.findById(this, R.id.space_left);
|
||||
emojiDrawerStub = ViewUtil.findStubById(this, R.id.emoji_drawer_stub);
|
||||
unblockButton = ViewUtil.findById(this, R.id.unblock_button);
|
||||
makeDefaultSmsButton = ViewUtil.findById(this, R.id.make_default_sms_button);
|
||||
registerButton = ViewUtil.findById(this, R.id.register_button);
|
||||
container = ViewUtil.findById(this, R.id.layout_container);
|
||||
reminderView = ViewUtil.findStubById(this, R.id.reminder_stub);
|
||||
unverifiedBannerView = ViewUtil.findStubById(this, R.id.unverified_banner_stub);
|
||||
groupShareProfileView = ViewUtil.findStubById(this, R.id.group_share_profile_view_stub);
|
||||
quickAttachmentToggle = ViewUtil.findById(this, R.id.quick_attachment_toggle);
|
||||
inlineAttachmentToggle = ViewUtil.findById(this, R.id.inline_attachment_container);
|
||||
inputPanel = ViewUtil.findById(this, R.id.bottom_panel);
|
||||
searchNav = ViewUtil.findById(this, R.id.conversation_search_nav);
|
||||
titleTextView = findViewById(R.id.titleTextView);
|
||||
buttonToggle = ViewUtil.findById(this, R.id.button_toggle);
|
||||
sendButton = ViewUtil.findById(this, R.id.send_button);
|
||||
attachButton = ViewUtil.findById(this, R.id.attach_button);
|
||||
composeText = ViewUtil.findById(this, R.id.embedded_text_editor);
|
||||
charactersLeft = ViewUtil.findById(this, R.id.space_left);
|
||||
emojiDrawerStub = ViewUtil.findStubById(this, R.id.emoji_drawer_stub);
|
||||
unblockButton = ViewUtil.findById(this, R.id.unblock_button);
|
||||
makeDefaultSmsButton = ViewUtil.findById(this, R.id.make_default_sms_button);
|
||||
registerButton = ViewUtil.findById(this, R.id.register_button);
|
||||
container = ViewUtil.findById(this, R.id.layout_container);
|
||||
reminderView = ViewUtil.findStubById(this, R.id.reminder_stub);
|
||||
unverifiedBannerView = ViewUtil.findStubById(this, R.id.unverified_banner_stub);
|
||||
groupShareProfileView = ViewUtil.findStubById(this, R.id.group_share_profile_view_stub);
|
||||
quickAttachmentToggle = ViewUtil.findById(this, R.id.quick_attachment_toggle);
|
||||
inlineAttachmentToggle = ViewUtil.findById(this, R.id.inline_attachment_container);
|
||||
inputPanel = ViewUtil.findById(this, R.id.bottom_panel);
|
||||
searchNav = ViewUtil.findById(this, R.id.conversation_search_nav);
|
||||
mentionCandidateSelectionViewContainer = ViewUtil.findById(this, R.id.mentionCandidateSelectionViewContainer);
|
||||
mentionCandidateSelectionView = ViewUtil.findById(this, R.id.userSelectionView);
|
||||
sessionRestoreBannerView = ViewUtil.findById(this, R.id.sessionRestoreBannerView);
|
||||
messageStatusProgressBar = ViewUtil.findById(this, R.id.messageStatusProgressBar);
|
||||
muteIndicatorImageView = ViewUtil.findById(this, R.id.muteIndicatorImageView);
|
||||
subtitleTextView = ViewUtil.findById(this, R.id.subtitleTextView);
|
||||
mentionCandidateSelectionView = ViewUtil.findById(this, R.id.userSelectionView);
|
||||
sessionRestoreBannerView = ViewUtil.findById(this, R.id.sessionRestoreBannerView);
|
||||
messageStatusProgressBar = ViewUtil.findById(this, R.id.messageStatusProgressBar);
|
||||
muteIndicatorImageView = ViewUtil.findById(this, R.id.muteIndicatorImageView);
|
||||
subtitleTextView = ViewUtil.findById(this, R.id.subtitleTextView);
|
||||
|
||||
ImageButton quickCameraToggle = ViewUtil.findById(this, R.id.quick_camera_toggle);
|
||||
ImageButton inlineAttachmentButton = ViewUtil.findById(this, R.id.inline_attachment_button);
|
||||
@ -1897,15 +1895,21 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
case AttachmentTypeSelector.TAKE_PHOTO:
|
||||
attachmentManager.capturePhoto(this, TAKE_PHOTO); break;
|
||||
case AttachmentTypeSelector.ADD_GIF:
|
||||
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) -> {
|
||||
boolean hasSeenGIFMetaDataWarning = TextSecurePreferences.hasSeenGIFMetaDataWarning(this);
|
||||
if (!hasSeenGIFMetaDataWarning) {
|
||||
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();
|
||||
TextSecurePreferences.setHasSeenGIFMetaDataWarning(this);
|
||||
} else {
|
||||
AttachmentManager.selectGif(this, PICK_GIF, !isSecureText);
|
||||
dialog.dismiss();
|
||||
});
|
||||
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss() );
|
||||
builder.create().show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2073,7 +2077,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void setGroupShareProfileReminder(@NonNull Recipient recipient) {
|
||||
if (recipient.isPushGroupRecipient() && !recipient.isProfileSharing() && !recipient.getAddress().isPublicChat() && !recipient.getAddress().isRSSFeed()) {
|
||||
if (recipient.isPushGroupRecipient() && !recipient.isProfileSharing() && !recipient.getAddress().isOpenGroup() && !recipient.getAddress().isRSSFeed()) {
|
||||
groupShareProfileView.get().setRecipient(recipient);
|
||||
groupShareProfileView.get().setVisibility(View.GONE); // Loki - Always hide for now
|
||||
} else if (groupShareProfileView.resolved()) {
|
||||
@ -2249,72 +2253,39 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
public void handleThreadFriendRequestStatusChanged(long threadID) {
|
||||
if (threadID != this.threadId) {
|
||||
Recipient threadRecipient = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadID);
|
||||
if (threadRecipient != null && !threadRecipient.isGroupRecipient()) {
|
||||
LokiDeviceLinkUtilities.INSTANCE.getAllLinkedDeviceHexEncodedPublicKeys(threadRecipient.getAddress().serialize()).success(devices -> {
|
||||
// We should update our input if this thread is a part of the other threads device
|
||||
if (devices.contains(recipient.getAddress().serialize())) {
|
||||
this.updateInputPanel();
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
return;
|
||||
if (recipient.isGroupRecipient()) { return; }
|
||||
boolean isUpdateNeeded = false;
|
||||
if (threadID == this.threadId) {
|
||||
isUpdateNeeded = true;
|
||||
} else {
|
||||
String thisThreadPublicKey = recipient.getAddress().serialize();
|
||||
Set<String> thisThreadAssociatedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(thisThreadPublicKey);
|
||||
Recipient changedThreadRecipient = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadID);
|
||||
String changedThreadPublicKey = changedThreadRecipient.getAddress().serialize();
|
||||
for (String device : thisThreadAssociatedDevices) {
|
||||
if (device.equals(changedThreadPublicKey)) { isUpdateNeeded = true; }
|
||||
}
|
||||
|
||||
this.updateInputPanel();
|
||||
}
|
||||
if (isUpdateNeeded) {
|
||||
updateInputPanel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSessionRestoreDevicesChanged(long threadId) {
|
||||
if (threadId == this.threadId) {
|
||||
public void handleSessionRestoreDevicesChanged(long threadID) {
|
||||
if (threadID == this.threadId) {
|
||||
runOnUiThread(this::updateSessionRestoreBanner);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateInputPanel() {
|
||||
/*
|
||||
isFriendsWithAnyDevice reflects whether we are friends with any of the other user's devices.
|
||||
|
||||
This fixes the case where the input panel disables and enables rapidly, which can occur when we are
|
||||
not friends with the current thread BUT multi device tells us that we are friends with another one of their devices.
|
||||
*/
|
||||
if (recipient.isGroupRecipient() || isNoteToSelf() || isFriendsWithAnyDevice) { setInputPanelEnabled(true); return; }
|
||||
|
||||
// Disable the input panel if a friend request is pending
|
||||
LokiThreadFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadDatabase(this).getFriendRequestStatus(threadId);
|
||||
boolean isPending = friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENDING || friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT || friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_RECEIVED;
|
||||
setInputPanelEnabled(!isPending);
|
||||
|
||||
// Always enable the input panel if we are friends with the current user
|
||||
isFriendsWithAnyDevice = (friendRequestStatus == LokiThreadFriendRequestStatus.FRIENDS);
|
||||
|
||||
if (!isFriendsWithAnyDevice) {
|
||||
// Enable the input panel if we don't have any pending friend requests OR we are friends with one of the user's linked devices
|
||||
MultiDeviceUtilities.hasPendingFriendRequestWithAnyLinkedDevice(this, recipient).success( hasPendingRequests -> {
|
||||
if (!hasPendingRequests) {
|
||||
setInputPanelEnabled(true);
|
||||
} else {
|
||||
MultiDeviceUtilities.isFriendsWithAnyLinkedDevice(this, recipient).success( isFriends -> {
|
||||
// Enable the input panel if we're friends with any of the user's devices
|
||||
isFriendsWithAnyDevice = isFriends;
|
||||
setInputPanelEnabled(isFriends);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void setInputPanelEnabled(boolean enabled) {
|
||||
boolean shouldInputPanelBeEnabled = FriendRequestProtocol.shouldInputPanelBeEnabled(this, recipient);
|
||||
Util.runOnMain(() -> {
|
||||
updateToggleButtonState();
|
||||
String hint = enabled ? "Message" : "Pending session request";
|
||||
String hint = shouldInputPanelBeEnabled ? "Message" : "Pending session request";
|
||||
inputPanel.setHint(hint);
|
||||
inputPanel.setEnabled(enabled);
|
||||
if (enabled && inputPanel.getVisibility() == View.VISIBLE) {
|
||||
inputPanel.setEnabled(shouldInputPanelBeEnabled);
|
||||
if (shouldInputPanelBeEnabled && inputPanel.getVisibility() == View.VISIBLE) {
|
||||
inputPanel.composeText.requestFocus();
|
||||
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
|
||||
inputMethodManager.showSoftInput(inputPanel.composeText, 0);
|
||||
@ -2370,7 +2341,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
Log.w(TAG, ex);
|
||||
}
|
||||
|
||||
if (messageStatus == null && !isGroupConversation()) {
|
||||
if (messageStatus == null && !isGroupConversation() && !SessionMetaProtocol.shared.isNoteToSelf(recipient.getAddress().serialize())) {
|
||||
messageStatus = "calculatingPoW";
|
||||
updateSubtitleTextView();
|
||||
updateMessageStatusProgressBar();
|
||||
@ -2425,7 +2396,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
// Loki - Send a friend request if we're not yet friends with the user in question
|
||||
LokiThreadFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadId);
|
||||
outgoingMessage.isFriendRequest = !isGroupConversation() && friendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS; // Needed for stageOutgoingMessage(...)
|
||||
outgoingMessage.isFriendRequest = !isGroupConversation() && friendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS
|
||||
&& !SessionMetaProtocol.shared.isNoteToSelf(recipient.getAddress().serialize()); // Needed for stageOutgoingMessage(...)
|
||||
|
||||
if (clearComposeBox) {
|
||||
inputPanel.clearQuote();
|
||||
@ -2477,7 +2449,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
// Loki - Send a friend request if we're not yet friends with the user in question
|
||||
LokiThreadFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadId);
|
||||
message.isFriendRequest = !isGroupConversation() && friendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS; // Needed for stageOutgoingMessage(...)
|
||||
message.isFriendRequest = !isGroupConversation() && friendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS
|
||||
&& !SessionMetaProtocol.shared.isNoteToSelf(recipient.getAddress().serialize()); // Needed for stageOutgoingMessage(...)
|
||||
|
||||
silentlySetComposeText("");
|
||||
final long id = fragment.stageOutgoingMessage(message);
|
||||
@ -2508,8 +2481,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void updateToggleButtonState() {
|
||||
// Don't allow attachments if we're not friends with any of the user's devices
|
||||
if (!isNoteToSelf() && !recipient.isGroupRecipient() && !isFriendsWithAnyDevice) {
|
||||
if (!FriendRequestProtocol.shouldAttachmentButtonBeEnabled(this, recipient)) {
|
||||
buttonToggle.display(sendButton);
|
||||
quickAttachmentToggle.hide();
|
||||
inlineAttachmentToggle.hide();
|
||||
@ -2745,7 +2717,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private void silentlySetComposeText(String text) {
|
||||
typingTextWatcher.setEnabled(false);
|
||||
composeText.setText(text);
|
||||
if (text.isEmpty()) resetMentions();
|
||||
if (text.isEmpty()) { resetMentions(); }
|
||||
typingTextWatcher.setEnabled(true);
|
||||
}
|
||||
|
||||
@ -2905,7 +2877,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
LokiThreadDatabase threadDatabase = DatabaseFactory.getLokiThreadDatabase(ConversationActivity.this);
|
||||
LokiUserDatabase userDatabase = DatabaseFactory.getLokiUserDatabase(ConversationActivity.this);
|
||||
if (lastCharacter == '@' && Character.isWhitespace(secondToLastCharacter)) {
|
||||
List<Mention> mentionCandidates = LokiAPI.Companion.getMentionCandidates("", threadId, userHexEncodedPublicKey, threadDatabase, userDatabase);
|
||||
List<Mention> mentionCandidates = MentionsManager.shared.getMentionCandidates("", threadId);
|
||||
currentMentionStartIndex = lastCharacterIndex;
|
||||
mentionCandidateSelectionViewContainer.setVisibility(View.VISIBLE);
|
||||
mentionCandidateSelectionView.show(mentionCandidates, threadId);
|
||||
@ -2916,7 +2888,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
} else {
|
||||
if (currentMentionStartIndex != -1) {
|
||||
String query = text.substring(currentMentionStartIndex + 1); // + 1 to get rid of the @
|
||||
List<Mention> mentionCandidates = LokiAPI.Companion.getMentionCandidates(query, threadId, userHexEncodedPublicKey, threadDatabase, userDatabase);
|
||||
List<Mention> mentionCandidates = MentionsManager.shared.getMentionCandidates(query, threadId);
|
||||
mentionCandidateSelectionViewContainer.setVisibility(View.VISIBLE);
|
||||
mentionCandidateSelectionView.show(mentionCandidates, threadId);
|
||||
}
|
||||
@ -2960,12 +2932,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
inputPanel.setQuote(GlideApp.with(this),
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
body,
|
||||
slideDeck,
|
||||
recipient,
|
||||
threadId);
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
body,
|
||||
slideDeck,
|
||||
recipient,
|
||||
threadId);
|
||||
|
||||
} else if (messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getLinkPreviews().isEmpty()) {
|
||||
LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0);
|
||||
@ -2976,20 +2948,20 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
inputPanel.setQuote(GlideApp.with(this),
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
messageRecord.getBody(),
|
||||
slideDeck,
|
||||
recipient,
|
||||
threadId);
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
messageRecord.getBody(),
|
||||
slideDeck,
|
||||
recipient,
|
||||
threadId);
|
||||
} else {
|
||||
inputPanel.setQuote(GlideApp.with(this),
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
messageRecord.getBody(),
|
||||
messageRecord.isMms() ? ((MmsMessageRecord) messageRecord).getSlideDeck() : new SlideDeck(),
|
||||
recipient,
|
||||
threadId);
|
||||
messageRecord.getDateSent(),
|
||||
author,
|
||||
messageRecord.getBody(),
|
||||
messageRecord.isMms() ? ((MmsMessageRecord) messageRecord).getSlideDeck() : new SlideDeck(),
|
||||
recipient,
|
||||
threadId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3106,17 +3078,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
// region Loki
|
||||
private void updateTitleTextView(Recipient recipient) {
|
||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
Set<DeviceLink> deviceLinks = DatabaseFactory.getLokiAPIDatabase(this).getDeviceLinks(userHexEncodedPublicKey);
|
||||
HashSet<String> userLinkedDeviceHexEncodedPublicKeys = new HashSet<>();
|
||||
for (DeviceLink deviceLink : deviceLinks) {
|
||||
userLinkedDeviceHexEncodedPublicKeys.add(deviceLink.getMasterHexEncodedPublicKey().toLowerCase());
|
||||
userLinkedDeviceHexEncodedPublicKeys.add(deviceLink.getSlaveHexEncodedPublicKey().toLowerCase());
|
||||
}
|
||||
userLinkedDeviceHexEncodedPublicKeys.add(userHexEncodedPublicKey.toLowerCase());
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
Set<String> allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey);
|
||||
if (recipient == null) {
|
||||
titleTextView.setText("Compose");
|
||||
} else if (userLinkedDeviceHexEncodedPublicKeys.contains(recipient.getAddress().toString().toLowerCase())) {
|
||||
} else if (allUserDevices.contains(recipient.getAddress().toString().toLowerCase())) {
|
||||
titleTextView.setText("Note to Self");
|
||||
} else {
|
||||
boolean hasName = (recipient.getName() != null && !recipient.getName().isEmpty());
|
||||
@ -3192,7 +3158,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void handleMessageStatusChanged(String newMessageStatus, long timestamp) {
|
||||
if (timestamp == 0) { return; }
|
||||
if (timestamp == 0 || SessionMetaProtocol.shared.isNoteToSelf(recipient.getAddress().serialize()) ) { return; }
|
||||
updateForNewMessageStatusIfNeeded(newMessageStatus, timestamp);
|
||||
if (newMessageStatus.equals("messageFailed") || newMessageStatus.equals("messageSent")) {
|
||||
new Handler().postDelayed(() -> clearMessageStatusIfNeeded(timestamp), 1000);
|
||||
@ -3232,48 +3198,16 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
public void acceptFriendRequest(@NotNull MessageRecord friendRequest) {
|
||||
// Send the accept to the original friend request thread ID
|
||||
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(this);
|
||||
long originalThreadID = lokiMessageDatabase.getOriginalThreadID(friendRequest.id);
|
||||
long threadID = originalThreadID < 0 ? this.threadId : originalThreadID;
|
||||
Recipient contact = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadID);
|
||||
Address address = contact.getAddress();
|
||||
String contactHexEncodedPublicKey = address.serialize();
|
||||
DatabaseFactory.getLokiThreadDatabase(this).setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
|
||||
lokiMessageDatabase.setFriendRequestStatus(friendRequest.id, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
|
||||
DatabaseFactory.getRecipientDatabase(this).setProfileSharing(contact, true);
|
||||
MessageSender.sendBackgroundMessageToAllDevices(this, contactHexEncodedPublicKey);
|
||||
MessageSender.syncContact(this, address);
|
||||
if (recipient.isGroupRecipient()) { return; }
|
||||
FriendRequestProtocol.acceptFriendRequest(this, recipient);
|
||||
updateInputPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rejectFriendRequest(@NotNull MessageRecord friendRequest) {
|
||||
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(this);
|
||||
long originalThreadID = lokiMessageDatabase.getOriginalThreadID(friendRequest.id);
|
||||
long threadID = originalThreadID < 0 ? this.threadId : originalThreadID;
|
||||
DatabaseFactory.getLokiThreadDatabase(this).setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.NONE);
|
||||
String contactID = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadID).getAddress().toString();
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(contactID);
|
||||
updateInputPanel();
|
||||
}
|
||||
|
||||
public boolean isNoteToSelf() {
|
||||
return TextSecurePreferences.getLocalNumber(this).equals(recipient.getAddress().serialize());
|
||||
}
|
||||
|
||||
public void restoreSession() {
|
||||
if (recipient.isGroupRecipient()) { return; }
|
||||
LokiThreadDatabase lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(this);
|
||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(this);
|
||||
Set<String> devices = lokiThreadDatabase.getSessionRestoreDevices(threadId);
|
||||
for (String device : devices) { MessageSender.sendRestoreSessionMessage(this, device); }
|
||||
long messageID = smsDatabase.insertMessageOutbox(threadId, new OutgoingTextMessage(recipient,"", 0, 0), false, System.currentTimeMillis(), null);
|
||||
if (messageID > -1) {
|
||||
smsDatabase.markAsLokiSessionRestoreSent(messageID);
|
||||
}
|
||||
lokiThreadDatabase.removeAllSessionRestoreDevices(threadId);
|
||||
updateSessionRestoreBanner();
|
||||
FriendRequestProtocol.rejectFriendRequest(this, recipient);
|
||||
updateInputPanel();
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.loki.views.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
@ -79,7 +79,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.loki.views.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.longmessage.LongMessageActivity;
|
||||
import org.thoughtcrime.securesms.mediasend.Media;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
@ -101,8 +101,8 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
|
||||
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.loki.api.publicchats.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.api.publicchats.LokiPublicChatAPI;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -375,9 +375,9 @@ public class ConversationFragment extends Fragment
|
||||
}
|
||||
|
||||
if (messageRecords.size() > 1) {
|
||||
// menu.findItem(R.id.menu_context_forward).setVisible(false);
|
||||
// menu.findItem(R.id.menu_context_forward).setVisible(false);
|
||||
menu.findItem(R.id.menu_context_reply).setVisible(false);
|
||||
// menu.findItem(R.id.menu_context_details).setVisible(false);
|
||||
// menu.findItem(R.id.menu_context_details).setVisible(false);
|
||||
menu.findItem(R.id.menu_context_save_attachment).setVisible(false);
|
||||
menu.findItem(R.id.menu_context_resend).setVisible(false);
|
||||
} else {
|
||||
@ -726,7 +726,7 @@ public class ConversationFragment extends Fragment
|
||||
}
|
||||
|
||||
if (!loader.hasSent() && !recipient.isSystemContact() && !recipient.isGroupRecipient() && recipient.getRegistered() == RecipientDatabase.RegisteredState.REGISTERED) {
|
||||
// adapter.setHeaderView(unknownSenderView);
|
||||
// adapter.setHeaderView(unknownSenderView);
|
||||
} else {
|
||||
clearHeaderIfNotTyping(adapter);
|
||||
}
|
||||
|
@ -86,11 +86,11 @@ import org.thoughtcrime.securesms.jobs.SmsSendJob;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.MentionUtilities;
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.FriendRequestView;
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.ProfilePictureView;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities;
|
||||
import org.thoughtcrime.securesms.loki.views.FriendRequestView;
|
||||
import org.thoughtcrime.securesms.loki.views.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.loki.views.ProfilePictureView;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.ImageSlide;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
@ -112,8 +112,8 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.views.Stub;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.loki.api.publicchats.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.api.publicchats.LokiPublicChatAPI;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
@ -49,8 +49,6 @@ public class ConversationPopupActivity extends ConversationActivity {
|
||||
else getWindow().setLayout((int) (width * .7), (int) (height * .75));
|
||||
|
||||
super.onCreate(bundle, ready);
|
||||
|
||||
// titleView.setOnClickListener(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -105,16 +105,16 @@ public class ConversationUpdateItem extends LinearLayout
|
||||
|
||||
this.sender.addListener(this);
|
||||
|
||||
if (messageRecord.isGroupAction()) setGroupRecord(messageRecord);
|
||||
else if (messageRecord.isCallLog()) setCallRecord(messageRecord);
|
||||
else if (messageRecord.isJoined()) setJoinedRecord(messageRecord);
|
||||
else if (messageRecord.isExpirationTimerUpdate()) setTimerRecord(messageRecord);
|
||||
else if (messageRecord.isEndSession()) setEndSessionRecord(messageRecord);
|
||||
else if (messageRecord.isIdentityUpdate()) setIdentityRecord(messageRecord);
|
||||
if (messageRecord.isGroupAction()) setGroupRecord(messageRecord);
|
||||
else if (messageRecord.isCallLog()) setCallRecord(messageRecord);
|
||||
else if (messageRecord.isJoined()) setJoinedRecord(messageRecord);
|
||||
else if (messageRecord.isExpirationTimerUpdate()) setTimerRecord(messageRecord);
|
||||
else if (messageRecord.isEndSession()) setEndSessionRecord(messageRecord);
|
||||
else if (messageRecord.isIdentityUpdate()) setIdentityRecord(messageRecord);
|
||||
else if (messageRecord.isIdentityVerified() ||
|
||||
messageRecord.isIdentityDefault()) setIdentityVerifyUpdate(messageRecord);
|
||||
messageRecord.isIdentityDefault()) setIdentityVerifyUpdate(messageRecord);
|
||||
else if (messageRecord.isLokiSessionRestoreSent()) setTextMessageRecord(messageRecord);
|
||||
else throw new AssertionError("Neither group nor log nor joined.");
|
||||
else throw new AssertionError("Neither group nor log nor joined.");
|
||||
|
||||
if (batchSelected.contains(messageRecord)) setSelected(true);
|
||||
else setSelected(false);
|
||||
|
@ -43,7 +43,7 @@ public class PreKeyUtil {
|
||||
|
||||
private static final int BATCH_SIZE = 100;
|
||||
|
||||
public synchronized static List<PreKeyRecord> generatePreKeys(Context context) {
|
||||
public synchronized static List<PreKeyRecord> generatePreKeyRecords(Context context) {
|
||||
PreKeyStore preKeyStore = new TextSecurePreKeyStore(context);
|
||||
List<PreKeyRecord> records = new LinkedList<>();
|
||||
int preKeyIdOffset = TextSecurePreferences.getNextPreKeyId(context);
|
||||
@ -101,7 +101,7 @@ public class PreKeyUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized static List<PreKeyRecord> generatePreKeys(Context context, int amount) {
|
||||
public synchronized static List<PreKeyRecord> generatePreKeyRecords(Context context, int amount) {
|
||||
List<PreKeyRecord> records = new LinkedList<>();
|
||||
int preKeyIDOffset = TextSecurePreferences.getNextPreKeyId(context);
|
||||
for (int i = 0; i < amount; i++) {
|
||||
|
@ -9,22 +9,15 @@ import android.support.annotation.WorkerThread;
|
||||
import org.signal.libsignal.metadata.SignalProtos;
|
||||
import org.signal.libsignal.metadata.certificate.CertificateValidator;
|
||||
import org.signal.libsignal.metadata.certificate.InvalidCertificateException;
|
||||
import network.loki.messenger.BuildConfig;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.libsignal.ecc.Curve;
|
||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class UnidentifiedAccessUtil {
|
||||
|
||||
private static final String TAG = UnidentifiedAccessUtil.class.getSimpleName();
|
||||
@ -116,9 +109,9 @@ public class UnidentifiedAccessUtil {
|
||||
String ourNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
if (ourNumber != null) {
|
||||
SignalProtos.SenderCertificate certificate = SignalProtos.SenderCertificate.newBuilder()
|
||||
.setSender(ourNumber)
|
||||
.setSenderDevice(SignalServiceAddress.DEFAULT_DEVICE_ID)
|
||||
.build();
|
||||
.setSender(ourNumber)
|
||||
.setSenderDevice(SignalServiceAddress.DEFAULT_DEVICE_ID)
|
||||
.build();
|
||||
return certificate.toByteArray();
|
||||
}
|
||||
|
||||
|
@ -105,11 +105,11 @@ public class Address implements Parcelable, Comparable<Address> {
|
||||
|
||||
public boolean isGroup() { return GroupUtil.isEncodedGroup(address); }
|
||||
|
||||
public boolean isSignalGroup() { return GroupUtil.isSignalGroup(address); }
|
||||
public boolean isClosedGroup() { return GroupUtil.isClosedGroup(address); }
|
||||
|
||||
public boolean isPublicChat() { return GroupUtil.isPublicChat(address); }
|
||||
public boolean isOpenGroup() { return GroupUtil.isOpenGroup(address); }
|
||||
|
||||
public boolean isRSSFeed() { return GroupUtil.isRssFeed(address); }
|
||||
public boolean isRSSFeed() { return GroupUtil.isRSSFeed(address); }
|
||||
|
||||
public boolean isMmsGroup() { return GroupUtil.isMmsGroup(address); }
|
||||
|
||||
@ -127,7 +127,7 @@ public class Address implements Parcelable, Comparable<Address> {
|
||||
}
|
||||
|
||||
public @NonNull String toPhoneString() {
|
||||
if (!isPhone() && !isPublicChat()) {
|
||||
if (!isPhone() && !isOpenGroup()) {
|
||||
if (isEmail()) throw new AssertionError("Not e164, is email");
|
||||
if (isGroup()) throw new AssertionError("Not e164, is group");
|
||||
throw new AssertionError("Not e164, unknown");
|
||||
|
@ -31,11 +31,12 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.helpers.ClassicOpenHelper;
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherMigrationHelper;
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||
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.loki.database.LokiAPIDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiPreKeyBundleDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiPreKeyRecordDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
public class DatabaseFactory {
|
||||
|
@ -160,14 +160,15 @@ public class GroupDatabase extends Database {
|
||||
return recipients;
|
||||
}
|
||||
|
||||
public boolean signalGroupsHaveMember(String hexEncodedPublicKey) {
|
||||
public boolean isClosedGroupMember(String hexEncodedPublicKey) {
|
||||
try {
|
||||
Address address = Address.fromSerialized(hexEncodedPublicKey);
|
||||
Reader reader = DatabaseFactory.getGroupDatabase(context).getGroups();
|
||||
|
||||
GroupRecord record;
|
||||
while ((record = reader.getNext()) != null) {
|
||||
if (record.isSignalGroup() && record.members.contains(address)) {
|
||||
return true;
|
||||
if (record.isClosedGroup() && record.members.contains(address)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,8 +293,7 @@ public class GroupDatabase extends Database {
|
||||
contents.put(ADMINS, Address.toSerializedList(admins, ','));
|
||||
contents.put(ACTIVE, 1);
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
||||
new String[] {groupId});
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?", new String[] {groupId});
|
||||
}
|
||||
|
||||
public void remove(String groupId, Address source) {
|
||||
@ -489,11 +489,11 @@ public class GroupDatabase extends Database {
|
||||
return mms;
|
||||
}
|
||||
|
||||
public boolean isPublicChat() { return Address.fromSerialized(id).isPublicChat(); }
|
||||
public boolean isOpenGroup() { return Address.fromSerialized(id).isOpenGroup(); }
|
||||
|
||||
public boolean isRSSFeed() { return Address.fromSerialized(id).isRSSFeed(); }
|
||||
|
||||
public boolean isSignalGroup() { return Address.fromSerialized(id).isSignalGroup(); }
|
||||
public boolean isClosedGroup() { return Address.fromSerialized(id).isClosedGroup(); }
|
||||
|
||||
public String getUrl() { return url; }
|
||||
|
||||
|
@ -47,7 +47,6 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -252,7 +251,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_NO_SESSION_BIT);
|
||||
}
|
||||
|
||||
public void markAsLokiSessionRestoreSent(long id) {
|
||||
public void markAsSentLokiSessionRestorationRequest(long id) {
|
||||
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT);
|
||||
}
|
||||
|
||||
@ -342,12 +341,12 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
|
||||
try {
|
||||
cursor = database.query(TABLE_NAME, new String[] { ID, THREAD_ID, ADDRESS, TYPE },
|
||||
DATE_SENT + " = ?", new String[] { String.valueOf(timestamp) },
|
||||
null, null, null, null);
|
||||
DATE_SENT + " = ?", new String[] { String.valueOf(timestamp) },
|
||||
null, null, null, null);
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
if (Types.isOutgoingMessageType(cursor.getLong(cursor.getColumnIndexOrThrow(TYPE)))) {
|
||||
isOutgoing = true;
|
||||
isOutgoing = true;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
@ -537,7 +537,7 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
|
||||
public @Nullable Recipient getRecipientForThreadId(long threadId) {
|
||||
// Loki - Cache the address.
|
||||
// Loki - Cache the address
|
||||
if (addressCache.containsKey(threadId) && addressCache.get(threadId) != null) {
|
||||
return Recipient.from(context, addressCache.get(threadId), false);
|
||||
}
|
||||
|
@ -35,17 +35,17 @@ import org.thoughtcrime.securesms.database.StickerDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
|
||||
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.loki.database.LokiAPIDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiPreKeyBundleDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiPreKeyRecordDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.loki.api.publicchats.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@ -81,8 +81,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
private static final int lokiV5 = 26;
|
||||
private static final int lokiV6 = 27;
|
||||
private static final int lokiV7 = 28;
|
||||
private static final int lokiV8 = 29;
|
||||
|
||||
private static final int DATABASE_VERSION = lokiV7; // Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
|
||||
private static final int DATABASE_VERSION = lokiV8; // Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
|
||||
private static final String DATABASE_NAME = "signal.db";
|
||||
|
||||
private final Context context;
|
||||
@ -138,6 +139,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
db.execSQL(LokiAPIDatabase.getCreateLastDeletionServerIDTableCommand());
|
||||
db.execSQL(LokiAPIDatabase.getCreateDeviceLinkTableCommand());
|
||||
db.execSQL(LokiAPIDatabase.getCreateUserCountTableCommand());
|
||||
db.execSQL(LokiAPIDatabase.getCreateSessionRequestTimestampTableCommand());
|
||||
db.execSQL(LokiPreKeyBundleDatabase.getCreateTableCommand());
|
||||
db.execSQL(LokiPreKeyRecordDatabase.getCreateTableCommand());
|
||||
db.execSQL(LokiMessageDatabase.getCreateMessageFriendRequestTableCommand());
|
||||
@ -181,8 +183,8 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
@Override
|
||||
public void onConfigure(SQLiteDatabase db) {
|
||||
super.onConfigure(db);
|
||||
// Loki: Enable Write Ahead Logging Mode, increase the cache size
|
||||
// This should be disabled if we ever run into serious race condition bugs
|
||||
// Loki - Enable write ahead logging mode and increase the cache size.
|
||||
// This should be disabled if we ever run into serious race condition bugs.
|
||||
db.enableWriteAheadLogging();
|
||||
db.execSQL("PRAGMA cache_size = 10000");
|
||||
}
|
||||
@ -544,7 +546,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
if (publicChat != null) {
|
||||
byte[] groupId = publicChat.getId().getBytes();
|
||||
String oldId = GroupUtil.getEncodedId(groupId, false);
|
||||
String newId = GroupUtil.getEncodedPublicChatId(groupId);
|
||||
String newId = GroupUtil.getEncodedOpenGroupId(groupId);
|
||||
ContentValues threadUpdate = new ContentValues();
|
||||
threadUpdate.put("recipient_ids", newId);
|
||||
db.update("thread", threadUpdate, "recipient_ids = ?", new String[]{ oldId });
|
||||
@ -555,7 +557,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate rss feeds from __textsecure_group__ to __loki_rss_feed_group__
|
||||
// Migrate RSS feeds from __textsecure_group__ to __loki_rss_feed_group__
|
||||
String[] rssFeedIds = new String[] { "loki.network.feed", "loki.network.messenger-updates.feed" };
|
||||
for (String groupId : rssFeedIds) {
|
||||
String oldId = GroupUtil.getEncodedId(groupId.getBytes(), false);
|
||||
@ -576,6 +578,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
db.execSQL(LokiMessageDatabase.getCreateErrorMessageTableCommand());
|
||||
}
|
||||
|
||||
if (oldVersion < lokiV8) {
|
||||
db.execSQL(LokiAPIDatabase.getCreateSessionRequestTimestampTableCommand());
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
@ -8,11 +8,11 @@ import com.annimon.stream.Stream;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.devicelist.Device;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.MnemonicUtilities;
|
||||
import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities;
|
||||
import org.thoughtcrime.securesms.util.AsyncLoader;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.loki.api.multidevice.LokiDeviceLinkUtilities;
|
||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec;
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
@ -33,9 +33,9 @@ public class DeviceListLoader extends AsyncLoader<List<Device>> {
|
||||
@Override
|
||||
public List<Device> loadInBackground() {
|
||||
try {
|
||||
String ourPublicKey = TextSecurePreferences.getLocalNumber(getContext());
|
||||
Set<String> secondaryDevicePublicKeys = LokiDeviceLinkUtilities.INSTANCE.getSlaveHexEncodedPublicKeys(ourPublicKey).get();
|
||||
List<Device> devices = Stream.of(secondaryDevicePublicKeys).map(this::mapToDevice).toList();
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(getContext());
|
||||
Set<String> slaveDevicePublicKeys = MultiDeviceProtocol.shared.getSlaveDevices(userPublicKey);
|
||||
List<Device> devices = Stream.of(slaveDevicePublicKeys).map(this::mapToDevice).toList();
|
||||
Collections.sort(devices, new DeviceComparator());
|
||||
return devices;
|
||||
} catch (Exception e) {
|
||||
|
@ -21,7 +21,6 @@ import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.SpannableString;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
@ -30,6 +29,8 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
/**
|
||||
* The message record model which represents standard SMS messages.
|
||||
*
|
||||
@ -67,9 +68,9 @@ public class SmsMessageRecord extends MessageRecord {
|
||||
int readReceiptCount, boolean unidentified, boolean isFriendRequest)
|
||||
{
|
||||
super(id, body, recipient, individualRecipient, recipientDeviceId,
|
||||
dateSent, dateReceived, threadId, status, deliveryReceiptCount, type,
|
||||
mismatches, new LinkedList<>(), subscriptionId,
|
||||
expiresIn, expireStarted, readReceiptCount, unidentified);
|
||||
dateSent, dateReceived, threadId, status, deliveryReceiptCount, type,
|
||||
mismatches, new LinkedList<>(), subscriptionId,
|
||||
expiresIn, expireStarted, readReceiptCount, unidentified);
|
||||
this.isFriendRequest = isFriendRequest;
|
||||
}
|
||||
|
||||
|
@ -45,9 +45,8 @@ import org.thoughtcrime.securesms.jobs.StickerPackDownloadJob;
|
||||
import org.thoughtcrime.securesms.jobs.TypingSendJob;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.LokiSessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.loki.MultiDeviceOpenGroupUpdateJob;
|
||||
import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob;
|
||||
import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceOpenGroupUpdateJob;
|
||||
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
|
||||
import org.thoughtcrime.securesms.push.MessageSenderEventListener;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||
@ -112,7 +111,6 @@ import network.loki.messenger.BuildConfig;
|
||||
MultiDeviceStickerPackOperationJob.class,
|
||||
MultiDeviceStickerPackSyncJob.class,
|
||||
LinkPreviewRepository.class,
|
||||
PushMessageSyncSendJob.class,
|
||||
MultiDeviceOpenGroupUpdateJob.class})
|
||||
|
||||
public class SignalCommunicationModule {
|
||||
@ -154,6 +152,7 @@ public class SignalCommunicationModule {
|
||||
Optional.fromNullable(IncomingMessageObserver.getUnidentifiedPipe()),
|
||||
Optional.of(new MessageSenderEventListener(context)),
|
||||
TextSecurePreferences.getLocalNumber(context),
|
||||
TextSecurePreferences.getMasterHexEncodedPublicKey(context),
|
||||
DatabaseFactory.getLokiAPIDatabase(context),
|
||||
DatabaseFactory.getLokiThreadDatabase(context),
|
||||
DatabaseFactory.getLokiMessageDatabase(context),
|
||||
|
@ -36,18 +36,18 @@ import java.util.Set;
|
||||
|
||||
public class GroupManager {
|
||||
|
||||
public static long getPublicChatThreadId(String id, @NonNull Context context) {
|
||||
final String groupId = GroupUtil.getEncodedPublicChatId(id.getBytes());
|
||||
return getThreadIdFromGroupId(groupId, context);
|
||||
public static long getOpenGroupThreadID(String id, @NonNull Context context) {
|
||||
final String groupID = GroupUtil.getEncodedOpenGroupId(id.getBytes());
|
||||
return getThreadIDFromGroupID(groupID, context);
|
||||
}
|
||||
|
||||
public static long getRSSFeedThreadId(String id, @NonNull Context context) {
|
||||
final String groupId = GroupUtil.getEncodedRSSFeedId(id.getBytes());
|
||||
return getThreadIdFromGroupId(groupId, context);
|
||||
public static long getRSSFeedThreadID(String id, @NonNull Context context) {
|
||||
final String groupID = GroupUtil.getEncodedRSSFeedId(id.getBytes());
|
||||
return getThreadIDFromGroupID(groupID, context);
|
||||
}
|
||||
|
||||
public static long getThreadIdFromGroupId(String groupId, @NonNull Context context) {
|
||||
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false);
|
||||
public static long getThreadIDFromGroupID(String groupID, @NonNull Context context) {
|
||||
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupID), false);
|
||||
return DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(groupRecipient);
|
||||
}
|
||||
|
||||
@ -78,10 +78,10 @@ public class GroupManager {
|
||||
final Set<Address> memberAddresses = getMemberAddresses(members);
|
||||
final Set<Address> adminAddresses = getMemberAddresses(admins);
|
||||
|
||||
String masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||
String ourNumber = masterHexEncodedPublicKey != null ? masterHexEncodedPublicKey : TextSecurePreferences.getLocalNumber(context);
|
||||
String masterPublicKeyOrNull = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||
String masterPublicKey = masterPublicKeyOrNull != null ? masterPublicKeyOrNull : TextSecurePreferences.getLocalNumber(context);
|
||||
|
||||
memberAddresses.add(Address.fromSerialized(ourNumber));
|
||||
memberAddresses.add(Address.fromSerialized(masterPublicKey));
|
||||
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>(adminAddresses));
|
||||
|
||||
if (!mms) {
|
||||
@ -94,28 +94,28 @@ public class GroupManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull GroupActionResult createPublicChatGroup(@NonNull String id,
|
||||
@NonNull Context context,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
public static @NonNull GroupActionResult createOpenGroup(@NonNull String id,
|
||||
@NonNull Context context,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
{
|
||||
final String groupId = GroupUtil.getEncodedPublicChatId(id.getBytes());
|
||||
return createLokiGroup(groupId, context, avatar, name);
|
||||
final String groupID = GroupUtil.getEncodedOpenGroupId(id.getBytes());
|
||||
return createLokiGroup(groupID, context, avatar, name);
|
||||
}
|
||||
|
||||
public static @NonNull GroupActionResult createRSSFeedGroup(@NonNull String id,
|
||||
@NonNull Context context,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
public static @NonNull GroupActionResult createRSSFeed(@NonNull String id,
|
||||
@NonNull Context context,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
{
|
||||
final String groupId = GroupUtil.getEncodedRSSFeedId(id.getBytes());
|
||||
return createLokiGroup(groupId, context, avatar, name);
|
||||
final String groupID = GroupUtil.getEncodedRSSFeedId(id.getBytes());
|
||||
return createLokiGroup(groupID, context, avatar, name);
|
||||
}
|
||||
|
||||
private static @NonNull GroupActionResult createLokiGroup(@NonNull String groupId,
|
||||
@NonNull Context context,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
private static @NonNull GroupActionResult createLokiGroup(@NonNull String groupId,
|
||||
@NonNull Context context,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
{
|
||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
@ -127,8 +127,8 @@ public class GroupManager {
|
||||
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||
return new GroupActionResult(groupRecipient, threadID);
|
||||
}
|
||||
|
||||
public static GroupActionResult updateGroup(@NonNull Context context,
|
||||
|
@ -8,7 +8,6 @@ import android.support.annotation.Nullable;
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
@ -18,26 +17,23 @@ import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.jobs.AvatarDownloadJob;
|
||||
import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup.Type;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.loki.api.multidevice.LokiDeviceLinkUtilities;
|
||||
import org.whispersystems.signalservice.loki.utilities.PromiseUtil;
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@ -45,8 +41,6 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.AttachmentPointer;
|
||||
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
||||
@ -95,7 +89,7 @@ public class GroupMessageProcessor {
|
||||
builder.setType(GroupContext.Type.UPDATE);
|
||||
|
||||
SignalServiceAttachment avatar = group.getAvatar().orNull();
|
||||
List<Address> members = group.getMembers().isPresent() ? new LinkedList<Address>() : null;
|
||||
List<Address> members = group.getMembers().isPresent() ? new LinkedList<>() : null;
|
||||
List<Address> admins = group.getAdmins().isPresent() ? new LinkedList<>() : null;
|
||||
|
||||
if (group.getMembers().isPresent()) {
|
||||
@ -104,13 +98,12 @@ public class GroupMessageProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
// We should only create the group if we are part of the member list
|
||||
String hexEncodedPublicKey = getMasterHexEncodedPublicKey(context, TextSecurePreferences.getLocalNumber(context));
|
||||
if (members == null || !members.contains(Address.fromSerialized(hexEncodedPublicKey))) {
|
||||
Log.d("Loki - Group Message", "Received a group create message which doesn't include us in the member list. Ignoring.");
|
||||
// Loki - Ignore message if needed
|
||||
if (ClosedGroupsProtocol.shouldIgnoreGroupCreatedMessage(context, group)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Loki - Parse admins
|
||||
if (group.getAdmins().isPresent()) {
|
||||
for (String admin : group.getAdmins().get()) {
|
||||
admins.add(Address.fromExternal(context, admin));
|
||||
@ -121,7 +114,7 @@ public class GroupMessageProcessor {
|
||||
avatar != null && avatar.isPointer() ? avatar.asPointer() : null, null, admins);
|
||||
|
||||
if (group.getMembers().isPresent()) {
|
||||
establishSessionsWithMembersIfNeeded(context, group.getMembers().get());
|
||||
ClosedGroupsProtocol.establishSessionsWithMembersIfNeeded(context, group.getMembers().get());
|
||||
}
|
||||
|
||||
return storeMessage(context, content, group, builder.build(), outgoing);
|
||||
@ -137,21 +130,21 @@ public class GroupMessageProcessor {
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
String id = GroupUtil.getEncodedId(group);
|
||||
|
||||
String ourHexEncodedPublicKey = getMasterHexEncodedPublicKey(context, TextSecurePreferences.getLocalNumber(context));
|
||||
String userMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||
|
||||
if (group.getGroupType() == SignalServiceGroup.GroupType.SIGNAL) {
|
||||
// Only update group if the group admin sent the message
|
||||
String hexEncodedPublicKey = getMasterHexEncodedPublicKey(context, content.getSender());
|
||||
if (!groupRecord.getAdmins().contains(Address.fromSerialized(hexEncodedPublicKey))) {
|
||||
Log.d("Loki - Group Message", "Received a group update message from a non-admin user for " + id +". Ignoring.");
|
||||
// Loki - Only update the group if the group admin sent the message
|
||||
String masterDevice = MultiDeviceProtocol.shared.getMasterDevice(content.getSender());
|
||||
if (!groupRecord.getAdmins().contains(Address.fromSerialized(masterDevice))) {
|
||||
Log.d("Loki", "Received a group update message from a non-admin user for: " + id +"; ignoring.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// We should only process update messages if we're in the group
|
||||
Address ourAddress = Address.fromSerialized(ourHexEncodedPublicKey);
|
||||
if (!groupRecord.getMembers().contains(ourAddress) &&
|
||||
!group.getMembers().or(Collections.emptyList()).contains(ourHexEncodedPublicKey)) {
|
||||
Log.d("Loki - Group Message", "Received a group update message from a group we are not a member of: " + id + "; ignoring.");
|
||||
// Loki - Only process update messages if we're part of the group
|
||||
Address userMasterDeviceAddress = Address.fromSerialized(userMasterDevice);
|
||||
if (!groupRecord.getMembers().contains(userMasterDeviceAddress) &&
|
||||
!group.getMembers().or(Collections.emptyList()).contains(userMasterDevice)) {
|
||||
Log.d("Loki", "Received a group update message from a group we're not a member of: " + id + "; ignoring.");
|
||||
database.setActive(id, false);
|
||||
return null;
|
||||
}
|
||||
@ -180,8 +173,8 @@ public class GroupMessageProcessor {
|
||||
database.updateMembers(id, new LinkedList<>(newMembers));
|
||||
}
|
||||
|
||||
// We add any new or removed members to the group context
|
||||
// This will allow us later to iterate over them to check if they left or were added for UI purposes
|
||||
// Add any new or removed members to the group context.
|
||||
// This will allow us later to iterate over them to check if they left or were added for UI purposes.
|
||||
for (Address addedMember : addedMembers) {
|
||||
builder.addNewMembers(addedMember.serialize());
|
||||
}
|
||||
@ -200,13 +193,13 @@ public class GroupMessageProcessor {
|
||||
}
|
||||
|
||||
// If we were removed then we need to disable the chat
|
||||
if (removedMembers.contains(Address.fromSerialized(ourHexEncodedPublicKey))) {
|
||||
if (removedMembers.contains(Address.fromSerialized(userMasterDevice))) {
|
||||
database.setActive(id, false);
|
||||
} else {
|
||||
if (!groupRecord.isActive()) database.setActive(id, true);
|
||||
|
||||
if (group.getMembers().isPresent()) {
|
||||
establishSessionsWithMembersIfNeeded(context, group.getMembers().get());
|
||||
ClosedGroupsProtocol.establishSessionsWithMembersIfNeeded(context, group.getMembers().get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,8 +211,8 @@ public class GroupMessageProcessor {
|
||||
@NonNull SignalServiceGroup group,
|
||||
@NonNull GroupRecord record)
|
||||
{
|
||||
String hexEncodedPublicKey = getMasterHexEncodedPublicKey(context, content.getSender());
|
||||
if (record.getMembers().contains(Address.fromSerialized(hexEncodedPublicKey))) {
|
||||
String masterDevice = MultiDeviceProtocol.shared.getMasterDevice(content.getSender());
|
||||
if (record.getMembers().contains(Address.fromSerialized(masterDevice))) {
|
||||
ApplicationContext.getInstance(context)
|
||||
.getJobManager()
|
||||
.add(new PushGroupUpdateJob(content.getSender(), group.getGroupId()));
|
||||
@ -240,9 +233,9 @@ public class GroupMessageProcessor {
|
||||
GroupContext.Builder builder = createGroupContext(group);
|
||||
builder.setType(GroupContext.Type.QUIT);
|
||||
|
||||
String hexEncodedPublicKey = getMasterHexEncodedPublicKey(context, content.getSender());
|
||||
if (members.contains(Address.fromExternal(context, hexEncodedPublicKey))) {
|
||||
database.remove(id, Address.fromExternal(context, hexEncodedPublicKey));
|
||||
String masterDevice = MultiDeviceProtocol.shared.getMasterDevice(content.getSender());
|
||||
if (members.contains(Address.fromExternal(context, masterDevice))) {
|
||||
database.remove(id, Address.fromExternal(context, masterDevice));
|
||||
if (outgoing) database.setActive(id, false);
|
||||
|
||||
return storeMessage(context, content, group, builder.build(), outgoing);
|
||||
@ -322,32 +315,4 @@ public class GroupMessageProcessor {
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static String getMasterHexEncodedPublicKey(Context context, String hexEncodedPublicKey) {
|
||||
String ourPublicKey = TextSecurePreferences.getLocalNumber(context);
|
||||
try {
|
||||
String masterHexEncodedPublicKey = hexEncodedPublicKey.equalsIgnoreCase(ourPublicKey)
|
||||
? TextSecurePreferences.getMasterHexEncodedPublicKey(context)
|
||||
: PromiseUtil.timeout(LokiDeviceLinkUtilities.INSTANCE.getMasterHexEncodedPublicKey(hexEncodedPublicKey), 5000).get();
|
||||
return masterHexEncodedPublicKey != null ? masterHexEncodedPublicKey : hexEncodedPublicKey;
|
||||
} catch (Exception e) {
|
||||
return hexEncodedPublicKey;
|
||||
}
|
||||
}
|
||||
|
||||
private static void establishSessionsWithMembersIfNeeded(Context context, List<String> members) {
|
||||
String ourNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
for (String member : members) {
|
||||
// Make sure we have session with all of the members secondary devices
|
||||
LokiDeviceLinkUtilities.INSTANCE.getAllLinkedDeviceHexEncodedPublicKeys(member).success(devices -> {
|
||||
if (devices.contains(ourNumber)) { return Unit.INSTANCE; }
|
||||
for (String device : devices) {
|
||||
SignalProtocolAddress protocolAddress = new SignalProtocolAddress(device, SignalServiceAddress.DEFAULT_DEVICE_ID);
|
||||
boolean haveSession = new TextSecureSessionStore(context).containsSession(protocolAddress);
|
||||
if (!haveSession) { MessageSender.sendBackgroundSessionRequest(context, device); }
|
||||
}
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -196,14 +196,17 @@ public class AttachmentDownloadJob extends BaseJob implements InjectableType {
|
||||
try {
|
||||
long id = Long.parseLong(attachment.getLocation());
|
||||
if (isPublicAttachment) {
|
||||
return new SignalServiceAttachmentPointer(id, null, new byte[0],
|
||||
Optional.of(Util.toIntExact(attachment.getSize())),
|
||||
Optional.absent(),
|
||||
0, 0,
|
||||
Optional.fromNullable(attachment.getDigest()),
|
||||
Optional.fromNullable(attachment.getFileName()),
|
||||
attachment.isVoiceNote(),
|
||||
Optional.absent(), attachment.getUrl());
|
||||
return new SignalServiceAttachmentPointer(id,
|
||||
null,
|
||||
new byte[0],
|
||||
Optional.of(Util.toIntExact(attachment.getSize())),
|
||||
Optional.absent(),
|
||||
0,
|
||||
0,
|
||||
Optional.fromNullable(attachment.getDigest()),
|
||||
Optional.fromNullable(attachment.getFileName()),
|
||||
attachment.isVoiceNote(),
|
||||
Optional.absent(), attachment.getUrl());
|
||||
}
|
||||
|
||||
byte[] key = Base64.decode(attachment.getKey());
|
||||
|
@ -40,7 +40,7 @@ public class CleanPreKeysJob extends BaseJob implements InjectableType {
|
||||
public CleanPreKeysJob() {
|
||||
this(new Job.Parameters.Builder()
|
||||
.setQueue("CleanPreKeysJob")
|
||||
.setMaxAttempts(5)
|
||||
.setMaxAttempts(3)
|
||||
.build());
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,8 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
|
||||
import org.thoughtcrime.securesms.loki.MultiDeviceOpenGroupUpdateJob;
|
||||
import org.thoughtcrime.securesms.loki.PushBackgroundMessageSendJob;
|
||||
import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob;
|
||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceOpenGroupUpdateJob;
|
||||
import org.thoughtcrime.securesms.loki.protocol.PushEphemeralMessageSendJob;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@ -71,8 +70,7 @@ public final class JobManagerFactories {
|
||||
put(TrimThreadJob.KEY, new TrimThreadJob.Factory());
|
||||
put(TypingSendJob.KEY, new TypingSendJob.Factory());
|
||||
put(UpdateApkJob.KEY, new UpdateApkJob.Factory());
|
||||
put(PushMessageSyncSendJob.KEY, new PushMessageSyncSendJob.Factory());
|
||||
put(PushBackgroundMessageSendJob.KEY, new PushBackgroundMessageSendJob.Factory());
|
||||
put(PushEphemeralMessageSendJob.KEY, new PushEphemeralMessageSendJob.Factory());
|
||||
put(MultiDeviceOpenGroupUpdateJob.KEY, new MultiDeviceOpenGroupUpdateJob.Factory());
|
||||
}};
|
||||
}
|
||||
|
@ -3,11 +3,6 @@ package org.thoughtcrime.securesms.jobs;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import com.android.mms.dom.smil.parser.SmilXmlSerializer;
|
||||
@ -30,6 +25,10 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
|
||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
@ -64,7 +63,7 @@ public class MmsSendJob extends SendJob {
|
||||
this(new Job.Parameters.Builder()
|
||||
.setQueue("mms-operation")
|
||||
.addConstraint(NetworkConstraint.KEY)
|
||||
.setMaxAttempts(15)
|
||||
.setMaxAttempts(25)
|
||||
.build(),
|
||||
messageId);
|
||||
}
|
||||
|
@ -84,8 +84,7 @@ public class MultiDeviceBlockedUpdateJob extends BaseJob implements InjectableTy
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Message ID
|
||||
messageSender.sendMessage(0, SignalServiceSyncMessage.forBlocked(new BlockedListMessage(blockedIndividuals, blockedGroups)),
|
||||
messageSender.sendMessage(SignalServiceSyncMessage.forBlocked(new BlockedListMessage(blockedIndividuals, blockedGroups)),
|
||||
UnidentifiedAccessUtil.getAccessForSync(context));
|
||||
}
|
||||
}
|
||||
|
@ -91,8 +91,7 @@ public class MultiDeviceConfigurationUpdateJob extends BaseJob implements Inject
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Message ID
|
||||
messageSender.sendMessage(0, SignalServiceSyncMessage.forConfiguration(new ConfigurationMessage(Optional.of(readReceiptsEnabled),
|
||||
messageSender.sendMessage(SignalServiceSyncMessage.forConfiguration(new ConfigurationMessage(Optional.of(readReceiptsEnabled),
|
||||
Optional.of(unidentifiedDeliveryIndicatorsEnabled),
|
||||
Optional.of(typingIndicatorsEnabled),
|
||||
Optional.of(linkPreviewsEnabled))),
|
||||
|
@ -1,21 +1,16 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.Database;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
@ -23,13 +18,12 @@ import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SyncMessagesProtocol;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
@ -39,18 +33,13 @@ import org.whispersystems.signalservice.api.messages.multidevice.DeviceContact;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsOutputStream;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus;
|
||||
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -65,57 +54,47 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
|
||||
private static final long FULL_SYNC_TIME = TimeUnit.HOURS.toMillis(6);
|
||||
|
||||
private static final String KEY_ADDRESS = "address";
|
||||
private static final String KEY_RECIPIENT = "recipient";
|
||||
private static final String KEY_FORCE_SYNC = "force_sync";
|
||||
|
||||
@Inject SignalServiceMessageSender messageSender;
|
||||
|
||||
private @Nullable String address;
|
||||
|
||||
// The recipient of this sync message. If null then we send to all devices
|
||||
private @Nullable String recipient;
|
||||
|
||||
private boolean forceSync;
|
||||
|
||||
/**
|
||||
* Create a full contact sync job which syncs across to all other devices
|
||||
* Create a full contact sync job that syncs to all linked devices.
|
||||
*/
|
||||
public MultiDeviceContactUpdateJob(@NonNull Context context) {
|
||||
this(context, false);
|
||||
}
|
||||
public MultiDeviceContactUpdateJob(@NonNull Context context, boolean forceSync) { this(context, null, forceSync); }
|
||||
|
||||
/**
|
||||
* Create a full contact sync job which only gets sent to `recipient`
|
||||
*/
|
||||
public MultiDeviceContactUpdateJob(@NonNull Context context, @Nullable Address recipient, boolean forceSync) {
|
||||
this(context, recipient, null, forceSync);
|
||||
public MultiDeviceContactUpdateJob(@NonNull Context context, boolean forceSync) {
|
||||
this(context, null, forceSync);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single contact sync job which syncs across `address` to the all other devices
|
||||
* Create a single contact sync job that syncs `address` to all linked devices.
|
||||
*/
|
||||
public MultiDeviceContactUpdateJob(@NonNull Context context, @Nullable Address address) {
|
||||
this(context, null, address, true);
|
||||
this(context, address, true);
|
||||
}
|
||||
|
||||
private MultiDeviceContactUpdateJob(@NonNull Context context, @Nullable Address recipient, @Nullable Address address, boolean forceSync) {
|
||||
public MultiDeviceContactUpdateJob(@NonNull Context context, @Nullable Address address, boolean forceSync) {
|
||||
this(new Job.Parameters.Builder()
|
||||
.addConstraint(NetworkConstraint.KEY)
|
||||
.setQueue("MultiDeviceContactUpdateJob")
|
||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
||||
.setMaxAttempts(1)
|
||||
.build(),
|
||||
recipient,
|
||||
address,
|
||||
forceSync);
|
||||
}
|
||||
|
||||
private MultiDeviceContactUpdateJob(@NonNull Job.Parameters parameters, @Nullable Address recipient, @Nullable Address address, boolean forceSync) {
|
||||
private MultiDeviceContactUpdateJob(@NonNull Job.Parameters parameters, @Nullable Address address, boolean forceSync) {
|
||||
super(parameters);
|
||||
|
||||
this.forceSync = forceSync;
|
||||
this.recipient = (recipient != null) ? recipient.serialize() : null;
|
||||
|
||||
if (address != null) this.address = address.serialize();
|
||||
else this.address = null;
|
||||
@ -125,7 +104,6 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
|
||||
public @NonNull Data serialize() {
|
||||
return new Data.Builder().putString(KEY_ADDRESS, address)
|
||||
.putBoolean(KEY_FORCE_SYNC, forceSync)
|
||||
.putString(KEY_RECIPIENT, recipient)
|
||||
.build();
|
||||
}
|
||||
|
||||
@ -144,14 +122,14 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
|
||||
}
|
||||
|
||||
if (address == null) generateFullContactUpdate();
|
||||
else if (!address.equals(TextSecurePreferences.getMasterHexEncodedPublicKey(context))) generateSingleContactUpdate(Address.fromSerialized(address));
|
||||
else if (SyncMessagesProtocol.shouldSyncContact(context, Address.fromSerialized(address))) generateSingleContactUpdate(Address.fromSerialized(address));
|
||||
}
|
||||
|
||||
private void generateSingleContactUpdate(@NonNull Address address)
|
||||
throws IOException, UntrustedIdentityException, NetworkException
|
||||
{
|
||||
// Loki - Only sync regular contacts
|
||||
if (!address.isPhone()) { return; }
|
||||
if (!PublicKeyValidation.isValid(address.serialize())) { return; }
|
||||
|
||||
File contactDataFile = createTempFile("multidevice-contact-update");
|
||||
|
||||
@ -162,17 +140,15 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
|
||||
Optional<VerifiedMessage> verifiedMessage = getVerifiedMessage(recipient, identityRecord);
|
||||
|
||||
// Loki - Only sync contacts we are friends with
|
||||
if (getFriendRequestStatus(recipient) == LokiThreadFriendRequestStatus.FRIENDS) {
|
||||
if (SyncMessagesProtocol.shouldSyncContact(context, address)) {
|
||||
out.write(new DeviceContact(address.toPhoneString(),
|
||||
Optional.fromNullable(recipient.getName()),
|
||||
getAvatar(recipient.getContactUri()),
|
||||
Optional.fromNullable(recipient.getColor().serialize()),
|
||||
verifiedMessage,
|
||||
Optional.fromNullable(recipient.getProfileKey()),
|
||||
recipient.isBlocked(),
|
||||
recipient.getExpireMessages() > 0 ?
|
||||
Optional.of(recipient.getExpireMessages()) :
|
||||
Optional.absent()));
|
||||
Optional.fromNullable(recipient.getName()),
|
||||
getAvatar(recipient.getContactUri()),
|
||||
Optional.fromNullable(recipient.getColor().serialize()),
|
||||
verifiedMessage,
|
||||
Optional.fromNullable(recipient.getProfileKey()),
|
||||
recipient.isBlocked(),
|
||||
recipient.getExpireMessages() > 0 ? Optional.of(recipient.getExpireMessages()) : Optional.absent()));
|
||||
}
|
||||
|
||||
out.close();
|
||||
@ -206,7 +182,7 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
|
||||
|
||||
try {
|
||||
DeviceContactsOutputStream out = new DeviceContactsOutputStream(new FileOutputStream(contactDataFile));
|
||||
List<ContactData> contacts = getAllContacts();
|
||||
List<ContactData> contacts = SyncMessagesProtocol.getContactsToSync(context);
|
||||
|
||||
for (ContactData contactData : contacts) {
|
||||
Uri contactUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(contactData.id));
|
||||
@ -220,10 +196,7 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
|
||||
boolean blocked = recipient.isBlocked();
|
||||
Optional<Integer> expireTimer = recipient.getExpireMessages() > 0 ? Optional.of(recipient.getExpireMessages()) : Optional.absent();
|
||||
|
||||
// Loki - Only sync contacts we are friends with
|
||||
if (getFriendRequestStatus(recipient) == LokiThreadFriendRequestStatus.FRIENDS) {
|
||||
out.write(new DeviceContact(address.toPhoneString(), name, getAvatar(contactUri), color, verified, profileKey, blocked, expireTimer));
|
||||
}
|
||||
out.write(new DeviceContact(address.toPhoneString(), name, getAvatar(contactUri), color, verified, profileKey, blocked, expireTimer));
|
||||
}
|
||||
|
||||
if (ProfileKeyUtil.hasProfileKey(context)) {
|
||||
@ -244,29 +217,9 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
|
||||
}
|
||||
}
|
||||
|
||||
private List<ContactData> getAllContacts() {
|
||||
List<Address> contactAddresses = new ArrayList<>(DatabaseFactory.getRecipientDatabase(context).getAllAddresses());
|
||||
List<ContactData> contacts = new ArrayList<>(contactAddresses.size());
|
||||
for (Address address : contactAddresses) {
|
||||
if (!address.isPhone()) { continue; }
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(Recipient.from(context, address, false));
|
||||
String name = DatabaseFactory.getLokiUserDatabase(context).getDisplayName(address.serialize());
|
||||
ContactData contactData = new ContactData(threadId, name);
|
||||
contactData.numbers.add(new ContactAccessor.NumberData("TextSecure", address.serialize()));
|
||||
contacts.add(contactData);
|
||||
}
|
||||
return contacts;
|
||||
}
|
||||
|
||||
private LokiThreadFriendRequestStatus getFriendRequestStatus(Recipient recipient) {
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient);
|
||||
return DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onShouldRetry(@NonNull Exception exception) {
|
||||
// Loki - Disabled because we have our own retrying
|
||||
// if (exception instanceof PushNetworkException) return true;
|
||||
// Loki - Disabled since we have our own retrying
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -286,13 +239,10 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
|
||||
.withLength(contactsFile.length())
|
||||
.build();
|
||||
|
||||
SignalServiceAddress messageRecipient = recipient != null ? new SignalServiceAddress(recipient) : null;
|
||||
Address address = recipient != null ? Address.fromSerialized(recipient) : null;
|
||||
|
||||
Optional<UnidentifiedAccessPair> unidentifiedAccess = address != null ? UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, address, false)) : Optional.absent();
|
||||
Optional<UnidentifiedAccessPair> unidentifiedAccess = address != null ? UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(address), false)) : Optional.absent();
|
||||
|
||||
try {
|
||||
messageSender.sendMessage(0, SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream, complete)), unidentifiedAccess, Optional.fromNullable(messageRecipient));
|
||||
messageSender.sendMessage(SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream, complete)), unidentifiedAccess);
|
||||
} catch (IOException ioe) {
|
||||
throw new NetworkException(ioe);
|
||||
}
|
||||
@ -302,7 +252,7 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
|
||||
private Optional<SignalServiceAttachmentStream> getAvatar(@Nullable Uri uri) throws IOException {
|
||||
return Optional.absent();
|
||||
|
||||
/* Loki - Disabled until we support custom avatars. This will need to be reworked
|
||||
/* Loki - Disabled until we support custom profile pictures. This will then need to be reworked.
|
||||
if (uri == null) {
|
||||
return Optional.absent();
|
||||
}
|
||||
@ -397,10 +347,7 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
|
||||
String serialized = data.getString(KEY_ADDRESS);
|
||||
Address address = serialized != null ? Address.fromSerialized(serialized) : null;
|
||||
|
||||
String recipientSerialized = data.getString(KEY_RECIPIENT);
|
||||
Address recipient = recipientSerialized != null ? Address.fromSerialized(recipientSerialized) : null;
|
||||
|
||||
return new MultiDeviceContactUpdateJob(parameters, recipient, address, data.getBoolean(KEY_FORCE_SYNC));
|
||||
return new MultiDeviceContactUpdateJob(parameters, address, data.getBoolean(KEY_FORCE_SYNC));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStre
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroup;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsOutputStream;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
@ -85,7 +84,7 @@ public class MultiDeviceGroupUpdateJob extends BaseJob implements InjectableType
|
||||
reader = DatabaseFactory.getGroupDatabase(context).getGroups();
|
||||
|
||||
while ((record = reader.getNext()) != null) {
|
||||
if (record.isSignalGroup()) {
|
||||
if (record.isClosedGroup()) {
|
||||
List<String> members = new LinkedList<>();
|
||||
List<String> admins = new LinkedList<>();
|
||||
|
||||
@ -125,8 +124,7 @@ public class MultiDeviceGroupUpdateJob extends BaseJob implements InjectableType
|
||||
|
||||
@Override
|
||||
public boolean onShouldRetry(@NonNull Exception exception) {
|
||||
// Loki - Disabled because we have our own retrying
|
||||
// if (exception instanceof PushNetworkException) return true;
|
||||
// Loki - Disabled since we have our own retrying
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -145,7 +143,7 @@ public class MultiDeviceGroupUpdateJob extends BaseJob implements InjectableType
|
||||
.withLength(contactsFile.length())
|
||||
.build();
|
||||
|
||||
messageSender.sendMessage(0, SignalServiceSyncMessage.forGroups(attachmentStream),
|
||||
messageSender.sendMessage(SignalServiceSyncMessage.forGroups(attachmentStream),
|
||||
UnidentifiedAccessUtil.getAccessForSync(context));
|
||||
}
|
||||
|
||||
|
@ -87,10 +87,9 @@ public class MultiDeviceProfileKeyUpdateJob extends BaseJob implements Injectabl
|
||||
.withLength(baos.toByteArray().length)
|
||||
.build();
|
||||
|
||||
SignalServiceSyncMessage syncMessage = SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream, false));
|
||||
SignalServiceSyncMessage syncMessage = SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream, false));
|
||||
|
||||
// TODO: Message ID
|
||||
messageSender.sendMessage(0, syncMessage, UnidentifiedAccessUtil.getAccessForSync(context));
|
||||
messageSender.sendMessage(syncMessage, UnidentifiedAccessUtil.getAccessForSync(context));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,8 +94,7 @@ public class MultiDeviceReadUpdateJob extends BaseJob implements InjectableType
|
||||
readMessages.add(new ReadMessage(messageId.sender, messageId.timestamp));
|
||||
}
|
||||
|
||||
// TODO: Message ID
|
||||
messageSender.sendMessage(0, SignalServiceSyncMessage.forRead(readMessages), UnidentifiedAccessUtil.getAccessForSync(context));
|
||||
messageSender.sendMessage(SignalServiceSyncMessage.forRead(readMessages), UnidentifiedAccessUtil.getAccessForSync(context));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,20 +2,14 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.util.Hex;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -76,6 +70,7 @@ public class MultiDeviceStickerPackOperationJob extends BaseJob implements Injec
|
||||
|
||||
@Override
|
||||
protected void onRun() throws Exception {
|
||||
/*
|
||||
if (!TextSecurePreferences.isMultiDevice(context)) {
|
||||
Log.i(TAG, "Not multi device, aborting...");
|
||||
return;
|
||||
@ -94,8 +89,9 @@ public class MultiDeviceStickerPackOperationJob extends BaseJob implements Injec
|
||||
|
||||
StickerPackOperationMessage stickerPackOperation = new StickerPackOperationMessage(packIdBytes, packKeyBytes, remoteType);
|
||||
|
||||
messageSender.sendMessage(0, SignalServiceSyncMessage.forStickerPackOperations(Collections.singletonList(stickerPackOperation)), // The message ID doesn't matter
|
||||
messageSender.sendMessage(SignalServiceSyncMessage.forStickerPackOperations(Collections.singletonList(stickerPackOperation)),
|
||||
UnidentifiedAccessUtil.getAccessForSync(context));
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,24 +2,14 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.StickerDatabase.StickerPackRecordReader;
|
||||
import org.thoughtcrime.securesms.database.model.StickerPackRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.util.Hex;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -59,6 +49,8 @@ public class MultiDeviceStickerPackSyncJob extends BaseJob implements Injectable
|
||||
|
||||
@Override
|
||||
protected void onRun() throws Exception {
|
||||
return;
|
||||
/*
|
||||
if (!TextSecurePreferences.isMultiDevice(context)) {
|
||||
Log.i(TAG, "Not multi device, aborting...");
|
||||
return;
|
||||
@ -76,8 +68,9 @@ public class MultiDeviceStickerPackSyncJob extends BaseJob implements Injectable
|
||||
}
|
||||
}
|
||||
|
||||
messageSender.sendMessage(0, SignalServiceSyncMessage.forStickerPackOperations(operations), // The message ID doesn't matter
|
||||
messageSender.sendMessage(SignalServiceSyncMessage.forStickerPackOperations(operations),
|
||||
UnidentifiedAccessUtil.getAccessForSync(context));
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,23 +3,16 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
|
||||
@ -89,6 +82,7 @@ public class MultiDeviceVerifiedUpdateJob extends BaseJob implements InjectableT
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException, UntrustedIdentityException {
|
||||
/*
|
||||
try {
|
||||
if (!TextSecurePreferences.isMultiDevice(context)) {
|
||||
Log.i(TAG, "Not multi device...");
|
||||
@ -104,12 +98,12 @@ public class MultiDeviceVerifiedUpdateJob extends BaseJob implements InjectableT
|
||||
VerifiedMessage.VerifiedState verifiedState = getVerifiedState(verifiedStatus);
|
||||
VerifiedMessage verifiedMessage = new VerifiedMessage(canonicalDestination.toPhoneString(), new IdentityKey(identityKey, 0), verifiedState, timestamp);
|
||||
|
||||
// TODO: Message ID
|
||||
messageSender.sendMessage(0, SignalServiceSyncMessage.forVerified(verifiedMessage),
|
||||
messageSender.sendMessage(SignalServiceSyncMessage.forVerified(verifiedMessage),
|
||||
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(destination), false)));
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private VerifiedMessage.VerifiedState getVerifiedState(VerifiedStatus status) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,31 +12,26 @@ import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupReceiptDatabase.GroupReceiptInfo;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||
@ -50,14 +45,10 @@ import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
|
||||
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
||||
import org.whispersystems.signalservice.loki.api.multidevice.LokiDeviceLinkUtilities;
|
||||
import org.whispersystems.signalservice.loki.api.publicchats.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.utilities.PromiseUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -159,36 +150,13 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
try {
|
||||
log(TAG, "Sending message: " + messageId);
|
||||
|
||||
List<Address> target;
|
||||
List<Address> targets;
|
||||
|
||||
if (filterAddress != null) target = Collections.singletonList(Address.fromSerialized(filterAddress));
|
||||
else if (!existingNetworkFailures.isEmpty()) target = Stream.of(existingNetworkFailures).map(NetworkFailure::getAddress).toList();
|
||||
else target = getGroupMessageRecipients(message.getRecipient().getAddress().toGroupString(), messageId);
|
||||
if (filterAddress != null) targets = Collections.singletonList(Address.fromSerialized(filterAddress));
|
||||
else if (!existingNetworkFailures.isEmpty()) targets = Stream.of(existingNetworkFailures).map(NetworkFailure::getAddress).toList();
|
||||
else targets = ClosedGroupsProtocol.getDestinations(message.getRecipient().getAddress().toGroupString(), context).get();
|
||||
|
||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
|
||||
// Only send messages to the contacts we have sessions with
|
||||
List<Address> validTargets = Stream.of(target).filter(member -> {
|
||||
if (member.isPublicChat()) { return true; }
|
||||
|
||||
// Our device is always valid
|
||||
if (member.serialize().equalsIgnoreCase(localNumber)) { return true; }
|
||||
|
||||
SignalProtocolAddress protocolAddress = new SignalProtocolAddress(member.toPhoneString(), SignalServiceAddress.DEFAULT_DEVICE_ID);
|
||||
boolean hasSession = new TextSecureSessionStore(context).containsSession(protocolAddress);
|
||||
if (hasSession) { return true; }
|
||||
|
||||
// We should allow sending if we have a prekeybundle for the contact
|
||||
return DatabaseFactory.getLokiPreKeyBundleDatabase(context).hasPreKeyBundle(member.toPhoneString());
|
||||
}).toList();
|
||||
|
||||
// Send a session request to the other devices
|
||||
List<Address> others = Stream.of(target).filter(t -> !validTargets.contains(t)).toList();
|
||||
for (Address device : others) {
|
||||
MessageSender.sendBackgroundSessionRequest(context, device.toPhoneString());
|
||||
}
|
||||
|
||||
List<SendMessageResult> results = deliver(message, validTargets);
|
||||
List<SendMessageResult> results = deliver(message, targets);
|
||||
List<NetworkFailure> networkFailures = Stream.of(results).filter(SendMessageResult::isNetworkFailure).map(result -> new NetworkFailure(Address.fromSerialized(result.getAddress().getNumber()))).toList();
|
||||
List<IdentityKeyMismatch> identityMismatches = Stream.of(results).filter(result -> result.getIdentityFailure() != null).map(result -> new IdentityKeyMismatch(Address.fromSerialized(result.getAddress().getNumber()), result.getIdentityFailure().getIdentityKey())).toList();
|
||||
Set<Address> successAddresses = Stream.of(results).filter(result -> result.getSuccess() != null).map(result -> Address.fromSerialized(result.getAddress().getNumber())).collect(Collectors.toSet());
|
||||
@ -237,7 +205,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
database.markAsSentFailed(messageId);
|
||||
notifyMediaMessageDeliveryFailed(context, messageId);
|
||||
}
|
||||
} catch (UntrustedIdentityException | UndeliverableMessageException e) {
|
||||
} catch (Exception e) {
|
||||
warn(TAG, e);
|
||||
database.markAsSentFailed(messageId);
|
||||
notifyMediaMessageDeliveryFailed(context, messageId);
|
||||
@ -246,10 +214,8 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
@Override
|
||||
public boolean onShouldRetry(@NonNull Exception exception) {
|
||||
if (exception instanceof IOException) return true;
|
||||
|
||||
if (exception instanceof IOException) return true;
|
||||
// Loki - Disable since we have our own retrying
|
||||
// if (exception instanceof RetryLaterException) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -260,17 +226,18 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
private List<SendMessageResult> deliver(OutgoingMediaMessage message, @NonNull List<Address> destinations)
|
||||
throws IOException, UntrustedIdentityException, UndeliverableMessageException {
|
||||
// rotateSenderCertificateIfNecessary();
|
||||
|
||||
// Messages shouldn't be able to be sent to RSS Feeds
|
||||
Address groupAddress = message.getRecipient().getAddress();
|
||||
if (groupAddress.isRSSFeed()) {
|
||||
// Loki - The user shouldn't be able to message RSS feeds
|
||||
Address address = message.getRecipient().getAddress();
|
||||
if (address.isRSSFeed()) {
|
||||
List<SendMessageResult> results = new ArrayList<>();
|
||||
for (Address destination : destinations) results.add(SendMessageResult.networkFailure(new SignalServiceAddress(destination.toPhoneString())));
|
||||
for (Address destination : destinations) {
|
||||
results.add(SendMessageResult.networkFailure(new SignalServiceAddress(destination.toPhoneString())));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
String groupId = groupAddress.toGroupString();
|
||||
String groupId = address.toGroupString();
|
||||
Optional<byte[]> profileKey = getProfileKey(message.getRecipient());
|
||||
Optional<Quote> quote = getQuoteFor(message);
|
||||
Optional<SignalServiceDataMessage.Sticker> sticker = getStickerFor(message);
|
||||
@ -281,18 +248,15 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
List<SignalServiceAttachment> attachmentPointers = getAttachmentPointersFor(attachments);
|
||||
|
||||
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(addresses)
|
||||
.map(address -> Address.fromSerialized(address.getNumber()))
|
||||
.map(address -> Recipient.from(context, address, false))
|
||||
.map(a -> Address.fromSerialized(a.getNumber()))
|
||||
.map(a -> Recipient.from(context, a, false))
|
||||
.map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient))
|
||||
.toList();
|
||||
|
||||
SignalServiceGroup.GroupType groupType = SignalServiceGroup.GroupType.SIGNAL;
|
||||
if (groupAddress.isPublicChat()) {
|
||||
groupType = SignalServiceGroup.GroupType.PUBLIC_CHAT;
|
||||
}
|
||||
SignalServiceGroup.GroupType groupType = address.isOpenGroup() ? SignalServiceGroup.GroupType.PUBLIC_CHAT : SignalServiceGroup.GroupType.SIGNAL;
|
||||
|
||||
if (message.isGroup() && groupAddress.isSignalGroup()) {
|
||||
// Loki - Only send GroupUpdate or GroupQuit to signal groups
|
||||
if (message.isGroup() && address.isClosedGroup()) {
|
||||
// Loki - Only send GroupUpdate or GroupQuit messages to closed groups
|
||||
OutgoingGroupMediaMessage groupMessage = (OutgoingGroupMediaMessage) message;
|
||||
GroupContext groupContext = groupMessage.getGroupContext();
|
||||
SignalServiceAttachment avatar = attachmentPointers.isEmpty() ? null : attachmentPointers.get(0);
|
||||
@ -301,7 +265,6 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
SignalServiceDataMessage groupDataMessage = SignalServiceDataMessage.newBuilder()
|
||||
.withTimestamp(message.getSentTimeMillis())
|
||||
.withExpiration(message.getRecipient().getExpireMessages())
|
||||
.withBody(message.getBody())
|
||||
.asGroupMessage(group)
|
||||
.build();
|
||||
|
||||
@ -326,65 +289,6 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
}
|
||||
}
|
||||
|
||||
private @NonNull List<Address> getGroupMessageRecipients(String groupId, long messageId) {
|
||||
if (GroupUtil.isRssFeed(groupId)) { return new ArrayList<>(); }
|
||||
|
||||
// Loki - All public chat group messages should be directed to their respective servers
|
||||
if (GroupUtil.isPublicChat(groupId)) {
|
||||
ArrayList<Address> result = new ArrayList<>();
|
||||
long threadID = GroupManager.getThreadIdFromGroupId(groupId, context);
|
||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID);
|
||||
if (publicChat != null) {
|
||||
result.add(Address.fromSerialized(groupId));
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
/*
|
||||
Our biggest assumption here is that group members will only consist of primary devices.
|
||||
No secondary device should be able to be added to a group.
|
||||
*/
|
||||
List<GroupReceiptInfo> destinations = DatabaseFactory.getGroupReceiptDatabase(context).getGroupReceiptInfo(messageId);
|
||||
|
||||
Set<Address> memberSet = new HashSet<>();
|
||||
if (destinations.isEmpty()) {
|
||||
List<Recipient> groupMembers = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
|
||||
memberSet.addAll(Stream.of(groupMembers).map(Recipient::getAddress).toList());
|
||||
} else {
|
||||
memberSet.addAll(Stream.of(destinations).map(GroupReceiptInfo::getAddress).toList());
|
||||
}
|
||||
|
||||
// Replace primary device public key with ours so message syncing works correctly
|
||||
String masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
if (masterHexEncodedPublicKey != null && memberSet.contains(Address.fromSerialized(masterHexEncodedPublicKey))) {
|
||||
memberSet.remove(Address.fromSerialized(masterHexEncodedPublicKey));
|
||||
memberSet.add(Address.fromSerialized(localNumber));
|
||||
}
|
||||
|
||||
// Add secondary devices to the list. We shouldn't add our secondary devices
|
||||
try {
|
||||
Set<Address> originalMemberSet = new HashSet<>(memberSet);
|
||||
for (Address member : originalMemberSet) {
|
||||
if (!member.isPhone() || member.serialize().equalsIgnoreCase(localNumber)) { continue; }
|
||||
|
||||
try {
|
||||
Set<String> secondaryDevices = PromiseUtil.timeout(LokiDeviceLinkUtilities.INSTANCE.getSlaveHexEncodedPublicKeys(member.serialize()), 5000).get();
|
||||
memberSet.addAll(Stream.of(secondaryDevices).map(string -> {
|
||||
// Loki - Calling .map(Address::fromSerialized) is causing errors, thus we use the long method :(
|
||||
return Address.fromSerialized(string);
|
||||
}).toList());
|
||||
} catch (Exception e) {
|
||||
// Timed out, go to the next member
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("PushGroupSend", "Error occurred while adding secondary devices: " + e);
|
||||
}
|
||||
|
||||
return new LinkedList<>(memberSet);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements Job.Factory<PushGroupSendJob> {
|
||||
@Override
|
||||
public @NonNull PushGroupSendJob create(@NonNull Parameters parameters, @NonNull org.thoughtcrime.securesms.jobmanager.Data data) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user