Merge pull request #192 from loki-project/refactoring

Separate Session Protocol from Signal Code
This commit is contained in:
Niels Andriesse 2020-05-22 15:04:24 +10:00 committed by GitHub
commit bf912e4369
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
237 changed files with 3220 additions and 3652 deletions

View File

@ -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>

View File

@ -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"

View File

@ -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" />

View File

@ -30,7 +30,7 @@
android:textAlignment="center"
android:text="Users can share their Session ID by going into their account settings and tapping &quot;Share Session ID&quot;, 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"

View 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>

View File

@ -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" />

View File

@ -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,7 +66,7 @@
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"

View File

@ -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"

View File

@ -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" />

View File

@ -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" />

View File

@ -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 dont 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" />

View File

@ -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"

View File

@ -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.loki.redesign.fragments.contactselection.ContactSelectionListFragment" />
android:name="org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment" />
</LinearLayout>

View File

@ -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" />

View File

@ -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"

View File

@ -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"

View File

@ -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">

View File

@ -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"

View File

@ -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

View File

@ -30,7 +30,7 @@
android:textAlignment="center"
android:text="Users can share their Session ID by going into their account settings and tapping &quot;Share Session ID&quot;, 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"

View File

@ -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" />

View File

@ -94,7 +94,7 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:name="org.thoughtcrime.securesms.loki.redesign.fragments.contactselection.ContactSelectionListFragment"
android:name="org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment"
tools:layout="@layout/contact_selection_list_fragment"/>
<LinearLayout android:layout_width="match_parent"

View File

@ -49,7 +49,7 @@
android:layout_below="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="org.thoughtcrime.securesms.loki.redesign.fragments.contactselection.ContactSelectionListFragment" />
android:name="org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment" />
<org.thoughtcrime.securesms.components.SearchToolbar
android:id="@+id/search_toolbar"

View File

@ -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"

View File

@ -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>

View File

@ -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"

View File

@ -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" />

View File

@ -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" />

View File

@ -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.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.redesign.shelved.LokiRSSFeedPoller;
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;
@ -96,16 +94,22 @@ 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;
@ -113,7 +117,6 @@ import java.security.SecureRandom;
import java.security.Security;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import dagger.ObjectGraph;
@ -131,7 +134,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
@ -145,10 +148,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;
@ -163,8 +164,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate()");
broadcaster = new Broadcaster(this);
checkNeedsDatabaseReset();
startKovenant();
initializeSecurityProvider();
initializeLogging();
@ -183,27 +182,32 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
initializeBlobProvider();
NotificationChannels.create(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
// Loki - Set up P2P API if needed
setUpP2PAPI();
// Loki - Set up push notification acknowledgement
// 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);
MultiDeviceProtocol.Companion.configureIfNeeded(apiDB);
SessionManagementProtocol.Companion.configureIfNeeded(sessionResetImpl, threadDB, this);
SyncMessagesProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
}
setUpP2PAPIIfNeeded();
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);
}
if (userPublicKey != null) {
Set<DeviceLink> deviceLinks = DatabaseFactory.getLokiAPIDatabase(this).getDeviceLinks(userPublicKey);
LokiFileServerAPI.shared.setDeviceLinks(deviceLinks);
}
}
// Loki - Resubmit profile picture if needed
resubmitProfilePictureIfNeeded();
// Loki - Set up public chat manager
lokiPublicChatManager = new LokiPublicChatManager(this);
updatePublicChatProfilePictureIfNeeded();
updateOpenGroupProfilePicturesIfNeeded();
registerForFCMIfNeeded(false);
}
@ -213,9 +217,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();
}
@ -225,14 +228,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();
}
@ -267,20 +270,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;
}
@ -362,8 +360,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);
@ -441,18 +439,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) -> {
@ -469,10 +465,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);
}
@ -486,15 +482,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;
});
@ -505,103 +501,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() {
return;
/*
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() {
return;
/*
// 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() {
return;
/*
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;
@ -609,7 +511,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());
@ -623,7 +525,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
});
}
public void updatePublicChatProfilePictureIfNeeded() {
public void updateOpenGroupProfilePicturesIfNeeded() {
AsyncTask.execute(() -> {
LokiPublicChatAPI publicChatAPI = null;
try {
@ -631,48 +533,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);
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.");
}
new Handler().postDelayed(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
}

View File

@ -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());
}

View File

@ -20,8 +20,8 @@ import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import org.thoughtcrime.securesms.components.ContactFilterToolbar;
import org.thoughtcrime.securesms.loki.redesign.fragments.contactselection.ContactSelectionListFragment;
import org.thoughtcrime.securesms.loki.redesign.fragments.contactselection.ContactSelectionListLoader.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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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>>,

View File

@ -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;

View File

@ -56,8 +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.redesign.fragments.contactselection.ContactSelectionListFragment;
import org.thoughtcrime.securesms.loki.redesign.fragments.contactselection.ContactSelectionListLoader.DisplayMode;
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;

View File

@ -28,8 +28,8 @@ import org.thoughtcrime.securesms.components.ContactFilterToolbar;
import org.thoughtcrime.securesms.components.ContactFilterToolbar.OnFilterChangedListener;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.loki.redesign.fragments.contactselection.ContactSelectionListFragment;
import org.thoughtcrime.securesms.loki.redesign.fragments.contactselection.ContactSelectionListLoader.DisplayMode;
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;

View File

@ -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;

View File

@ -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;

View File

@ -19,7 +19,7 @@ package org.thoughtcrime.securesms;
import android.content.Intent;
import android.os.Bundle;
import org.thoughtcrime.securesms.loki.redesign.fragments.contactselection.ContactSelectionListFragment;
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment;
import java.util.ArrayList;
import java.util.List;

View File

@ -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);

View File

@ -40,8 +40,8 @@ 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.redesign.fragments.contactselection.ContactSelectionListFragment;
import org.thoughtcrime.securesms.loki.redesign.fragments.contactselection.ContactSelectionListLoader.DisplayMode;
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;

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}
}

View File

@ -200,7 +200,6 @@ public class TransferControlView extends FrameLayout {
if (view != null) {
view.setVisibility(VISIBLE);
// setVisibility(VISIBLE);
} else {
setVisibility(GONE);
}

View File

@ -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 {

View File

@ -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);
// ========
}
}

View File

@ -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);
// ========
}
}

View File

@ -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
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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++) {

View File

@ -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();
}

View File

@ -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");

View File

@ -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 {

View File

@ -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; }

View File

@ -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 {

View File

@ -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);
}

View File

@ -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();

View File

@ -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) {

View File

@ -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;
}

View File

@ -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),

View File

@ -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,

View File

@ -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;
});
}
}
}

View File

@ -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());

View File

@ -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());
}

View File

@ -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());
}};
}

View File

@ -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);
}

View File

@ -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));
}
}

View File

@ -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))),

View File

@ -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));
}
}
}

View File

@ -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));
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -123,7 +123,6 @@ public class PushGroupUpdateJob extends BaseJob implements InjectableType {
.withExpiration(groupRecipient.getExpireMessages())
.build();
// TODO: Message ID
messageSender.sendMessage(0, new SignalServiceAddress(source),
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(source), false)),
message);

View File

@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
@ -45,9 +45,7 @@ import org.whispersystems.signalservice.api.messages.shared.SharedContact;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
import org.whispersystems.signalservice.loki.api.LokiAPI;
import org.whispersystems.signalservice.loki.api.multidevice.LokiDeviceLinkUtilities;
import org.whispersystems.signalservice.loki.messaging.LokiSyncMessage;
import org.whispersystems.signalservice.loki.utilities.PromiseUtil;
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -66,9 +64,8 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
private static final String KEY_TEMPLATE_MESSAGE_ID = "template_message_id";
private static final String KEY_MESSAGE_ID = "message_id";
private static final String KEY_DESTINATION = "destination";
private static final String KEY_IS_FRIEND_REQUEST = "is_friend_request";
private static final String KEY_IS_LOKI_PRE_KEY_BUNDLE_MESSAGE = "is_friend_request";
private static final String KEY_CUSTOM_FR_MESSAGE = "custom_friend_request_message";
private static final String KEY_SHOULD_SEND_SYNC_MESSAGE = "should_send_sync_message";
@Inject SignalServiceMessageSender messageSender;
@ -76,33 +73,37 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
private long templateMessageId; // The message ID of the message to template this send job from
// Loki - Multi device
private Address destination; // Destination to check whether this is another device we're sending to
private boolean isFriendRequest; // Whether this is a friend request message
private Address destination; // Used to check whether this is another device we're sending to
private boolean isLokiPreKeyBundleMessage; // Whether this is a friend request / session request / device link message
private String customFriendRequestMessage; // If this isn't set then we use the message body
private boolean shouldSendSyncMessage;
public PushMediaSendJob(long messageId, Address destination) { this(messageId, messageId, destination); }
public PushMediaSendJob(long templateMessageId, long messageId, Address destination) { this(templateMessageId, messageId, destination, false, null, false); }
public PushMediaSendJob(long templateMessageId, long messageId, Address destination, boolean isFriendRequest, String customFriendRequestMessage, boolean shouldSendSyncMessage) {
this(constructParameters(destination), templateMessageId, messageId, destination, isFriendRequest, customFriendRequestMessage, shouldSendSyncMessage);
public PushMediaSendJob(long messageId, Address destination) {
this(messageId, messageId, destination);
}
private PushMediaSendJob(@NonNull Job.Parameters parameters, long templateMessageId, long messageId, Address destination, boolean isFriendRequest, String customFriendRequestMessage, boolean shouldSendSyncMessage) {
public PushMediaSendJob(long templateMessageId, long messageId, Address destination) {
this(templateMessageId, messageId, destination, false, null);
}
public PushMediaSendJob(long templateMessageId, long messageId, Address destination, boolean isLokiPreKeyBundleMessage, String customFriendRequestMessage) {
this(constructParameters(destination), templateMessageId, messageId, destination, isLokiPreKeyBundleMessage, customFriendRequestMessage);
}
private PushMediaSendJob(@NonNull Job.Parameters parameters, long templateMessageId, long messageId, Address destination, boolean isLokiPreKeyBundleMessage, String customFriendRequestMessage) {
super(parameters);
this.templateMessageId = templateMessageId;
this.messageId = messageId;
this.destination = destination;
this.isFriendRequest = isFriendRequest;
this.isLokiPreKeyBundleMessage = isLokiPreKeyBundleMessage;
this.customFriendRequestMessage = customFriendRequestMessage;
this.shouldSendSyncMessage = shouldSendSyncMessage;
}
public static void enqueue(@NonNull Context context, @NonNull JobManager jobManager, long messageId, @NonNull Address destination, boolean shouldSendSyncMessage) {
enqueue(context, jobManager, messageId, messageId, destination, false, null, shouldSendSyncMessage);
public static void enqueue(@NonNull Context context, @NonNull JobManager jobManager, long messageId, @NonNull Address destination) {
enqueue(context, jobManager, messageId, messageId, destination, false, null);
}
public static void enqueue(@NonNull Context context, @NonNull JobManager jobManager, long templateMessageId, long messageId, @NonNull Address destination, Boolean isFriendRequest, @Nullable String customFriendRequestMessage, boolean shouldSendSyncMessage) {
enqueue(context, jobManager, Collections.singletonList(new PushMediaSendJob(templateMessageId, messageId, destination, isFriendRequest, customFriendRequestMessage, shouldSendSyncMessage)));
public static void enqueue(@NonNull Context context, @NonNull JobManager jobManager, long templateMessageId, long messageId, @NonNull Address destination, Boolean isFriendRequest, @Nullable String customFriendRequestMessage) {
enqueue(context, jobManager, Collections.singletonList(new PushMediaSendJob(templateMessageId, messageId, destination, isFriendRequest, customFriendRequestMessage)));
}
@WorkerThread
@ -144,11 +145,10 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
@Override
public @NonNull Data serialize() {
Data.Builder builder = new Data.Builder()
.putLong(KEY_TEMPLATE_MESSAGE_ID, templateMessageId)
.putLong(KEY_MESSAGE_ID, messageId)
.putString(KEY_DESTINATION, destination.serialize())
.putBoolean(KEY_IS_FRIEND_REQUEST, isFriendRequest)
.putBoolean(KEY_SHOULD_SEND_SYNC_MESSAGE, shouldSendSyncMessage);
.putLong(KEY_TEMPLATE_MESSAGE_ID, templateMessageId)
.putLong(KEY_MESSAGE_ID, messageId)
.putString(KEY_DESTINATION, destination.serialize())
.putBoolean(KEY_IS_LOKI_PRE_KEY_BUNDLE_MESSAGE, isLokiPreKeyBundleMessage);
if (customFriendRequestMessage != null) { builder.putString(KEY_CUSTOM_FR_MESSAGE, customFriendRequestMessage); }
return builder.build();
@ -233,15 +233,17 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
}
} catch (LokiAPI.Error e) {
Log.d("Loki", "Couldn't send message due to error: " + e.getDescription());
if (messageId < 0) { return; }
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
lokiMessageDatabase.setErrorMessage(messageId, e.getDescription());
database.markAsSentFailed(messageId);
if (messageId >= 0) {
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
lokiMessageDatabase.setErrorMessage(messageId, e.getDescription());
database.markAsSentFailed(messageId);
}
}
}
@Override
public boolean onShouldRetry(@NonNull Exception exception) {
// Loki - Disable since we have our own retrying
return false;
}
@ -268,9 +270,15 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
List<SharedContact> sharedContacts = getSharedContactsFor(message);
List<Preview> previews = getPreviewsFor(message);
// Loki - Include a pre key bundle if the message is a friend request or an end session message
PreKeyBundle preKeyBundle = isFriendRequest ? DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.getNumber()) : null;
String body = (isFriendRequest && customFriendRequestMessage != null) ? customFriendRequestMessage : message.getBody();
// Loki - Include a pre key bundle if needed
PreKeyBundle preKeyBundle;
if (isLokiPreKeyBundleMessage) {
preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.getNumber());
} else {
preKeyBundle = null;
}
String body = (isLokiPreKeyBundleMessage && customFriendRequestMessage != null) ? customFriendRequestMessage : message.getBody();
SignalServiceDataMessage mediaMessage = SignalServiceDataMessage.newBuilder()
.withBody(body)
.withAttachments(serviceAttachments)
@ -283,25 +291,18 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
.withPreviews(previews)
.asExpirationUpdate(message.isExpirationUpdate())
.withPreKeyBundle(preKeyBundle)
.asFriendRequest(isFriendRequest)
.asFriendRequest(isLokiPreKeyBundleMessage)
.build();
if (address.getNumber().equals(TextSecurePreferences.getLocalNumber(context))) {
if (SessionMetaProtocol.shared.isNoteToSelf(address.getNumber())) {
// Loki - Device link messages don't go through here
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, mediaMessage, syncAccess);
messageSender.sendMessage(templateMessageId, syncMessage, syncAccess);
messageSender.sendMessage(syncMessage, syncAccess);
return syncAccess.isPresent();
} else {
LokiSyncMessage syncMessage = null;
if (shouldSendSyncMessage) {
// Set the sync message destination to the master device, this way it will show that we sent a message to the master device and not the slave device
String masterDevice = PromiseUtil.get(LokiDeviceLinkUtilities.INSTANCE.getMasterHexEncodedPublicKey(address.getNumber()), null);
SignalServiceAddress masterAddress = masterDevice == null ? address : new SignalServiceAddress(masterDevice);
// We also need to use the original message ID and not -1
syncMessage = new LokiSyncMessage(masterAddress, templateMessageId);
}
SendMessageResult result = messageSender.sendMessage(messageId, address, UnidentifiedAccessUtil.getAccessFor(context, recipient), mediaMessage, Optional.fromNullable(syncMessage));
SendMessageResult result = messageSender.sendMessage(messageId, address, UnidentifiedAccessUtil.getAccessFor(context, recipient), mediaMessage);
if (result.getLokiAPIError() != null) {
throw result.getLokiAPIError();
} else {
@ -326,10 +327,9 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
long templateMessageID = data.getLong(KEY_TEMPLATE_MESSAGE_ID);
long messageID = data.getLong(KEY_MESSAGE_ID);
Address destination = Address.fromSerialized(data.getString(KEY_DESTINATION));
boolean isFriendRequest = data.getBoolean(KEY_IS_FRIEND_REQUEST);
boolean shouldSendSyncMessage = data.getBoolean(KEY_SHOULD_SEND_SYNC_MESSAGE);
String frMessage = data.hasString(KEY_CUSTOM_FR_MESSAGE) ? data.getString(KEY_CUSTOM_FR_MESSAGE) : null;
return new PushMediaSendJob(parameters, templateMessageID, messageID, destination, isFriendRequest, frMessage, shouldSendSyncMessage);
boolean isLokiPreKeyBundleMessage = data.getBoolean(KEY_IS_LOKI_PRE_KEY_BUNDLE_MESSAGE);
String customFRMessage = data.hasString(KEY_CUSTOM_FR_MESSAGE) ? data.getString(KEY_CUSTOM_FR_MESSAGE) : null;
return new PushMediaSendJob(parameters, templateMessageID, messageID, destination, isLokiPreKeyBundleMessage, customFRMessage);
}
}
}

View File

@ -57,7 +57,7 @@ public class PushNotificationReceiveJob extends PushReceivedJob implements Injec
synchronized (PushReceivedJob.RECEIVE_LOCK) {
receiver.retrieveMessages(envelope -> {
Log.i(tag, "Retrieved an envelope." + timeSuffix(startTime));
processEnvelope(envelope);
processEnvelope(envelope, false);
Log.i(tag, "Successfully processed an envelope." + timeSuffix(startTime));
});
TextSecurePreferences.setNeedsMessagePull(context, false);

View File

@ -22,7 +22,7 @@ public abstract class PushReceivedJob extends BaseJob {
super(parameters);
}
public void processEnvelope(@NonNull SignalServiceEnvelope envelope) {
public void processEnvelope(@NonNull SignalServiceEnvelope envelope, boolean isPushNotification) {
synchronized (RECEIVE_LOCK) {
try {
if (envelope.hasSource()) {
@ -37,18 +37,18 @@ public abstract class PushReceivedJob extends BaseJob {
if (envelope.isReceipt()) {
handleReceipt(envelope);
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage() || envelope.isUnidentifiedSender() || envelope.isFriendRequest()) {
handleMessage(envelope);
handleMessage(envelope, isPushNotification);
} else {
Log.w(TAG, "Received envelope of unknown type: " + envelope.getType());
}
} catch (Exception e) {
Log.d("Loki", "Failed to process envelope: " + e);
Log.d("Loki", "Failed to process envelope due to error: " + e);
}
}
}
private void handleMessage(SignalServiceEnvelope envelope) {
new PushDecryptJob(context).processMessage(envelope);
private void handleMessage(SignalServiceEnvelope envelope, boolean isPushNotification) {
new PushDecryptJob(context).processMessage(envelope, isPushNotification);
}
@SuppressLint("DefaultLocale")

View File

@ -9,8 +9,6 @@ import android.text.TextUtils;
import com.annimon.stream.Stream;
import org.greenrobot.eventbus.EventBus;
import org.signal.libsignal.metadata.certificate.InvalidCertificateException;
import org.signal.libsignal.metadata.certificate.SenderCertificate;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.TextSecureExpiredException;
import org.thoughtcrime.securesms.attachments.Attachment;
@ -68,7 +66,7 @@ public abstract class PushSendJob extends SendJob {
.setQueue(destination.serialize())
.addConstraint(NetworkConstraint.KEY)
.setLifespan(TimeUnit.DAYS.toMillis(1))
.setMaxAttempts(3)
.setMaxAttempts(1)
.build();
}
@ -284,13 +282,13 @@ public abstract class PushSendJob extends SendJob {
}
protected SignalServiceSyncMessage buildSelfSendSyncMessage(@NonNull Context context, @NonNull SignalServiceDataMessage message, Optional<UnidentifiedAccessPair> syncAccess) {
String primary = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
String localNumber = primary != null ? primary : TextSecurePreferences.getLocalNumber(context);
SentTranscriptMessage transcript = new SentTranscriptMessage(localNumber,
message.getTimestamp(),
message,
message.getExpiresInSeconds(),
Collections.singletonMap(localNumber, syncAccess.isPresent()));
String masterPublicKeyOrNull = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
String masterPublicKey = masterPublicKeyOrNull != null ? masterPublicKeyOrNull : TextSecurePreferences.getLocalNumber(context);
SentTranscriptMessage transcript = new SentTranscriptMessage(masterPublicKey,
message.getTimestamp(),
message,
message.getExpiresInSeconds(),
Collections.singletonMap(masterPublicKey, syncAccess.isPresent()));
return SignalServiceSyncMessage.forSentTranscript(transcript);
}

View File

@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
@ -33,9 +33,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSy
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
import org.whispersystems.signalservice.loki.api.LokiAPI;
import org.whispersystems.signalservice.loki.api.multidevice.LokiDeviceLinkUtilities;
import org.whispersystems.signalservice.loki.messaging.LokiSyncMessage;
import org.whispersystems.signalservice.loki.utilities.PromiseUtil;
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
import java.io.IOException;
@ -50,9 +48,8 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
private static final String KEY_TEMPLATE_MESSAGE_ID = "template_message_id";
private static final String KEY_MESSAGE_ID = "message_id";
private static final String KEY_DESTINATION = "destination";
private static final String KEY_IS_FRIEND_REQUEST = "is_friend_request";
private static final String KEY_IS_LOKI_PRE_KEY_BUNDLE_MESSAGE = "is_friend_request";
private static final String KEY_CUSTOM_FR_MESSAGE = "custom_friend_request_message";
private static final String KEY_SHOULD_SEND_SYNC_MESSAGE = "should_send_sync_message";
@Inject SignalServiceMessageSender messageSender;
@ -60,35 +57,38 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
private long templateMessageId; // The message ID of the message to template this send job from
// Loki - Multi device
private Address destination; // Destination to check whether this is another device we're sending to
private boolean isFriendRequest; // Whether this is a friend request message
private Address destination; // Used to check whether this is another device we're sending to
private boolean isLokiPreKeyBundleMessage; // Whether this is a friend request / session request / device link message
private String customFriendRequestMessage; // If this isn't set then we use the message body
private boolean shouldSendSyncMessage;
public PushTextSendJob(long messageId, Address destination) { this(messageId, messageId, destination, false); }
public PushTextSendJob(long templateMessageId, long messageId, Address destination, boolean shouldSendSyncMessage) { this(templateMessageId, messageId, destination, false, null, shouldSendSyncMessage); }
public PushTextSendJob(long templateMessageId, long messageId, Address destination, boolean isFriendRequest, String customFriendRequestMessage, boolean shouldSendSyncMessage) {
this(constructParameters(destination), templateMessageId, messageId, destination, isFriendRequest, customFriendRequestMessage, shouldSendSyncMessage);
public PushTextSendJob(long messageId, Address destination) {
this(messageId, messageId, destination);
}
private PushTextSendJob(@NonNull Job.Parameters parameters, long templateMessageId, long messageId, Address destination, boolean isFriendRequest, String customFriendRequestMessage, boolean shouldSendSyncMessage) {
public PushTextSendJob(long templateMessageId, long messageId, Address destination) {
this(templateMessageId, messageId, destination, false, null);
}
public PushTextSendJob(long templateMessageId, long messageId, Address destination, boolean isLokiPreKeyBundleMessage, String customFriendRequestMessage) {
this(constructParameters(destination), templateMessageId, messageId, destination, isLokiPreKeyBundleMessage, customFriendRequestMessage);
}
private PushTextSendJob(@NonNull Job.Parameters parameters, long templateMessageId, long messageId, Address destination, boolean isLokiPreKeyBundleMessage, String customFriendRequestMessage) {
super(parameters);
this.templateMessageId = templateMessageId;
this.messageId = messageId;
this.destination = destination;
this.isFriendRequest = isFriendRequest;
this.isLokiPreKeyBundleMessage = isLokiPreKeyBundleMessage;
this.customFriendRequestMessage = customFriendRequestMessage;
this.shouldSendSyncMessage = shouldSendSyncMessage;
}
@Override
public @NonNull Data serialize() {
Data.Builder builder = new Data.Builder()
.putLong(KEY_TEMPLATE_MESSAGE_ID, templateMessageId)
.putLong(KEY_MESSAGE_ID, messageId)
.putString(KEY_DESTINATION, destination.serialize())
.putBoolean(KEY_IS_FRIEND_REQUEST, isFriendRequest)
.putBoolean(KEY_SHOULD_SEND_SYNC_MESSAGE, shouldSendSyncMessage);
.putLong(KEY_TEMPLATE_MESSAGE_ID, templateMessageId)
.putLong(KEY_MESSAGE_ID, messageId)
.putString(KEY_DESTINATION, destination.serialize())
.putBoolean(KEY_IS_LOKI_PRE_KEY_BUNDLE_MESSAGE, isLokiPreKeyBundleMessage);
if (customFriendRequestMessage != null) { builder.putString(KEY_CUSTOM_FR_MESSAGE, customFriendRequestMessage); }
return builder.build();
@ -116,14 +116,14 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
boolean hasSameDestination = destination.equals(recordRecipient.getAddress());
if (hasSameDestination && !record.isPending() && !record.isFailed()) {
warn(TAG, "Message " + templateMessageId + " was already sent. Ignoring.");
Log.d("Loki", "Message with ID: " + templateMessageId + " was already sent; ignoring.");
return;
}
try {
log(TAG, "Sending message: " + templateMessageId + (hasSameDestination ? "" : "to another device."));
log(TAG, "Sending message: " + templateMessageId + (hasSameDestination ? "" : "to a linked device."));
Recipient recipient = Recipient.from(context, destination, false);
Recipient recipient = Recipient.from(context, destination, false);
byte[] profileKey = recipient.getProfileKey();
UnidentifiedAccessMode accessMode = recipient.getUnidentifiedAccessMode();
@ -158,16 +158,16 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
expirationManager.scheduleDeletion(record.getId(), record.isMms(), record.getExpiresIn());
}
log(TAG, "Sent message: " + templateMessageId + (hasSameDestination ? "" : "to another device."));
log(TAG, "Sent message: " + templateMessageId + (hasSameDestination ? "" : "to a linked device."));
} catch (InsecureFallbackApprovalException e) {
warn(TAG, "Failure", e);
warn(TAG, "Couldn't send message due to error: ", e);
if (messageId >= 0) {
database.markAsPendingInsecureSmsFallback(record.getId());
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
}
} catch (UntrustedIdentityException e) {
warn(TAG, "Failure", e);
warn(TAG, "Couldn't send message due to error: ", e);
if (messageId >= 0) {
database.addMismatchedIdentity(record.getId(), Address.fromSerialized(e.getE164Number()), e.getIdentityKey());
database.markAsSentFailed(record.getId());
@ -175,18 +175,17 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
}
} catch (LokiAPI.Error e) {
Log.d("Loki", "Couldn't send message due to error: " + e.getDescription());
if (messageId < 0) { return; }
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
lokiMessageDatabase.setErrorMessage(record.getId(), e.getDescription());
database.markAsSentFailed(record.getId());
if (messageId >= 0) {
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
lokiMessageDatabase.setErrorMessage(record.getId(), e.getDescription());
database.markAsSentFailed(record.getId());
}
}
}
@Override
public boolean onShouldRetry(@NonNull Exception exception) {
// Loki - Disable since we have our own retrying
// if (exception instanceof RetryLaterException) return true;
return false;
}
@ -208,7 +207,6 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
throws UntrustedIdentityException, InsecureFallbackApprovalException, RetryLaterException, LokiAPI.Error
{
try {
// rotateSenderCertificateIfNecessary();
Recipient recipient = Recipient.from(context, destination, false);
SignalServiceAddress address = getPushAddress(recipient.getAddress());
Optional<byte[]> profileKey = getProfileKey(recipient);
@ -216,41 +214,34 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
log(TAG, "Have access key to use: " + unidentifiedAccess.isPresent());
// Loki - Include a pre key bundle if the message is a friend request or an end session message
// Loki - Include a pre key bundle if needed
PreKeyBundle preKeyBundle;
if (isFriendRequest || message.isEndSession()) {
if (isLokiPreKeyBundleMessage || message.isEndSession()) {
preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.getNumber());
} else {
preKeyBundle = null;
}
String body = (isFriendRequest && customFriendRequestMessage != null) ? customFriendRequestMessage : message.getBody();
String body = (isLokiPreKeyBundleMessage && customFriendRequestMessage != null) ? customFriendRequestMessage : message.getBody();
SignalServiceDataMessage textSecureMessage = SignalServiceDataMessage.newBuilder()
.withTimestamp(message.getDateSent())
.withBody(body)
.withExpiration((int)(message.getExpiresIn() / 1000))
.withProfileKey(profileKey.orNull())
.asEndSessionMessage(message.isEndSession())
.asFriendRequest(isFriendRequest)
.asFriendRequest(isLokiPreKeyBundleMessage)
.withPreKeyBundle(preKeyBundle)
.build();
if (address.getNumber().equals(TextSecurePreferences.getLocalNumber(context))) {
if (SessionMetaProtocol.shared.isNoteToSelf(address.getNumber())) {
// Loki - Device link messages don't go through here
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, textSecureMessage, syncAccess);
SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, textSecureMessage, syncAccess);
messageSender.sendMessage(templateMessageId, syncMessage, syncAccess);
messageSender.sendMessage(syncMessage, syncAccess);
return syncAccess.isPresent();
} else {
LokiSyncMessage syncMessage = null;
if (shouldSendSyncMessage) {
// Set the sync message destination to the master device, this way it will show that we sent a message to the master device and not the slave device
String masterDevice = PromiseUtil.get(LokiDeviceLinkUtilities.INSTANCE.getMasterHexEncodedPublicKey(address.getNumber()), null);
SignalServiceAddress masterAddress = masterDevice == null ? address : new SignalServiceAddress(masterDevice);
// We also need to use the original message ID and not -1
syncMessage = new LokiSyncMessage(masterAddress, templateMessageId);
}
SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage, Optional.fromNullable(syncMessage));
SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage);
if (result.getLokiAPIError() != null) {
throw result.getLokiAPIError();
} else {
@ -272,10 +263,9 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
long templateMessageID = data.getLong(KEY_TEMPLATE_MESSAGE_ID);
long messageID = data.getLong(KEY_MESSAGE_ID);
Address destination = Address.fromSerialized(data.getString(KEY_DESTINATION));
boolean isFriendRequest = data.getBoolean(KEY_IS_FRIEND_REQUEST);
String frMessage = data.hasString(KEY_CUSTOM_FR_MESSAGE) ? data.getString(KEY_CUSTOM_FR_MESSAGE) : null;
boolean shouldSendSyncMessage = data.getBoolean(KEY_SHOULD_SEND_SYNC_MESSAGE);
return new PushTextSendJob(parameters, templateMessageID, messageID, destination, isFriendRequest, frMessage, shouldSendSyncMessage);
boolean isLokiPreKeyBundleMessage = data.getBoolean(KEY_IS_LOKI_PRE_KEY_BUNDLE_MESSAGE);
String customFRMessage = data.hasString(KEY_CUSTOM_FR_MESSAGE) ? data.getString(KEY_CUSTOM_FR_MESSAGE) : null;
return new PushTextSendJob(parameters, templateMessageID, messageID, destination, isLokiPreKeyBundleMessage, customFRMessage);
}
}
}

View File

@ -2,16 +2,11 @@ package org.thoughtcrime.securesms.jobs;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.crypto.PreKeyUtil;
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.TextSecurePreferences;
import org.whispersystems.libsignal.IdentityKeyPair;
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
@ -34,7 +29,7 @@ public class RefreshPreKeysJob extends BaseJob implements InjectableType {
this(new Job.Parameters.Builder()
.setQueue("RefreshPreKeysJob")
.addConstraint(NetworkConstraint.KEY)
.setMaxAttempts(5)
.setMaxAttempts(3)
.build());
}
@ -54,15 +49,7 @@ public class RefreshPreKeysJob extends BaseJob implements InjectableType {
@Override
public void onRun() throws IOException {
if (TextSecurePreferences.isSignedPreKeyRegistered(context)) {
Log.d("Loki", "A signed pre key has already been registered.");
} else {
Log.d("Loki", "Registering a new signed pre key.");
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context);
PreKeyUtil.generateSignedPreKey(context, identityKey, true);
TextSecurePreferences.setSignedPreKeyRegistered(context, true);
ApplicationContext.getInstance(context).getJobManager().add(new CleanPreKeysJob());
}
SessionManagementProtocol.refreshSignedPreKey(context);
}
/* Loki - Original code
@ -77,7 +64,7 @@ public class RefreshPreKeysJob extends BaseJob implements InjectableType {
return;
}
List<PreKeyRecord> preKeyRecords = PreKeyUtil.generatePreKeys(context);
List<PreKeyRecord> preKeyRecords = PreKeyUtil.generatePreKeyRecords(context);
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context);
SignedPreKeyRecord signedPreKeyRecord = PreKeyUtil.generateSignedPreKey(context, identityKey, false);

View File

@ -79,7 +79,6 @@ public class RequestGroupInfoJob extends BaseJob implements InjectableType {
.withTimestamp(System.currentTimeMillis())
.build();
// TODO: Message ID
messageSender.sendMessage(0, new SignalServiceAddress(source),
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromExternal(context, source), false)),
message);

View File

@ -49,7 +49,7 @@ public class RetrieveProfileAvatarJob extends BaseJob implements InjectableType
.setQueue("RetrieveProfileAvatarJob" + recipient.getAddress().serialize())
.addConstraint(NetworkConstraint.KEY)
.setLifespan(TimeUnit.HOURS.toMillis(1))
.setMaxAttempts(2)
.setMaxAttempts(3)
.build(),
recipient,
profileAvatar);
@ -99,8 +99,8 @@ public class RetrieveProfileAvatarJob extends BaseJob implements InjectableType
File downloadDestination = File.createTempFile("avatar", "jpg", context.getCacheDir());
try {
InputStream avatarStream = receiver.retrieveProfileAvatar(profileAvatar, downloadDestination, profileKey, MAX_PROFILE_SIZE_BYTES);
File decryptDestination = File.createTempFile("avatar", "jpg", context.getCacheDir());
InputStream avatarStream = receiver.retrieveProfileAvatar(profileAvatar, downloadDestination, profileKey, MAX_PROFILE_SIZE_BYTES);
File decryptDestination = File.createTempFile("avatar", "jpg", context.getCacheDir());
Util.copy(avatarStream, new FileOutputStream(decryptDestination));
decryptDestination.renameTo(AvatarHelper.getAvatarFile(context, recipient.getAddress()));

View File

@ -77,7 +77,7 @@ public class RetrieveProfileJob extends BaseJob implements InjectableType {
@Override
public void onRun() throws IOException, InvalidKeyException {
// Loki - Disable retrieve profile
// Loki - Do nothing
/*
try {
if (recipient.isGroupRecipient()) handleGroupRecipient(recipient);

Some files were not shown because too many files have changed in this diff Show More