mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-17 15:18:26 +00:00
Remove the concept of friend requests
This commit is contained in:
parent
21554441f3
commit
455471b20e
@ -45,174 +45,159 @@
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/body_bubble"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginEnd="@dimen/massive_spacing"
|
||||
android:layout_marginStart="12dp"
|
||||
android:paddingTop="@dimen/medium_spacing"
|
||||
android:paddingBottom="@dimen/medium_spacing"
|
||||
android:layout_toStartOf="@+id/indicators_parent"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
android:orientation="vertical"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false">
|
||||
android:clipChildren="false"
|
||||
android:background="@color/white"
|
||||
tools:backgroundTint="@color/conversation_blue">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/body_bubble"
|
||||
android:id="@+id/group_sender_holder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/massive_spacing"
|
||||
android:layout_marginStart="12dp"
|
||||
android:paddingTop="@dimen/medium_spacing"
|
||||
android:paddingBottom="@dimen/medium_spacing"
|
||||
android:orientation="vertical"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false"
|
||||
android:background="@color/white"
|
||||
tools:backgroundTint="@color/conversation_blue">
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginBottom="@dimen/medium_spacing"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/group_sender_holder"
|
||||
<TextView
|
||||
android:id="@+id/group_message_sender"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginBottom="@dimen/medium_spacing"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/group_message_sender"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="4sp"
|
||||
style="@style/Signal.Text.Preview"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:textColor="?conversation_item_received_text_primary_color"
|
||||
android:textSize="@dimen/small_font_size"
|
||||
android:alpha="0.6"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
tools:visibility="visible"
|
||||
tools:text="+14152222222"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/group_message_sender_profile"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="4sp"
|
||||
android:paddingEnd="4sp"
|
||||
style="@style/Signal.Text.Preview"
|
||||
android:fontFamily="sans-serif-regular"
|
||||
android:textColor="?conversation_item_received_text_primary_color"
|
||||
android:textStyle="italic"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
tools:text="~Clement Duval"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<org.thoughtcrime.securesms.components.QuoteView
|
||||
android:id="@+id/quote_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/large_spacing"
|
||||
android:layout_marginBottom="@dimen/medium_spacing"
|
||||
android:layout_marginEnd="@dimen/large_spacing"
|
||||
android:visibility="gone"
|
||||
app:message_type="incoming"
|
||||
app:quote_colorPrimary="@color/text"
|
||||
app:quote_colorSecondary="@color/text"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/shared_contact_view_stub"
|
||||
android:layout="@layout/conversation_item_received_shared_contact"
|
||||
android:layout_width="@dimen/media_bubble_default_dimens"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/message_bubble_top_padding"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/image_view_stub"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout="@layout/conversation_item_received_thumbnail" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/sticker_view_stub"
|
||||
android:layout_width="@dimen/media_bubble_sticker_dimens"
|
||||
android:layout_height="@dimen/media_bubble_sticker_dimens"
|
||||
android:layout="@layout/conversation_item_received_sticker" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/link_preview_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout="@layout/conversation_item_received_link_preview" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/audio_view_stub"
|
||||
android:layout="@layout/conversation_item_received_audio"
|
||||
android:layout_width="210dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/document_view_stub"
|
||||
android:layout="@layout/conversation_item_received_document"
|
||||
android:layout_width="210dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/conversation_item_body"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
style="@style/Signal.Text.Body"
|
||||
android:layout_marginEnd="4sp"
|
||||
style="@style/Signal.Text.Preview"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:textColor="?conversation_item_received_text_primary_color"
|
||||
android:textColorLink="?conversation_item_received_text_primary_color"
|
||||
android:ellipsize="end"
|
||||
app:scaleEmojis="true"
|
||||
app:emoji_maxLength="1000"
|
||||
tools:text="Mango pickle lorem ipsum"/>
|
||||
|
||||
<org.thoughtcrime.securesms.components.ConversationItemFooter
|
||||
android:id="@+id/conversation_item_footer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:textSize="@dimen/small_font_size"
|
||||
android:alpha="0.6"
|
||||
app:footer_text_color="?conversation_item_received_text_secondary_color"
|
||||
app:footer_icon_color="?conversation_item_received_text_secondary_color"/>
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
tools:visibility="visible"
|
||||
tools:text="+14152222222"/>
|
||||
|
||||
<org.thoughtcrime.securesms.components.ConversationItemFooter
|
||||
android:id="@+id/conversation_item_sticker_footer"
|
||||
<TextView
|
||||
android:id="@+id/group_message_sender_profile"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:visibility="gone"
|
||||
app:footer_text_color="?conversation_sticker_footer_text_color"
|
||||
app:footer_icon_color="?conversation_sticker_footer_icon_color"/>
|
||||
android:paddingStart="4sp"
|
||||
android:paddingEnd="4sp"
|
||||
style="@style/Signal.Text.Preview"
|
||||
android:fontFamily="sans-serif-regular"
|
||||
android:textColor="?conversation_item_received_text_primary_color"
|
||||
android:textStyle="italic"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
tools:text="~Clement Duval"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<org.thoughtcrime.securesms.loki.views.FriendRequestView
|
||||
android:id="@+id/friend_request_view"
|
||||
<org.thoughtcrime.securesms.components.QuoteView
|
||||
android:id="@+id/quote_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/large_spacing"
|
||||
android:layout_marginBottom="@dimen/medium_spacing"
|
||||
android:layout_marginEnd="@dimen/large_spacing"
|
||||
android:visibility="gone"
|
||||
app:message_type="incoming"
|
||||
app:quote_colorPrimary="@color/text"
|
||||
app:quote_colorSecondary="@color/text"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/shared_contact_view_stub"
|
||||
android:layout="@layout/conversation_item_received_shared_contact"
|
||||
android:layout_width="@dimen/media_bubble_default_dimens"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/message_bubble_top_padding"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/image_view_stub"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout="@layout/conversation_item_received_thumbnail" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/sticker_view_stub"
|
||||
android:layout_width="@dimen/media_bubble_sticker_dimens"
|
||||
android:layout_height="@dimen/media_bubble_sticker_dimens"
|
||||
android:layout="@layout/conversation_item_received_sticker" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/link_preview_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
android:layout="@layout/conversation_item_received_link_preview" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/audio_view_stub"
|
||||
android:layout="@layout/conversation_item_received_audio"
|
||||
android:layout_width="210dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/document_view_stub"
|
||||
android:layout="@layout/conversation_item_received_document"
|
||||
android:layout_width="210dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/conversation_item_body"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
style="@style/Signal.Text.Body"
|
||||
android:textColor="?conversation_item_received_text_primary_color"
|
||||
android:textColorLink="?conversation_item_received_text_primary_color"
|
||||
android:ellipsize="end"
|
||||
app:scaleEmojis="true"
|
||||
app:emoji_maxLength="1000"
|
||||
tools:text="Mango pickle lorem ipsum"/>
|
||||
|
||||
<org.thoughtcrime.securesms.components.ConversationItemFooter
|
||||
android:id="@+id/conversation_item_footer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:alpha="0.6"
|
||||
app:footer_text_color="?conversation_item_received_text_secondary_color"
|
||||
app:footer_icon_color="?conversation_item_received_text_secondary_color"/>
|
||||
|
||||
<org.thoughtcrime.securesms.components.ConversationItemFooter
|
||||
android:id="@+id/conversation_item_sticker_footer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:visibility="gone"
|
||||
app:footer_text_color="?conversation_sticker_footer_text_color"
|
||||
app:footer_icon_color="?conversation_sticker_footer_icon_color"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -23,150 +23,135 @@
|
||||
android:clipChildren="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/body_bubble"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginStart="@dimen/massive_spacing"
|
||||
android:paddingTop="@dimen/medium_spacing"
|
||||
android:paddingBottom="@dimen/medium_spacing"
|
||||
android:layout_toStartOf="@+id/indicators_parent"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
android:layout_gravity="end"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false">
|
||||
android:clipChildren="false"
|
||||
android:background="@color/white"
|
||||
tools:backgroundTint="@color/core_grey_05">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/body_bubble"
|
||||
<org.thoughtcrime.securesms.components.QuoteView
|
||||
android:id="@+id/quote_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginStart="@dimen/massive_spacing"
|
||||
android:paddingTop="@dimen/medium_spacing"
|
||||
android:paddingBottom="@dimen/medium_spacing"
|
||||
android:layout_gravity="end"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false"
|
||||
android:background="@color/white"
|
||||
tools:backgroundTint="@color/core_grey_05">
|
||||
android:layout_marginStart="@dimen/large_spacing"
|
||||
android:layout_marginBottom="@dimen/medium_spacing"
|
||||
android:layout_marginEnd="@dimen/large_spacing"
|
||||
android:visibility="gone"
|
||||
app:message_type="outgoing"
|
||||
app:quote_colorPrimary="@color/text"
|
||||
app:quote_colorSecondary="@color/text"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<org.thoughtcrime.securesms.components.QuoteView
|
||||
android:id="@+id/quote_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/large_spacing"
|
||||
android:layout_marginBottom="@dimen/medium_spacing"
|
||||
android:layout_marginEnd="@dimen/large_spacing"
|
||||
android:visibility="gone"
|
||||
app:message_type="outgoing"
|
||||
app:quote_colorPrimary="@color/text"
|
||||
app:quote_colorSecondary="@color/text"
|
||||
tools:visibility="visible"/>
|
||||
<ViewStub
|
||||
android:id="@+id/shared_contact_view_stub"
|
||||
android:layout="@layout/conversation_item_sent_shared_contact"
|
||||
android:layout_width="@dimen/media_bubble_default_dimens"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/medium_spacing"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/shared_contact_view_stub"
|
||||
android:layout="@layout/conversation_item_sent_shared_contact"
|
||||
android:layout_width="@dimen/media_bubble_default_dimens"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/medium_spacing"
|
||||
android:visibility="gone"/>
|
||||
<ViewStub
|
||||
android:id="@+id/image_view_stub"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout="@layout/conversation_item_sent_thumbnail" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/image_view_stub"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout="@layout/conversation_item_sent_thumbnail" />
|
||||
<ViewStub
|
||||
android:id="@+id/sticker_view_stub"
|
||||
android:layout_width="@dimen/media_bubble_sticker_dimens"
|
||||
android:layout_height="@dimen/media_bubble_sticker_dimens"
|
||||
android:layout="@layout/conversation_item_sent_sticker" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/sticker_view_stub"
|
||||
android:layout_width="@dimen/media_bubble_sticker_dimens"
|
||||
android:layout_height="@dimen/media_bubble_sticker_dimens"
|
||||
android:layout="@layout/conversation_item_sent_sticker" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/link_preview_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout="@layout/conversation_item_sent_link_preview" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/audio_view_stub"
|
||||
android:layout="@layout/conversation_item_sent_audio"
|
||||
android:layout_width="210dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/document_view_stub"
|
||||
android:layout="@layout/conversation_item_sent_document"
|
||||
android:layout_width="210dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/conversation_item_body"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
style="@style/Signal.Text.Body"
|
||||
android:textColor="?conversation_item_sent_text_primary_color"
|
||||
android:textColorLink="?conversation_item_sent_text_primary_color"
|
||||
android:ellipsize="end"
|
||||
app:scaleEmojis="true"
|
||||
app:emoji_maxLength="1000"
|
||||
tools:text="Mango pickle lorem ipsum"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/group_sender_holder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/group_message_sender"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/group_message_sender_profile"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.ConversationItemFooter
|
||||
android:id="@+id/conversation_item_footer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
app:footer_text_color="?attr/conversation_item_sent_text_secondary_color"
|
||||
app:footer_icon_color="?attr/conversation_item_sent_icon_color"/>
|
||||
|
||||
<org.thoughtcrime.securesms.components.ConversationItemFooter
|
||||
android:id="@+id/conversation_item_sticker_footer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:visibility="gone"
|
||||
app:footer_text_color="?conversation_sticker_footer_text_color"
|
||||
app:footer_icon_color="?conversation_sticker_footer_icon_color"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<org.thoughtcrime.securesms.loki.views.FriendRequestView
|
||||
android:id="@+id/friend_request_view"
|
||||
<ViewStub
|
||||
android:id="@+id/link_preview_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout="@layout/conversation_item_sent_link_preview" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/audio_view_stub"
|
||||
android:layout="@layout/conversation_item_sent_audio"
|
||||
android:layout_width="210dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/document_view_stub"
|
||||
android:layout="@layout/conversation_item_sent_document"
|
||||
android:layout_width="210dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/conversation_item_body"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
style="@style/Signal.Text.Body"
|
||||
android:textColor="?conversation_item_sent_text_primary_color"
|
||||
android:textColorLink="?conversation_item_sent_text_primary_color"
|
||||
android:ellipsize="end"
|
||||
app:scaleEmojis="true"
|
||||
app:emoji_maxLength="1000"
|
||||
tools:text="Mango pickle lorem ipsum"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/group_sender_holder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/group_message_sender"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/group_message_sender_profile"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.ConversationItemFooter
|
||||
android:id="@+id/conversation_item_footer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
app:footer_text_color="?attr/conversation_item_sent_text_secondary_color"
|
||||
app:footer_icon_color="?attr/conversation_item_sent_icon_color"/>
|
||||
|
||||
<org.thoughtcrime.securesms.components.ConversationItemFooter
|
||||
android:id="@+id/conversation_item_sticker_footer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginStart="@dimen/message_bubble_horizontal_padding"
|
||||
android:layout_marginEnd="@dimen/message_bubble_horizontal_padding"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:visibility="gone"
|
||||
app:footer_text_color="?conversation_sticker_footer_text_color"
|
||||
app:footer_icon_color="?conversation_sticker_footer_icon_color"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<org.thoughtcrime.securesms.components.AlertView
|
||||
|
@ -1561,4 +1561,5 @@ Otrzymano wiadomość wymiany klucz dla niepoprawnej wersji protokołu.</string>
|
||||
<string name="fragment_contact_selection_contacts_title">Łączność</string>
|
||||
<string name="fragment_contact_selection_closed_groups_title">Grupy zamknięte</string>
|
||||
<string name="fragment_contact_selection_open_groups_title">Otwórz grupy</string>
|
||||
|
||||
</resources>
|
||||
|
@ -1358,6 +1358,7 @@
|
||||
|
||||
|
||||
|
||||
<!-- Session -->
|
||||
<string name="continue_2">Продолжить</string>
|
||||
<string name="copy">Копировать</string>
|
||||
<string name="invalid_url">Неверная ссылка</string>
|
||||
|
@ -1655,7 +1655,6 @@
|
||||
|
||||
|
||||
<!-- Session -->
|
||||
|
||||
<string name="continue_2">Continue</string>
|
||||
<string name="copy">Copy</string>
|
||||
<string name="invalid_url">Invalid URL</string>
|
||||
|
@ -61,13 +61,13 @@ import org.thoughtcrime.securesms.logging.PersistentLogger;
|
||||
import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger;
|
||||
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.loki.api.BackgroundPollWorker;
|
||||
import org.thoughtcrime.securesms.loki.api.LokiPublicChatManager;
|
||||
import org.thoughtcrime.securesms.loki.api.PublicChatManager;
|
||||
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.SessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.loki.protocol.PushEphemeralMessageSendJob;
|
||||
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
|
||||
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
||||
@ -154,7 +154,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
// Loki
|
||||
public MessageNotifier messageNotifier = null;
|
||||
public Poller lokiPoller = null;
|
||||
public LokiPublicChatManager lokiPublicChatManager = null;
|
||||
public PublicChatManager publicChatManager = null;
|
||||
private PublicChatAPI publicChatAPI = null;
|
||||
public Broadcaster broadcaster = null;
|
||||
public SignalCommunicationModule communicationModule;
|
||||
@ -184,7 +184,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(this);
|
||||
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
LokiSessionResetImplementation sessionResetImpl = new LokiSessionResetImplementation(this);
|
||||
SessionResetImplementation sessionResetImpl = new SessionResetImplementation(this);
|
||||
if (userPublicKey != null) {
|
||||
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||
@ -203,7 +203,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
}
|
||||
}
|
||||
resubmitProfilePictureIfNeeded();
|
||||
lokiPublicChatManager = new LokiPublicChatManager(this);
|
||||
publicChatManager = new PublicChatManager(this);
|
||||
updateOpenGroupProfilePicturesIfNeeded();
|
||||
registerForFCMIfNeeded(false);
|
||||
// ========
|
||||
@ -229,8 +229,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
// Loki
|
||||
if (lokiPoller != null) { lokiPoller.setCaughtUp(false); }
|
||||
startPollingIfNeeded();
|
||||
lokiPublicChatManager.markAllAsNotCaughtUp();
|
||||
lokiPublicChatManager.startPollersIfNeeded();
|
||||
publicChatManager.markAllAsNotCaughtUp();
|
||||
publicChatManager.startPollersIfNeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -241,7 +241,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
messageNotifier.setVisibleThread(-1);
|
||||
// Loki
|
||||
if (lokiPoller != null) { lokiPoller.stopIfNeeded(); }
|
||||
if (lokiPublicChatManager != null) { lokiPublicChatManager.stopPollers(); }
|
||||
if (publicChatManager != null) { publicChatManager.stopPollers(); }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -322,7 +322,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(GroupCreateActivity.this, PushContactSelectionActivity.class);
|
||||
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_FRIENDS);
|
||||
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_CONTACTS);
|
||||
startActivityForResult(intent, PICK_CONTACT);
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState, boolean ready) {
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_FRIENDS);
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_CONTACTS);
|
||||
getIntent().putExtra(ContactSelectionListFragment.MULTI_SELECT, true);
|
||||
getIntent().putExtra(ContactSelectionListFragment.REFRESHABLE, false);
|
||||
|
||||
|
@ -84,7 +84,7 @@ public class TypingStatusSender {
|
||||
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||
Recipient recipient = threadDatabase.getRecipientForThreadId(threadId);
|
||||
// Loki - Check whether we want to send a typing indicator to this user
|
||||
if (!SessionMetaProtocol.shouldSendTypingIndicator(recipient, context)) { return; }
|
||||
if (recipient != null && !SessionMetaProtocol.shouldSendTypingIndicator(recipient.getAddress())) { return; }
|
||||
// Loki - Take into account multi device
|
||||
Set<String> linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(recipient.getAddress().serialize());
|
||||
for (String device : linkedDevices) {
|
||||
|
@ -68,7 +68,6 @@ import android.view.View.OnFocusChangeListener;
|
||||
import android.view.View.OnKeyListener;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
@ -81,7 +80,6 @@ import com.annimon.stream.Stream;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.ExpirationDialog;
|
||||
import org.thoughtcrime.securesms.GroupCreateActivity;
|
||||
@ -159,10 +157,8 @@ 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;
|
||||
@ -231,7 +227,6 @@ 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;
|
||||
@ -272,8 +267,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
ComposeText.CursorPositionChangedListener,
|
||||
ConversationSearchBottomBar.EventListener,
|
||||
StickerKeyboardProvider.StickerEventListener,
|
||||
LokiThreadDatabaseDelegate,
|
||||
FriendRequestViewDelegate
|
||||
LokiThreadDatabaseDelegate
|
||||
{
|
||||
private static final String TAG = ConversationActivity.class.getSimpleName();
|
||||
|
||||
@ -355,14 +349,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
// Message status bar
|
||||
private ArrayList<BroadcastReceiver> broadcastReceivers = new ArrayList<>();
|
||||
private String messageStatus = null;
|
||||
private String messageStatus = null;
|
||||
|
||||
// Mentions
|
||||
private View mentionCandidateSelectionViewContainer;
|
||||
private View mentionCandidateSelectionViewContainer;
|
||||
private MentionCandidateSelectionView mentionCandidateSelectionView;
|
||||
private int currentMentionStartIndex = -1;
|
||||
private ArrayList<Mention> mentions = new ArrayList<>();
|
||||
private String oldText = "";
|
||||
private int currentMentionStartIndex = -1;
|
||||
private ArrayList<Mention> mentions = new ArrayList<>();
|
||||
private String oldText = "";
|
||||
|
||||
// Restoration
|
||||
protected SessionRestoreBannerView sessionRestoreBannerView;
|
||||
@ -386,7 +380,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
getWindow().getDecorView().setBackgroundColor(color);
|
||||
|
||||
fragment = initFragment(R.id.fragment_content, new ConversationFragment(), dynamicLanguage.getCurrentLocale());
|
||||
fragment.friendRequestViewDelegate = this;
|
||||
|
||||
registerMessageStatusObserver("calculatingPoW");
|
||||
registerMessageStatusObserver("contactingNetwork");
|
||||
@ -554,8 +547,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
DatabaseFactory.getLokiThreadDatabase(this).setDelegate(this);
|
||||
|
||||
updateInputPanel();
|
||||
|
||||
updateSessionRestoreBanner();
|
||||
|
||||
Log.i(TAG, "onResume() Finished: " + (System.currentTimeMillis() - getIntent().getLongExtra(TIMING_EXTRA, 0)));
|
||||
@ -2252,26 +2243,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
updateLinkPreviewState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleThreadFriendRequestStatusChanged(long threadID) {
|
||||
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; }
|
||||
}
|
||||
}
|
||||
if (isUpdateNeeded) {
|
||||
updateInputPanel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSessionRestoreDevicesChanged(long threadID) {
|
||||
if (threadID == this.threadId) {
|
||||
@ -2279,21 +2250,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
|
||||
private void updateInputPanel() {
|
||||
boolean shouldInputPanelBeEnabled = FriendRequestProtocol.shouldInputPanelBeEnabled(this, recipient);
|
||||
Util.runOnMain(() -> {
|
||||
updateToggleButtonState();
|
||||
String hint = shouldInputPanelBeEnabled ? "Message" : "Pending session request";
|
||||
inputPanel.setHint(hint);
|
||||
inputPanel.setEnabled(shouldInputPanelBeEnabled);
|
||||
if (shouldInputPanelBeEnabled && inputPanel.getVisibility() == View.VISIBLE) {
|
||||
inputPanel.composeText.requestFocus();
|
||||
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
|
||||
inputMethodManager.showSoftInput(inputPanel.composeText, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendMessage() {
|
||||
if (inputPanel.isRecordingInLockedMode()) {
|
||||
inputPanel.releaseRecordingLock();
|
||||
@ -2395,11 +2351,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
outgoingMessage = outgoingMessageCandidate;
|
||||
}
|
||||
|
||||
// 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
|
||||
&& !SessionMetaProtocol.shared.isNoteToSelf(recipient.getAddress().serialize()); // Needed for stageOutgoingMessage(...)
|
||||
|
||||
if (clearComposeBox) {
|
||||
inputPanel.clearQuote();
|
||||
attachmentManager.clear(glideRequests, false);
|
||||
@ -2448,11 +2399,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
message = new OutgoingTextMessage(recipient, messageBody, expiresIn, subscriptionId);
|
||||
}
|
||||
|
||||
// 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
|
||||
&& !SessionMetaProtocol.shared.isNoteToSelf(recipient.getAddress().serialize()); // Needed for stageOutgoingMessage(...)
|
||||
|
||||
silentlySetComposeText("");
|
||||
final long id = fragment.stageOutgoingMessage(message);
|
||||
|
||||
@ -2482,13 +2428,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void updateToggleButtonState() {
|
||||
if (!FriendRequestProtocol.shouldAttachmentButtonBeEnabled(this, recipient)) {
|
||||
buttonToggle.display(sendButton);
|
||||
quickAttachmentToggle.hide();
|
||||
inlineAttachmentToggle.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputPanel.isRecordingInLockedMode()) {
|
||||
buttonToggle.display(sendButton);
|
||||
quickAttachmentToggle.show();
|
||||
@ -3192,19 +3131,5 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
updateSubtitleTextView();
|
||||
updateMessageStatusProgressBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptFriendRequest(@NotNull MessageRecord friendRequest) {
|
||||
if (recipient.isGroupRecipient()) { return; }
|
||||
FriendRequestProtocol.acceptFriendRequest(this, recipient);
|
||||
updateInputPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rejectFriendRequest(@NotNull MessageRecord friendRequest) {
|
||||
if (recipient.isGroupRecipient()) { return; }
|
||||
FriendRequestProtocol.rejectFriendRequest(this, recipient);
|
||||
updateInputPanel();
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ 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.views.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
@ -108,8 +107,6 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
||||
private MessageRecord recordToPulseHighlight;
|
||||
private String searchQuery;
|
||||
|
||||
public FriendRequestViewDelegate friendRequestViewDelegate; // Loki
|
||||
|
||||
protected static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public <V extends View & BindableConversationItem> ViewHolder(final @NonNull V itemView) {
|
||||
super(itemView);
|
||||
@ -202,11 +199,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
||||
MessageRecord previousRecord = adapterPosition < getItemCount() - 1 && !isFooterPosition(adapterPosition + 1) ? getRecordForPositionOrThrow(adapterPosition + 1) : null;
|
||||
MessageRecord nextRecord = adapterPosition > 0 && !isHeaderPosition(adapterPosition - 1) ? getRecordForPositionOrThrow(adapterPosition - 1) : null;
|
||||
|
||||
BindableConversationItem conversationItem = viewHolder.getView();
|
||||
if (conversationItem instanceof ConversationItem) {
|
||||
((ConversationItem)conversationItem).friendRequestViewDelegate = this.friendRequestViewDelegate;
|
||||
}
|
||||
conversationItem.bind(messageRecord,
|
||||
viewHolder.getView().bind(messageRecord,
|
||||
Optional.fromNullable(previousRecord),
|
||||
Optional.fromNullable(nextRecord),
|
||||
glideRequests,
|
||||
|
@ -79,7 +79,6 @@ 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.views.FriendRequestViewDelegate;
|
||||
import org.thoughtcrime.securesms.longmessage.LongMessageActivity;
|
||||
import org.thoughtcrime.securesms.mediasend.Media;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
@ -151,7 +150,6 @@ public class ConversationFragment extends Fragment
|
||||
private View composeDivider;
|
||||
private View scrollToBottomButton;
|
||||
private TextView scrollDateHeader;
|
||||
public FriendRequestViewDelegate friendRequestViewDelegate; // Loki
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
@ -706,7 +704,6 @@ public class ConversationFragment extends Fragment
|
||||
if (adapter == null) {
|
||||
return;
|
||||
}
|
||||
adapter.friendRequestViewDelegate = this.friendRequestViewDelegate;
|
||||
|
||||
if (cursor.getCount() >= PARTIAL_CONVERSATION_LIMIT && loader.hasLimit()) {
|
||||
adapter.setFooterView(topLoadMoreView);
|
||||
|
@ -86,10 +86,7 @@ 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.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;
|
||||
@ -158,7 +155,6 @@ public class ConversationItem extends LinearLayout
|
||||
private ViewGroup contactPhotoHolder;
|
||||
private AlertView alertView;
|
||||
private ViewGroup container;
|
||||
private FriendRequestView friendRequestView;
|
||||
|
||||
private @NonNull Set<MessageRecord> batchSelected = new HashSet<>();
|
||||
private Recipient conversationRecipient;
|
||||
@ -182,8 +178,6 @@ public class ConversationItem extends LinearLayout
|
||||
|
||||
private final Context context;
|
||||
|
||||
public FriendRequestViewDelegate friendRequestViewDelegate; // Loki
|
||||
|
||||
public ConversationItem(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@ -223,7 +217,6 @@ public class ConversationItem extends LinearLayout
|
||||
this.groupSenderHolder = findViewById(R.id.group_sender_holder);
|
||||
this.quoteView = findViewById(R.id.quote_view);
|
||||
this.container = findViewById(R.id.container);
|
||||
this.friendRequestView = findViewById(R.id.friend_request_view);
|
||||
|
||||
setOnClickListener(new ClickListener(null));
|
||||
|
||||
@ -269,7 +262,6 @@ public class ConversationItem extends LinearLayout
|
||||
setQuote(messageRecord, previousMessageRecord, nextMessageRecord, groupThread);
|
||||
setMessageSpacing(context, messageRecord, previousMessageRecord, nextMessageRecord, groupThread);
|
||||
setFooter(messageRecord, nextMessageRecord, locale, groupThread);
|
||||
setFriendRequestView(messageRecord);
|
||||
adjustMarginsIfNeeded(messageRecord);
|
||||
}
|
||||
|
||||
@ -807,8 +799,8 @@ public class ConversationItem extends LinearLayout
|
||||
layoutParams.setMarginStart((groupThread && !isRSSFeed) ? groupThreadMargin : defaultMargin);
|
||||
bodyBubble.setLayoutParams(layoutParams);
|
||||
if (profilePictureView == null) return;
|
||||
profilePictureView.setHexEncodedPublicKey(recipient.getAddress().toString());
|
||||
profilePictureView.setAdditionalHexEncodedPublicKey(null);
|
||||
profilePictureView.setPublicKey(recipient.getAddress().toString());
|
||||
profilePictureView.setAdditionalPublicKey(null);
|
||||
profilePictureView.setRSSFeed(false);
|
||||
profilePictureView.setGlide(glideRequests);
|
||||
profilePictureView.update();
|
||||
@ -920,11 +912,6 @@ public class ConversationItem extends LinearLayout
|
||||
}
|
||||
}
|
||||
|
||||
private void setFriendRequestView(@NonNull MessageRecord record) {
|
||||
friendRequestView.setDelegate(friendRequestViewDelegate);
|
||||
friendRequestView.update(record);
|
||||
}
|
||||
|
||||
private ConversationItemFooter getActiveFooter(@NonNull MessageRecord messageRecord) {
|
||||
if (hasSticker(messageRecord)) {
|
||||
return stickerFooter;
|
||||
@ -1067,10 +1054,8 @@ public class ConversationItem extends LinearLayout
|
||||
int spacingBottom = spacingTop;
|
||||
|
||||
boolean isOutgoingStack = current.isOutgoing() && previous.orNull() != null && previous.get().isOutgoing();
|
||||
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
|
||||
boolean isPreviousMessageFriendRequest = previous.orNull() != null && lokiMessageDatabase.isFriendRequest(previous.get().id);
|
||||
|
||||
if (isOutgoingStack && isPreviousMessageFriendRequest) {
|
||||
if (isOutgoingStack) {
|
||||
spacingTop = readDimen(context, R.dimen.conversation_vertical_message_spacing_default);
|
||||
}
|
||||
|
||||
|
@ -885,7 +885,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
0, message.isSecureMessage() ? MmsSmsColumns.Types.getOutgoingEncryptedMessageType() : MmsSmsColumns.Types.getOutgoingSmsMessageType(),
|
||||
threadId, 0, new LinkedList<IdentityKeyMismatch>(),
|
||||
message.getSubscriptionId(), message.getExpiresIn(),
|
||||
System.currentTimeMillis(), 0, false, message.isFriendRequest);
|
||||
System.currentTimeMillis(), 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -934,15 +934,12 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
List<IdentityKeyMismatch> mismatches = getMismatches(mismatchDocument);
|
||||
Recipient recipient = Recipient.from(context, address, true);
|
||||
|
||||
// Loki - Check to see if this message was a friend request
|
||||
boolean isFriendRequest = DatabaseFactory.getLokiMessageDatabase(context).isFriendRequest(messageId);
|
||||
|
||||
return new SmsMessageRecord(messageId, body, recipient,
|
||||
recipient,
|
||||
addressDeviceId,
|
||||
dateSent, dateReceived, deliveryReceiptCount, type,
|
||||
threadId, status, mismatches, subscriptionId,
|
||||
expiresIn, expireStarted, readReceiptCount, unidentified, isFriendRequest);
|
||||
expiresIn, expireStarted, readReceiptCount, unidentified);
|
||||
}
|
||||
|
||||
private List<IdentityKeyMismatch> getMismatches(String document) {
|
||||
|
@ -145,10 +145,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
db.execSQL(LokiAPIDatabase.getCreateSessionRequestTimestampCacheCommand());
|
||||
db.execSQL(LokiPreKeyBundleDatabase.getCreateTableCommand());
|
||||
db.execSQL(LokiPreKeyRecordDatabase.getCreateTableCommand());
|
||||
db.execSQL(LokiMessageDatabase.getCreateMessageFriendRequestTableCommand());
|
||||
db.execSQL(LokiMessageDatabase.getCreateMessageIDTableCommand());
|
||||
db.execSQL(LokiMessageDatabase.getCreateMessageToThreadMappingTableCommand());
|
||||
db.execSQL(LokiMessageDatabase.getCreateErrorMessageTableCommand());
|
||||
db.execSQL(LokiThreadDatabase.getCreateFriendRequestTableCommand());
|
||||
db.execSQL(LokiThreadDatabase.getCreateSessionResetTableCommand());
|
||||
db.execSQL(LokiThreadDatabase.getCreatePublicChatTableCommand());
|
||||
db.execSQL(LokiUserDatabase.getCreateDisplayNameTableCommand());
|
||||
|
@ -39,23 +39,6 @@ import network.loki.messenger.R;
|
||||
*/
|
||||
public class SmsMessageRecord extends MessageRecord {
|
||||
|
||||
// Loki
|
||||
private final boolean isFriendRequest;
|
||||
|
||||
public SmsMessageRecord(long id,
|
||||
String body, Recipient recipient,
|
||||
Recipient individualRecipient,
|
||||
int recipientDeviceId,
|
||||
long dateSent, long dateReceived,
|
||||
int deliveryReceiptCount,
|
||||
long type, long threadId,
|
||||
int status, List<IdentityKeyMismatch> mismatches,
|
||||
int subscriptionId, long expiresIn, long expireStarted,
|
||||
int readReceiptCount, boolean unidentified)
|
||||
{
|
||||
this(id, body, recipient, individualRecipient, recipientDeviceId, dateSent, dateReceived, deliveryReceiptCount, type, threadId, status, mismatches, subscriptionId, expiresIn, expireStarted, readReceiptCount, unidentified, false);
|
||||
}
|
||||
|
||||
public SmsMessageRecord(long id,
|
||||
String body, Recipient recipient,
|
||||
Recipient individualRecipient,
|
||||
@ -65,22 +48,18 @@ public class SmsMessageRecord extends MessageRecord {
|
||||
long type, long threadId,
|
||||
int status, List<IdentityKeyMismatch> mismatches,
|
||||
int subscriptionId, long expiresIn, long expireStarted,
|
||||
int readReceiptCount, boolean unidentified, boolean isFriendRequest)
|
||||
int readReceiptCount, boolean unidentified)
|
||||
{
|
||||
super(id, body, recipient, individualRecipient, recipientDeviceId,
|
||||
dateSent, dateReceived, threadId, status, deliveryReceiptCount, type,
|
||||
mismatches, new LinkedList<>(), subscriptionId,
|
||||
expiresIn, expireStarted, readReceiptCount, unidentified);
|
||||
this.isFriendRequest = isFriendRequest;
|
||||
}
|
||||
|
||||
public long getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
// Loki
|
||||
public boolean isFriendRequest() { return isFriendRequest; }
|
||||
|
||||
@Override
|
||||
public SpannableString getDisplayBody(@NonNull Context context) {
|
||||
Recipient recipient = getRecipient();
|
||||
|
@ -45,7 +45,7 @@ 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.protocol.LokiSessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceOpenGroupUpdateJob;
|
||||
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
|
||||
import org.thoughtcrime.securesms.push.MessageSenderEventListener;
|
||||
@ -156,7 +156,7 @@ public class SignalCommunicationModule {
|
||||
DatabaseFactory.getLokiThreadDatabase(context),
|
||||
DatabaseFactory.getLokiMessageDatabase(context),
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(context),
|
||||
new LokiSessionResetImplementation(context),
|
||||
new SessionResetImplementation(context),
|
||||
DatabaseFactory.getLokiUserDatabase(context),
|
||||
((ApplicationContext)context.getApplicationContext()).broadcaster);
|
||||
} else {
|
||||
|
@ -139,7 +139,6 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
|
||||
Optional<IdentityDatabase.IdentityRecord> identityRecord = DatabaseFactory.getIdentityDatabase(context).getIdentity(address);
|
||||
Optional<VerifiedMessage> verifiedMessage = getVerifiedMessage(recipient, identityRecord);
|
||||
|
||||
// Loki - Only sync contacts we are friends with
|
||||
if (SyncMessagesProtocol.shouldSyncContact(context, address)) {
|
||||
out.write(new DeviceContact(address.toPhoneString(),
|
||||
Optional.fromNullable(recipient.getName()),
|
||||
|
@ -66,15 +66,11 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.EphemeralMessage;
|
||||
import org.thoughtcrime.securesms.loki.protocol.FriendRequestProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.PushEphemeralMessageSendJob;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SyncMessagesProtocol;
|
||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
||||
import org.thoughtcrime.securesms.loki.utilities.PromiseUtilities;
|
||||
@ -130,7 +126,6 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI;
|
||||
import org.whispersystems.signalservice.loki.crypto.LokiServiceCipher;
|
||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus;
|
||||
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
@ -145,8 +140,6 @@ import javax.inject.Inject;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
import static org.thoughtcrime.securesms.loki.utilities.RecipientUtilitiesKt.recipient;
|
||||
|
||||
public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
|
||||
public static final String KEY = "PushDecryptJob";
|
||||
@ -225,9 +218,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
|
||||
}
|
||||
public void onCanceled() { }
|
||||
|
||||
public void processMessage(@NonNull SignalServiceEnvelope envelope, boolean isPushNotification) {
|
||||
synchronized (PushReceivedJob.RECEIVE_LOCK) {
|
||||
@ -264,18 +255,12 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
try {
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
SignalProtocolStore axolotlStore = new SignalProtocolStoreImpl(context);
|
||||
SessionResetProtocol sessionResetProtocol = new LokiSessionResetImplementation(context);
|
||||
SessionResetProtocol sessionResetProtocol = new SessionResetImplementation(context);
|
||||
SignalServiceAddress localAddress = new SignalServiceAddress(TextSecurePreferences.getLocalNumber(context));
|
||||
LokiServiceCipher cipher = new LokiServiceCipher(localAddress, axolotlStore, sessionResetProtocol, UnidentifiedAccessUtil.getCertificateValidator());
|
||||
|
||||
SignalServiceContent content = cipher.decrypt(envelope);
|
||||
|
||||
// Loki - Ignore any friend requests from before restoration
|
||||
if (FriendRequestProtocol.isFriendRequestFromBeforeRestoration(context, content)) {
|
||||
Log.d("Loki", "Ignoring friend request from before restoration.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldIgnore(content)) {
|
||||
Log.i(TAG, "Ignoring message.");
|
||||
return;
|
||||
@ -300,8 +285,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
if (message.isDeviceUnlinkingRequest()) {
|
||||
MultiDeviceProtocol.handleUnlinkingRequestIfNeeded(context, content);
|
||||
} else {
|
||||
// Loki - Handle friend request acceptance if needed
|
||||
FriendRequestProtocol.handleFriendRequestAcceptanceIfNeeded(context, content.getSender(), content);
|
||||
|
||||
if (message.isEndSession()) {
|
||||
handleEndSessionMessage(content, smsMessageId);
|
||||
@ -311,14 +294,8 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
handleExpirationUpdate(content, message, smsMessageId);
|
||||
} else if (isMediaMessage) {
|
||||
handleMediaMessage(content, message, smsMessageId, Optional.absent());
|
||||
|
||||
// Loki - Handle friend request message if needed
|
||||
FriendRequestProtocol.handleFriendRequestMessageIfNeeded(context, content.getSender(), content);
|
||||
} else if (message.getBody().isPresent()) {
|
||||
handleTextMessage(content, message, smsMessageId, Optional.absent());
|
||||
|
||||
// Loki - Handle friend request message if needed
|
||||
FriendRequestProtocol.handleFriendRequestMessageIfNeeded(context, content.getSender(), content);
|
||||
}
|
||||
|
||||
if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get()))) {
|
||||
@ -364,7 +341,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
} else if (content.getTypingMessage().isPresent()) {
|
||||
handleTypingMessage(content, content.getTypingMessage().get());
|
||||
} else if (content.getNullMessage().isPresent()) {
|
||||
|
||||
// Loki - This is needed for compatibility with refactored desktop clients
|
||||
// ========
|
||||
// if (content.isFriendRequest()) {
|
||||
@ -372,18 +348,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
// } else {
|
||||
// Log.w(TAG, "Got unrecognized message...");
|
||||
// }
|
||||
Recipient recipient = recipient(context, content.getSender());
|
||||
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context);
|
||||
LokiThreadFriendRequestStatus threadFriendRequestStatus = threadDB.getFriendRequestStatus(threadID);
|
||||
if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.NONE || threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_EXPIRED) {
|
||||
threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED);
|
||||
} else if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) {
|
||||
threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
|
||||
EphemeralMessage ephemeralMessage = EphemeralMessage.create(content.getSender());
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new PushEphemeralMessageSendJob(ephemeralMessage));
|
||||
SyncMessagesProtocol.syncContact(context, Address.fromSerialized(content.getSender()));
|
||||
}
|
||||
// ========
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.WorkerThread;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
@ -31,7 +30,6 @@ import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.state.PreKeyBundle;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||
@ -64,46 +62,34 @@ 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_LOKI_PRE_KEY_BUNDLE_MESSAGE = "is_friend_request";
|
||||
private static final String KEY_CUSTOM_FR_MESSAGE = "custom_friend_request_message";
|
||||
|
||||
@Inject SignalServiceMessageSender messageSender;
|
||||
|
||||
private long messageId; // The message ID
|
||||
private long templateMessageId; // The message ID of the message to template this send job from
|
||||
|
||||
// Loki - Multi device
|
||||
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 long messageId;
|
||||
private long templateMessageId;
|
||||
private Address destination;
|
||||
|
||||
public PushMediaSendJob(long messageId, Address destination) {
|
||||
this(messageId, messageId, destination);
|
||||
}
|
||||
|
||||
public PushMediaSendJob(long templateMessageId, long messageId, Address destination) {
|
||||
this(templateMessageId, messageId, destination, false, null);
|
||||
this(constructParameters(destination), templateMessageId, messageId, destination);
|
||||
}
|
||||
|
||||
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) {
|
||||
private PushMediaSendJob(@NonNull Job.Parameters parameters, long templateMessageId, long messageId, Address destination) {
|
||||
super(parameters);
|
||||
this.templateMessageId = templateMessageId;
|
||||
this.messageId = messageId;
|
||||
this.destination = destination;
|
||||
this.isLokiPreKeyBundleMessage = isLokiPreKeyBundleMessage;
|
||||
this.customFriendRequestMessage = customFriendRequestMessage;
|
||||
}
|
||||
|
||||
public static void enqueue(@NonNull Context context, @NonNull JobManager jobManager, long messageId, @NonNull Address destination) {
|
||||
enqueue(context, jobManager, messageId, messageId, destination, false, null);
|
||||
enqueue(context, jobManager, messageId, messageId, destination);
|
||||
}
|
||||
|
||||
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)));
|
||||
public static void enqueue(@NonNull Context context, @NonNull JobManager jobManager, long templateMessageId, long messageId, @NonNull Address destination) {
|
||||
enqueue(context, jobManager, Collections.singletonList(new PushMediaSendJob(templateMessageId, messageId, destination)));
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@ -144,14 +130,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_LOKI_PRE_KEY_BUNDLE_MESSAGE, isLokiPreKeyBundleMessage);
|
||||
|
||||
if (customFriendRequestMessage != null) { builder.putString(KEY_CUSTOM_FR_MESSAGE, customFriendRequestMessage); }
|
||||
return builder.build();
|
||||
return new Data.Builder()
|
||||
.putLong(KEY_TEMPLATE_MESSAGE_ID, templateMessageId)
|
||||
.putLong(KEY_MESSAGE_ID, messageId)
|
||||
.putString(KEY_DESTINATION, destination.serialize()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -270,17 +252,8 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
List<SharedContact> sharedContacts = getSharedContactsFor(message);
|
||||
List<Preview> previews = getPreviewsFor(message);
|
||||
|
||||
// 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)
|
||||
.withBody(message.getBody())
|
||||
.withAttachments(serviceAttachments)
|
||||
.withTimestamp(message.getSentTimeMillis())
|
||||
.withExpiration((int)(message.getExpiresIn() / 1000))
|
||||
@ -290,7 +263,6 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
.withSharedContacts(sharedContacts)
|
||||
.withPreviews(previews)
|
||||
.asExpirationUpdate(message.isExpirationUpdate())
|
||||
.withPreKeyBundle(preKeyBundle)
|
||||
.build();
|
||||
|
||||
if (SessionMetaProtocol.shared.isNoteToSelf(address.getNumber())) {
|
||||
@ -326,9 +298,7 @@ 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 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);
|
||||
return new PushMediaSendJob(parameters, templateMessageID, messageID, destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.state.PreKeyBundle;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||
@ -47,50 +46,34 @@ 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_LOKI_PRE_KEY_BUNDLE_MESSAGE = "is_friend_request";
|
||||
private static final String KEY_CUSTOM_FR_MESSAGE = "custom_friend_request_message";
|
||||
|
||||
@Inject SignalServiceMessageSender messageSender;
|
||||
|
||||
private long messageId; // The message ID
|
||||
private long templateMessageId; // The message ID of the message to template this send job from
|
||||
|
||||
// Loki - Multi device
|
||||
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 long messageId;
|
||||
private long templateMessageId;
|
||||
private Address destination;
|
||||
|
||||
public PushTextSendJob(long messageId, Address destination) {
|
||||
this(messageId, messageId, destination);
|
||||
}
|
||||
|
||||
public PushTextSendJob(long templateMessageId, long messageId, Address destination) {
|
||||
this(templateMessageId, messageId, destination, false, null);
|
||||
this(constructParameters(destination), templateMessageId, messageId, destination);
|
||||
}
|
||||
|
||||
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) {
|
||||
private PushTextSendJob(@NonNull Job.Parameters parameters, long templateMessageId, long messageId, Address destination) {
|
||||
super(parameters);
|
||||
this.templateMessageId = templateMessageId;
|
||||
this.messageId = messageId;
|
||||
this.destination = destination;
|
||||
this.isLokiPreKeyBundleMessage = isLokiPreKeyBundleMessage;
|
||||
this.customFriendRequestMessage = customFriendRequestMessage;
|
||||
}
|
||||
|
||||
@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_LOKI_PRE_KEY_BUNDLE_MESSAGE, isLokiPreKeyBundleMessage);
|
||||
|
||||
if (customFriendRequestMessage != null) { builder.putString(KEY_CUSTOM_FR_MESSAGE, customFriendRequestMessage); }
|
||||
return builder.build();
|
||||
return new Data.Builder()
|
||||
.putLong(KEY_TEMPLATE_MESSAGE_ID, templateMessageId)
|
||||
.putLong(KEY_MESSAGE_ID, messageId)
|
||||
.putString(KEY_DESTINATION, destination.serialize()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -213,22 +196,12 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
log(TAG, "Have access key to use: " + unidentifiedAccess.isPresent());
|
||||
|
||||
// Loki - Include a pre key bundle if needed
|
||||
PreKeyBundle preKeyBundle;
|
||||
if (isLokiPreKeyBundleMessage || message.isEndSession()) {
|
||||
preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.getNumber());
|
||||
} else {
|
||||
preKeyBundle = null;
|
||||
}
|
||||
|
||||
String body = (isLokiPreKeyBundleMessage && customFriendRequestMessage != null) ? customFriendRequestMessage : message.getBody();
|
||||
SignalServiceDataMessage textSecureMessage = SignalServiceDataMessage.newBuilder()
|
||||
.withTimestamp(message.getDateSent())
|
||||
.withBody(body)
|
||||
.withBody(message.getBody())
|
||||
.withExpiration((int)(message.getExpiresIn() / 1000))
|
||||
.withProfileKey(profileKey.orNull())
|
||||
.asEndSessionMessage(message.isEndSession())
|
||||
.withPreKeyBundle(preKeyBundle)
|
||||
.build();
|
||||
|
||||
if (SessionMetaProtocol.shared.isNoteToSelf(address.getNumber())) {
|
||||
@ -261,9 +234,7 @@ 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 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);
|
||||
return new PushTextSendJob(parameters, templateMessageID, messageID, destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,8 @@ class CreateClosedGroupLoader(context: Context) : AsyncLoader<List<String>>(cont
|
||||
|
||||
override fun loadInBackground(): List<String> {
|
||||
val contacts = ContactUtilities.getAllContacts(context)
|
||||
// Only show the master devices of the users we are friends with
|
||||
return contacts.filter { contact ->
|
||||
!contact.recipient.isGroupRecipient && contact.isFriend && !contact.isOurDevice && !contact.isSlave
|
||||
!contact.recipient.isGroupRecipient && !contact.isOurDevice && !contact.isSlave
|
||||
}.map {
|
||||
it.recipient.address.toPhoneString()
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import org.thoughtcrime.securesms.loki.dialogs.PNModeBottomSheet
|
||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol
|
||||
import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
|
||||
import org.thoughtcrime.securesms.loki.utilities.*
|
||||
import org.thoughtcrime.securesms.loki.views.ConversationView
|
||||
import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetViewDelegate
|
||||
@ -47,18 +47,16 @@ import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.syncmessages.SyncMessagesProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiMessageFriendRequestStatus
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
import kotlin.math.abs
|
||||
|
||||
class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListener, SeedReminderViewDelegate, NewConversationButtonSetViewDelegate {
|
||||
private lateinit var glide: GlideRequests
|
||||
|
||||
private val hexEncodedPublicKey: String
|
||||
private val publicKey: String
|
||||
get() {
|
||||
val masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(this)
|
||||
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
return masterHexEncodedPublicKey ?: userHexEncodedPublicKey
|
||||
val masterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(this)
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
return masterPublicKey ?: userPublicKey
|
||||
}
|
||||
|
||||
// region Lifecycle
|
||||
@ -94,7 +92,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
glide = GlideApp.with(this)
|
||||
// Set up toolbar buttons
|
||||
profileButton.glide = glide
|
||||
profileButton.hexEncodedPublicKey = hexEncodedPublicKey
|
||||
profileButton.publicKey = publicKey
|
||||
profileButton.update()
|
||||
profileButton.setOnClickListener { openSettings() }
|
||||
pathStatusViewContainer.setOnClickListener { showPath() }
|
||||
@ -156,45 +154,23 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
val threadDB = DatabaseFactory.getLokiThreadDatabase(this)
|
||||
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
val sessionResetImpl = LokiSessionResetImplementation(this)
|
||||
val sessionResetImpl = SessionResetImplementation(this)
|
||||
if (userPublicKey != null) {
|
||||
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
||||
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
SyncMessagesProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
application.lokiPublicChatManager.startPollersIfNeeded()
|
||||
application.publicChatManager.startPollersIfNeeded()
|
||||
}
|
||||
SessionManagementProtocol.configureIfNeeded(sessionResetImpl, threadDB, application)
|
||||
MultiDeviceProtocol.configureIfNeeded(apiDB)
|
||||
IP2Country.configureIfNeeded(this)
|
||||
// Preload device links to make message sending quicker
|
||||
val publicKeys = ContactUtilities.getAllContacts(this).filter { contact ->
|
||||
!contact.recipient.isGroupRecipient && contact.isFriend && !contact.isOurDevice && !contact.isSlave
|
||||
!contact.recipient.isGroupRecipient && !contact.isOurDevice && !contact.isSlave
|
||||
}.map {
|
||||
it.recipient.address.toPhoneString()
|
||||
}.toSet()
|
||||
FileServerAPI.shared.getDeviceLinks(publicKeys)
|
||||
// TODO: Temporary hack to unbork existing clients
|
||||
val allContacts = DatabaseFactory.getRecipientDatabase(this).allAddresses.map {
|
||||
MultiDeviceProtocol.shared.getMasterDevice(it.serialize()) ?: it.serialize()
|
||||
}.toSet()
|
||||
val lokiMessageDB = DatabaseFactory.getLokiMessageDatabase(this)
|
||||
for (contact in allContacts) {
|
||||
val slaveDeviceHasPendingFR = MultiDeviceProtocol.shared.getSlaveDevices(contact).any {
|
||||
val slaveDeviceThreadID = DatabaseFactory.getThreadDatabase(this).getThreadIdFor(recipient(this, it))
|
||||
DatabaseFactory.getLokiThreadDatabase(this).getFriendRequestStatus(slaveDeviceThreadID) == LokiThreadFriendRequestStatus.REQUEST_RECEIVED
|
||||
}
|
||||
val masterDeviceThreadID = DatabaseFactory.getThreadDatabase(this).getThreadIdFor(recipient(this, contact))
|
||||
val masterDeviceHasNoPendingFR = (DatabaseFactory.getLokiThreadDatabase(this).getFriendRequestStatus(masterDeviceThreadID) == LokiThreadFriendRequestStatus.NONE)
|
||||
if (slaveDeviceHasPendingFR && masterDeviceHasNoPendingFR) {
|
||||
val lastMessageID = org.thoughtcrime.securesms.loki.protocol.FriendRequestProtocol.getLastMessageID(this, masterDeviceThreadID)
|
||||
if (lastMessageID != null) {
|
||||
val lastMessageFRStatus = lokiMessageDB.getFriendRequestStatus(lastMessageID)
|
||||
if (lastMessageFRStatus != LokiMessageFriendRequestStatus.REQUEST_PENDING) {
|
||||
lokiMessageDB.setFriendRequestStatus(lastMessageID, LokiMessageFriendRequestStatus.REQUEST_PENDING)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.database.IdentityDatabase
|
||||
import org.thoughtcrime.securesms.logging.Log
|
||||
import org.thoughtcrime.securesms.loki.dialogs.LinkDeviceSlaveModeDialog
|
||||
import org.thoughtcrime.securesms.loki.dialogs.LinkDeviceSlaveModeDialogDelegate
|
||||
import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
|
||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
|
||||
import org.thoughtcrime.securesms.loki.utilities.push
|
||||
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
|
||||
@ -109,7 +109,7 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
||||
val threadDB = DatabaseFactory.getLokiThreadDatabase(this)
|
||||
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
val sessionResetImpl = LokiSessionResetImplementation(this)
|
||||
val sessionResetImpl = SessionResetImplementation(this)
|
||||
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
||||
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol.configureIfNeeded(apiDB)
|
||||
|
@ -73,7 +73,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
showQRCodeButton.setOnClickListener { showQRCode() }
|
||||
glide = GlideApp.with(this)
|
||||
profilePictureView.glide = glide
|
||||
profilePictureView.hexEncodedPublicKey = hexEncodedPublicKey
|
||||
profilePictureView.publicKey = hexEncodedPublicKey
|
||||
profilePictureView.isLarge = true
|
||||
profilePictureView.update()
|
||||
profilePictureView.setOnClickListener { showEditProfilePictureUI() }
|
||||
|
@ -47,7 +47,7 @@ class BackgroundPollWorker : PersistentAlarmManagerListener() {
|
||||
}
|
||||
val openGroups = DatabaseFactory.getLokiThreadDatabase(context).getAllPublicChats().map { it.value }
|
||||
for (openGroup in openGroups) {
|
||||
val poller = LokiPublicChatPoller(context, openGroup)
|
||||
val poller = PublicChatPoller(context, openGroup)
|
||||
poller.stop()
|
||||
poller.pollForNewMessages()
|
||||
}
|
||||
|
@ -14,9 +14,9 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||
|
||||
class LokiPublicChatManager(private val context: Context) {
|
||||
class PublicChatManager(private val context: Context) {
|
||||
private var chats = mutableMapOf<Long, PublicChat>()
|
||||
private val pollers = mutableMapOf<Long, LokiPublicChatPoller>()
|
||||
private val pollers = mutableMapOf<Long, PublicChatPoller>()
|
||||
private val observers = mutableMapOf<Long, ContentObserver>()
|
||||
private var isPolling = false
|
||||
|
||||
@ -24,7 +24,7 @@ class LokiPublicChatManager(private val context: Context) {
|
||||
var areAllCaughtUp = true
|
||||
refreshChatsAndPollers()
|
||||
for ((threadID, chat) in chats) {
|
||||
val poller = pollers[threadID] ?: LokiPublicChatPoller(context, chat)
|
||||
val poller = pollers[threadID] ?: PublicChatPoller(context, chat)
|
||||
areAllCaughtUp = areAllCaughtUp && poller.isCaughtUp
|
||||
}
|
||||
return areAllCaughtUp
|
||||
@ -33,7 +33,7 @@ class LokiPublicChatManager(private val context: Context) {
|
||||
public fun markAllAsNotCaughtUp() {
|
||||
refreshChatsAndPollers()
|
||||
for ((threadID, chat) in chats) {
|
||||
val poller = pollers[threadID] ?: LokiPublicChatPoller(context, chat)
|
||||
val poller = pollers[threadID] ?: PublicChatPoller(context, chat)
|
||||
poller.isCaughtUp = false
|
||||
}
|
||||
}
|
||||
@ -42,7 +42,7 @@ class LokiPublicChatManager(private val context: Context) {
|
||||
refreshChatsAndPollers()
|
||||
|
||||
for ((threadId, chat) in chats) {
|
||||
val poller = pollers[threadId] ?: LokiPublicChatPoller(context, chat)
|
||||
val poller = pollers[threadId] ?: PublicChatPoller(context, chat)
|
||||
poller.startIfNeeded()
|
||||
listenToThreadDeletion(threadId)
|
||||
if (!pollers.containsKey(threadId)) { pollers[threadId] = poller }
|
@ -27,11 +27,10 @@ import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatAPI
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatMessage
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
import java.security.MessageDigest
|
||||
import java.util.*
|
||||
|
||||
class LokiPublicChatPoller(private val context: Context, private val group: PublicChat) {
|
||||
class PublicChatPoller(private val context: Context, private val group: PublicChat) {
|
||||
private val handler = Handler()
|
||||
private var hasStarted = false
|
||||
public var isCaughtUp = false
|
||||
@ -182,13 +181,6 @@ class LokiPublicChatPoller(private val context: Context, private val group: Publ
|
||||
database.setProfileKey(senderAsRecipient, profileKey)
|
||||
ApplicationContext.getInstance(context).jobManager.add(RetrieveProfileAvatarJob(senderAsRecipient, url))
|
||||
}
|
||||
} else if (senderAsRecipient.profileAvatar.orEmpty().isNotEmpty()) {
|
||||
// Clear the profile picture if we had a profile picture before and we're not friends with the person
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(senderAsRecipient)
|
||||
val friendRequestStatus = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID)
|
||||
if (friendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS) {
|
||||
ApplicationContext.getInstance(context).jobManager.add(RetrieveProfileAvatarJob(senderAsRecipient, ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun processOutgoingMessage(message: PublicChatMessage) {
|
@ -11,12 +11,11 @@ import org.thoughtcrime.securesms.loki.utilities.getInt
|
||||
import org.thoughtcrime.securesms.loki.utilities.getString
|
||||
import org.thoughtcrime.securesms.loki.utilities.insertOrUpdate
|
||||
import org.whispersystems.signalservice.loki.database.LokiMessageDatabaseProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiMessageFriendRequestStatus
|
||||
|
||||
class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiMessageDatabaseProtocol {
|
||||
|
||||
companion object {
|
||||
private val messageFriendRequestTable = "loki_message_friend_request_database"
|
||||
private val messageIDTable = "loki_message_friend_request_database"
|
||||
private val messageThreadMappingTable = "loki_message_thread_mapping_database"
|
||||
private val errorMessageTable = "loki_error_message_database"
|
||||
private val messageID = "message_id"
|
||||
@ -24,7 +23,7 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
private val friendRequestStatus = "friend_request_status"
|
||||
private val threadID = "thread_id"
|
||||
private val errorMessage = "error_message"
|
||||
@JvmStatic val createMessageFriendRequestTableCommand = "CREATE TABLE $messageFriendRequestTable ($messageID INTEGER PRIMARY KEY, $serverID INTEGER DEFAULT 0, $friendRequestStatus INTEGER DEFAULT 0);"
|
||||
@JvmStatic val createMessageIDTableCommand = "CREATE TABLE $messageIDTable ($messageID INTEGER PRIMARY KEY, $serverID INTEGER DEFAULT 0, $friendRequestStatus INTEGER DEFAULT 0);"
|
||||
@JvmStatic val createMessageToThreadMappingTableCommand = "CREATE TABLE IF NOT EXISTS $messageThreadMappingTable ($messageID INTEGER PRIMARY KEY, $threadID INTEGER);"
|
||||
@JvmStatic val createErrorMessageTableCommand = "CREATE TABLE IF NOT EXISTS $errorMessageTable ($messageID INTEGER PRIMARY KEY, $errorMessage STRING);"
|
||||
}
|
||||
@ -36,14 +35,14 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
|
||||
fun getServerID(messageID: Long): Long? {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(messageFriendRequestTable, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||
return database.get(messageIDTable, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||
cursor.getInt(serverID)
|
||||
}?.toLong()
|
||||
}
|
||||
|
||||
fun getMessageID(serverID: Long): Long? {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(messageFriendRequestTable, "${Companion.serverID} = ?", arrayOf( serverID.toString() )) { cursor ->
|
||||
return database.get(messageIDTable, "${Companion.serverID} = ?", arrayOf( serverID.toString() )) { cursor ->
|
||||
cursor.getInt(messageID)
|
||||
}?.toLong()
|
||||
}
|
||||
@ -53,7 +52,7 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.messageID, messageID)
|
||||
contentValues.put(Companion.serverID, serverID)
|
||||
database.insertOrUpdate(messageFriendRequestTable, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||
database.insertOrUpdate(messageIDTable, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||
}
|
||||
|
||||
fun getOriginalThreadID(messageID: Long): Long {
|
||||
@ -71,32 +70,6 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
database.insertOrUpdate(messageThreadMappingTable, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||
}
|
||||
|
||||
fun getFriendRequestStatus(messageID: Long): LokiMessageFriendRequestStatus {
|
||||
val database = databaseHelper.readableDatabase
|
||||
val result = database.get(messageFriendRequestTable, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||
cursor.getInt(friendRequestStatus)
|
||||
}
|
||||
return if (result != null) {
|
||||
LokiMessageFriendRequestStatus.values().first { it.rawValue == result }
|
||||
} else {
|
||||
LokiMessageFriendRequestStatus.NONE
|
||||
}
|
||||
}
|
||||
|
||||
fun setFriendRequestStatus(messageID: Long, friendRequestStatus: LokiMessageFriendRequestStatus) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.messageID, messageID)
|
||||
contentValues.put(Companion.friendRequestStatus, friendRequestStatus.rawValue)
|
||||
database.insertOrUpdate(messageFriendRequestTable, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||
val threadID = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageID)
|
||||
notifyConversationListeners(threadID)
|
||||
}
|
||||
|
||||
fun isFriendRequest(messageID: Long): Boolean {
|
||||
return getFriendRequestStatus(messageID) != LokiMessageFriendRequestStatus.NONE
|
||||
}
|
||||
|
||||
fun getErrorMessage(messageID: Long): String? {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.get(errorMessageTable, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||
|
@ -15,21 +15,18 @@ import org.whispersystems.libsignal.loki.SessionResetStatus
|
||||
import org.whispersystems.signalservice.internal.util.JsonUtil
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||
import org.whispersystems.signalservice.loki.database.LokiThreadDatabaseProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
|
||||
|
||||
class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiThreadDatabaseProtocol {
|
||||
var delegate: LokiThreadDatabaseDelegate? = null
|
||||
|
||||
companion object {
|
||||
private val friendRequestTable = "loki_thread_friend_request_database"
|
||||
private val sessionResetTable = "loki_thread_session_reset_database"
|
||||
val publicChatTable = "loki_public_chat_database"
|
||||
val threadID = "thread_id"
|
||||
private val friendRequestStatus = "friend_request_status"
|
||||
private val sessionResetStatus = "session_reset_status"
|
||||
val publicChat = "public_chat"
|
||||
@JvmStatic val createFriendRequestTableCommand = "CREATE TABLE $friendRequestTable ($threadID INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);"
|
||||
@JvmStatic val createSessionResetTableCommand = "CREATE TABLE $sessionResetTable ($threadID INTEGER PRIMARY KEY, $sessionResetStatus INTEGER DEFAULT 0);"
|
||||
@JvmStatic val createPublicChatTableCommand = "CREATE TABLE $publicChatTable ($threadID INTEGER PRIMARY KEY, $publicChat TEXT);"
|
||||
}
|
||||
@ -44,34 +41,6 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
||||
return DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageID)
|
||||
}
|
||||
|
||||
fun getFriendRequestStatus(threadID: Long): LokiThreadFriendRequestStatus {
|
||||
if (threadID < 0) { return LokiThreadFriendRequestStatus.NONE }
|
||||
val recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID)
|
||||
if (recipient != null && recipient.isGroupRecipient) { return LokiThreadFriendRequestStatus.FRIENDS; }
|
||||
val database = databaseHelper.readableDatabase
|
||||
val result = database.get(friendRequestTable, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
|
||||
cursor.getInt(friendRequestStatus)
|
||||
}
|
||||
return if (result != null) {
|
||||
LokiThreadFriendRequestStatus.values().first { it.rawValue == result }
|
||||
} else {
|
||||
LokiThreadFriendRequestStatus.NONE
|
||||
}
|
||||
}
|
||||
|
||||
fun setFriendRequestStatus(threadID: Long, friendRequestStatus: LokiThreadFriendRequestStatus) {
|
||||
if (threadID < 0) { return }
|
||||
Log.d("Loki", "Setting FR status for thread with ID $threadID to $friendRequestStatus.")
|
||||
val database = databaseHelper.writableDatabase
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.threadID, threadID)
|
||||
contentValues.put(Companion.friendRequestStatus, friendRequestStatus.rawValue)
|
||||
database.insertOrUpdate(friendRequestTable, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
||||
notifyConversationListListeners()
|
||||
notifyConversationListeners(threadID)
|
||||
delegate?.handleThreadFriendRequestStatusChanged(threadID)
|
||||
}
|
||||
|
||||
fun getSessionResetStatus(hexEncodedPublicKey: String): SessionResetStatus {
|
||||
val threadID = getThreadID(hexEncodedPublicKey)
|
||||
val database = databaseHelper.readableDatabase
|
||||
|
@ -2,6 +2,5 @@ package org.thoughtcrime.securesms.loki.database
|
||||
|
||||
interface LokiThreadDatabaseDelegate {
|
||||
|
||||
fun handleThreadFriendRequestStatusChanged(threadID: Long)
|
||||
fun handleSessionRestoreDevicesChanged(threadID: Long)
|
||||
}
|
@ -15,10 +15,10 @@ sealed class ContactSelectionListItem {
|
||||
class ContactSelectionListLoader(context: Context, val mode: Int, val filter: String?) : AsyncLoader<List<ContactSelectionListItem>>(context) {
|
||||
|
||||
object DisplayMode {
|
||||
const val FLAG_FRIENDS = 1
|
||||
const val FLAG_CONTACTS = 1
|
||||
const val FLAG_CLOSED_GROUPS = 1 shl 1
|
||||
const val FLAG_OPEN_GROUPS = 1 shl 2
|
||||
const val FLAG_ALL = FLAG_FRIENDS or FLAG_CLOSED_GROUPS or FLAG_OPEN_GROUPS
|
||||
const val FLAG_ALL = FLAG_CONTACTS or FLAG_CLOSED_GROUPS or FLAG_OPEN_GROUPS
|
||||
}
|
||||
|
||||
private fun isFlagSet(flag: Int): Boolean {
|
||||
@ -39,15 +39,15 @@ class ContactSelectionListLoader(context: Context, val mode: Int, val filter: St
|
||||
if (isFlagSet(DisplayMode.FLAG_OPEN_GROUPS)) {
|
||||
list.addAll(getOpenGroups(contacts))
|
||||
}
|
||||
if (isFlagSet(DisplayMode.FLAG_FRIENDS)) {
|
||||
list.addAll(getFriends(contacts))
|
||||
if (isFlagSet(DisplayMode.FLAG_CONTACTS)) {
|
||||
list.addAll(getContacts(contacts))
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
private fun getFriends(contacts: List<Contact>): List<ContactSelectionListItem> {
|
||||
private fun getContacts(contacts: List<Contact>): List<ContactSelectionListItem> {
|
||||
return getItems(contacts, context.getString(R.string.fragment_contact_selection_contacts_title)) {
|
||||
!it.recipient.isGroupRecipient && it.isFriend && !it.isOurDevice && !it.isSlave
|
||||
!it.recipient.isGroupRecipient && !it.isOurDevice && !it.isSlave
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,10 +10,7 @@ class EphemeralMessage private constructor(val data: Map<*, *>) {
|
||||
fun create(publicKey: String) = EphemeralMessage(mapOf( "recipient" to publicKey ))
|
||||
|
||||
@JvmStatic
|
||||
fun createUnlinkingRequest(publicKey: String) = EphemeralMessage(mapOf( "recipient" to publicKey, "unpairingRequest" to true ))
|
||||
|
||||
@JvmStatic
|
||||
fun createSessionRestorationRequest(publicKey: String) = EphemeralMessage(mapOf( "recipient" to publicKey, "friendRequest" to true, "sessionRestore" to true ))
|
||||
fun createDeviceUnlinkingRequest(publicKey: String) = EphemeralMessage(mapOf( "recipient" to publicKey, "unpairingRequest" to true ))
|
||||
|
||||
@JvmStatic
|
||||
fun createSessionRequest(publicKey: String) = EphemeralMessage(mapOf( "recipient" to publicKey, "friendRequest" to true, "sessionRequest" to true ))
|
||||
|
@ -1,316 +0,0 @@
|
||||
package org.thoughtcrime.securesms.loki.protocol
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.database.Address
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.loki.utilities.recipient
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.sms.MessageSender
|
||||
import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent
|
||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiMessageFriendRequestStatus
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
|
||||
object FriendRequestProtocol {
|
||||
|
||||
@JvmStatic
|
||||
fun acceptFriendRequest(context: Context, recipient: Recipient) {
|
||||
if (recipient.isGroupRecipient) { return; }
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
val allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey)
|
||||
// Accept all outstanding friend requests associated with this user and try to establish sessions with the
|
||||
// subset of their devices that haven't sent a friend request.
|
||||
val allContactDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(recipient.address.serialize())
|
||||
val threadDB = DatabaseFactory.getThreadDatabase(context)
|
||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
for (device in allContactDevices) {
|
||||
val deviceAsRecipient = recipient(context, device)
|
||||
val deviceThreadID = threadDB.getThreadIdFor(deviceAsRecipient)
|
||||
val deviceFRStatus = lokiThreadDB.getFriendRequestStatus(deviceThreadID)
|
||||
if (deviceFRStatus == LokiThreadFriendRequestStatus.REQUEST_RECEIVED) {
|
||||
lokiThreadDB.setFriendRequestStatus(deviceThreadID, LokiThreadFriendRequestStatus.FRIENDS)
|
||||
val lastMessageID = getLastMessageID(context, deviceThreadID)
|
||||
if (lastMessageID != null) {
|
||||
DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(lastMessageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED)
|
||||
}
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient(context, device), true)
|
||||
val ephemeralMessage = EphemeralMessage.create(device)
|
||||
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(ephemeralMessage))
|
||||
// Sync contact if needed
|
||||
if (allUserDevices.contains(device)) { return }
|
||||
val deviceToSync = MultiDeviceProtocol.shared.getMasterDevice(device) ?: device
|
||||
SyncMessagesProtocol.syncContact(context, Address.fromSerialized(deviceToSync))
|
||||
} else if (deviceFRStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) {
|
||||
// Do nothing
|
||||
} else if (!allUserDevices.contains(device)
|
||||
&& (deviceFRStatus == LokiThreadFriendRequestStatus.NONE || deviceFRStatus == LokiThreadFriendRequestStatus.REQUEST_EXPIRED)) {
|
||||
sendAutoGeneratedFriendRequest(context, device)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun rejectFriendRequest(context: Context, recipient: Recipient) {
|
||||
if (recipient.isGroupRecipient) { return; }
|
||||
val linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(recipient.address.serialize())
|
||||
val threadDB = DatabaseFactory.getThreadDatabase(context)
|
||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
for (device in linkedDevices) {
|
||||
val deviceAsRecipient = recipient(context, device)
|
||||
val deviceThreadID = threadDB.getThreadIdFor(deviceAsRecipient)
|
||||
val deviceFRStatus = lokiThreadDB.getFriendRequestStatus(deviceThreadID)
|
||||
// We only want to decline incoming requests
|
||||
if (deviceFRStatus == LokiThreadFriendRequestStatus.REQUEST_RECEIVED) {
|
||||
// Delete the pre key bundle for the given contact. This ensures that if we send a
|
||||
// new message after this, it restarts the friend request process from scratch.
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(context).removePreKeyBundle(device)
|
||||
lokiThreadDB.setFriendRequestStatus(deviceThreadID, LokiThreadFriendRequestStatus.NONE)
|
||||
val lastMessageID = getLastMessageID(context, deviceThreadID)
|
||||
if (lastMessageID != null) {
|
||||
DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(lastMessageID, LokiMessageFriendRequestStatus.REQUEST_REJECTED)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun shouldInputPanelBeEnabled(context: Context, recipient: Recipient): Boolean {
|
||||
// Friend requests have nothing to do with groups, so if this is a group thread the input panel should be enabled
|
||||
if (recipient.isGroupRecipient) { return true }
|
||||
// If this is a note to self the input panel should be enabled
|
||||
if (SessionMetaProtocol.shared.isNoteToSelf(recipient.address.serialize())) { return true }
|
||||
// Gather friend request statuses
|
||||
val linkedDeviceFRStatuses = mutableSetOf<LokiThreadFriendRequestStatus>()
|
||||
val linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(recipient.address.serialize())
|
||||
val threadDB = DatabaseFactory.getThreadDatabase(context)
|
||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
for (device in linkedDevices) {
|
||||
val deviceAsRecipient = recipient(context, device)
|
||||
val deviceThreadID = threadDB.getThreadIdFor(deviceAsRecipient)
|
||||
val deviceFRStatus = lokiThreadDB.getFriendRequestStatus(deviceThreadID)
|
||||
linkedDeviceFRStatuses.add(deviceFRStatus)
|
||||
}
|
||||
// If the user is friends with any of the other user's devices the input panel should be enabled
|
||||
if (linkedDeviceFRStatuses.contains(LokiThreadFriendRequestStatus.FRIENDS)) { return true }
|
||||
// If no friend request has been sent the input panel should be enabled
|
||||
if (linkedDeviceFRStatuses.all { it == LokiThreadFriendRequestStatus.NONE || it == LokiThreadFriendRequestStatus.REQUEST_EXPIRED }) { return true }
|
||||
// There must be a pending friend request
|
||||
return false
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun shouldAttachmentButtonBeEnabled(context: Context, recipient: Recipient): Boolean {
|
||||
// Friend requests have nothing to do with groups, so if this is a group thread the attachment button should be enabled
|
||||
if (recipient.isGroupRecipient) { return true }
|
||||
// If this is a note to self the attachment button should be enabled
|
||||
if (SessionMetaProtocol.shared.isNoteToSelf(recipient.address.serialize())) { return true }
|
||||
// Gather friend request statuses
|
||||
val linkedDeviceFRStatuses = mutableSetOf<LokiThreadFriendRequestStatus>()
|
||||
val linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(recipient.address.serialize())
|
||||
val threadDB = DatabaseFactory.getThreadDatabase(context)
|
||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
for (device in linkedDevices) {
|
||||
val deviceAsRecipient = recipient(context, device)
|
||||
val deviceThreadID = threadDB.getThreadIdFor(deviceAsRecipient)
|
||||
val deviceFRStatus = lokiThreadDB.getFriendRequestStatus(deviceThreadID)
|
||||
linkedDeviceFRStatuses.add(deviceFRStatus)
|
||||
}
|
||||
// If the user is friends with any of the other user's devices the attachment button should be enabled
|
||||
if (linkedDeviceFRStatuses.contains(LokiThreadFriendRequestStatus.FRIENDS)) { return true }
|
||||
// Otherwise don't allow attachments
|
||||
return false
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getLastMessageID(context: Context, threadID: Long): Long? {
|
||||
val db = DatabaseFactory.getSmsDatabase(context)
|
||||
val messageCount = db.getMessageCountForThread(threadID)
|
||||
if (messageCount == 0) { return null }
|
||||
return db.getIDForMessageAtIndex(threadID, messageCount - 1)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun handleFriendRequestAcceptanceIfNeeded(context: Context, publicKey: String, content: SignalServiceContent) {
|
||||
// If we get an envelope that isn't a friend request, then we can infer that we had to use
|
||||
// Signal cipher decryption and thus that we have a session with the other person.
|
||||
val recipient = recipient(context, publicKey)
|
||||
// Friend requests don't apply to groups
|
||||
if (recipient.isGroupRecipient) { return }
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
|
||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
val threadFRStatus = lokiThreadDB.getFriendRequestStatus(threadID)
|
||||
// Guard against invalid state transitions
|
||||
if (threadFRStatus != LokiThreadFriendRequestStatus.REQUEST_SENDING && threadFRStatus != LokiThreadFriendRequestStatus.REQUEST_SENT
|
||||
&& threadFRStatus != LokiThreadFriendRequestStatus.REQUEST_RECEIVED) { return }
|
||||
Log.d("Loki", "Received a friend request accepted message from $publicKey.")
|
||||
lokiThreadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS)
|
||||
val lastMessageID = getLastMessageID(context, threadID)
|
||||
if (lastMessageID != null) {
|
||||
DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(lastMessageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED)
|
||||
}
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true)
|
||||
// Send a contact sync message if needed
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
val allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey)
|
||||
if (allUserDevices.contains(publicKey)) { return }
|
||||
val deviceToSync = MultiDeviceProtocol.shared.getMasterDevice(publicKey) ?: publicKey
|
||||
SyncMessagesProtocol.syncContact(context, Address.fromSerialized(deviceToSync))
|
||||
}
|
||||
|
||||
private fun canFriendRequestBeAutoAccepted(context: Context, publicKey: String): Boolean {
|
||||
val recipient = recipient(context, publicKey)
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
|
||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
val threadFRStatus = lokiThreadDB.getFriendRequestStatus(threadID)
|
||||
if (threadFRStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) {
|
||||
// This can happen if Alice sent Bob a friend request, Bob declined, but then Bob changed his
|
||||
// mind and sent a friend request to Alice. In this case we want Alice to auto-accept the request
|
||||
// and send a friend request accepted message back to Bob. We don't check that sending the
|
||||
// friend request accepted message succeeds. Even if it doesn't, the thread's current friend
|
||||
// request status will be set to FRIENDS for Alice making it possible for Alice to send messages
|
||||
// to Bob. When Bob receives a message, his thread's friend request status will then be set to
|
||||
// FRIENDS. If we do check for a successful send before updating Alice's thread's friend request
|
||||
// status to FRIENDS, we can end up in a deadlock where both users' threads' friend request statuses
|
||||
// are SENT.
|
||||
return true
|
||||
}
|
||||
// Auto-accept any friend requests from the user's own linked devices
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
val allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey)
|
||||
if (allUserDevices.contains(publicKey)) { return true }
|
||||
// Auto-accept if the user is friends with any of the sender's linked devices.
|
||||
val allSenderDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(publicKey)
|
||||
if (allSenderDevices.any { device ->
|
||||
val deviceAsRecipient = recipient(context, publicKey)
|
||||
val deviceThreadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(deviceAsRecipient)
|
||||
lokiThreadDB.getFriendRequestStatus(deviceThreadID) == LokiThreadFriendRequestStatus.FRIENDS
|
||||
}) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun handleFriendRequestMessageIfNeeded(context: Context, publicKey: String, content: SignalServiceContent) {
|
||||
val recipient = recipient(context, publicKey)
|
||||
// Friend requests don't apply to groups
|
||||
if (recipient.isGroupRecipient) { return }
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
|
||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
val threadFRStatus = lokiThreadDB.getFriendRequestStatus(threadID)
|
||||
if (canFriendRequestBeAutoAccepted(context, publicKey)) {
|
||||
Log.d("Loki", "Auto-accepting friend request from $publicKey.")
|
||||
lokiThreadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS)
|
||||
val lastMessageID = getLastMessageID(context, threadID)
|
||||
if (lastMessageID != null) {
|
||||
DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(lastMessageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED)
|
||||
}
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true)
|
||||
val ephemeralMessage = EphemeralMessage.create(publicKey)
|
||||
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(ephemeralMessage))
|
||||
} else if (threadFRStatus != LokiThreadFriendRequestStatus.FRIENDS) {
|
||||
Log.d("Loki", "Handling friend request from $publicKey.")
|
||||
// Checking that the sender of the message isn't already a friend is necessary because otherwise
|
||||
// the following situation can occur: Alice and Bob are friends. Bob loses his database and his
|
||||
// friend request status is reset to NONE. Bob now sends Alice a friend request. Alice's thread's
|
||||
// friend request status is reset to RECEIVED
|
||||
lokiThreadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED)
|
||||
val masterPublicKey = MultiDeviceProtocol.shared.getMasterDevice(publicKey) ?: publicKey
|
||||
val masterThreadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient(context, masterPublicKey))
|
||||
val masterThreadLastMessageID = getLastMessageID(context, masterThreadID) // Messages get routed into the master thread
|
||||
if (masterThreadLastMessageID != null) {
|
||||
DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(masterThreadLastMessageID, LokiMessageFriendRequestStatus.REQUEST_PENDING)
|
||||
} else {
|
||||
// Device link fetching could fail, in which case the message could get routed into the slave thread
|
||||
val slaveThreadLastMessageID = getLastMessageID(context, threadID)
|
||||
if (slaveThreadLastMessageID != null) {
|
||||
DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(slaveThreadLastMessageID, LokiMessageFriendRequestStatus.REQUEST_PENDING)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isFriendRequestFromBeforeRestoration(context: Context, content: SignalServiceContent): Boolean {
|
||||
return content.timestamp < TextSecurePreferences.getRestorationTime(context)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun shouldUpdateFriendRequestStatusFromOutgoingTextMessage(context: Context, message: OutgoingTextMessage): Boolean {
|
||||
// The order of these checks matters
|
||||
if (message.recipient.isGroupRecipient) { return false }
|
||||
if (message.recipient.address.serialize() == TextSecurePreferences.getLocalNumber(context)) { return false }
|
||||
// TODO: Return true if the message is a device linking request
|
||||
// TODO: Return false if the message is a session request
|
||||
return message.isFriendRequest
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun shouldUpdateFriendRequestStatusFromOutgoingMediaMessage(context: Context, message: OutgoingMediaMessage): Boolean {
|
||||
// The order of these checks matters
|
||||
if (message.recipient.isGroupRecipient) { return false }
|
||||
if (message.recipient.address.serialize() == TextSecurePreferences.getLocalNumber(context)) { return false }
|
||||
// TODO: Return true if the message is a device linking request
|
||||
// TODO: Return false if the message is a session request
|
||||
return message.isFriendRequest
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setFriendRequestStatusToSendingIfNeeded(context: Context, messageID: Long, threadID: Long) {
|
||||
val messageDB = DatabaseFactory.getLokiMessageDatabase(context)
|
||||
val messageFRStatus = messageDB.getFriendRequestStatus(messageID)
|
||||
if (messageFRStatus == LokiMessageFriendRequestStatus.NONE || messageFRStatus == LokiMessageFriendRequestStatus.REQUEST_EXPIRED) {
|
||||
messageDB.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_SENDING)
|
||||
}
|
||||
val threadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
val threadFRStatus = threadDB.getFriendRequestStatus(threadID)
|
||||
if (threadFRStatus == LokiThreadFriendRequestStatus.NONE || threadFRStatus == LokiThreadFriendRequestStatus.REQUEST_EXPIRED) {
|
||||
threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_SENDING)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setFriendRequestStatusToSentIfNeeded(context: Context, messageID: Long, threadID: Long) {
|
||||
val messageDB = DatabaseFactory.getLokiMessageDatabase(context)
|
||||
val messageFRStatus = messageDB.getFriendRequestStatus(messageID)
|
||||
if (messageFRStatus == LokiMessageFriendRequestStatus.NONE || messageFRStatus == LokiMessageFriendRequestStatus.REQUEST_EXPIRED
|
||||
|| messageFRStatus == LokiMessageFriendRequestStatus.REQUEST_SENDING) {
|
||||
messageDB.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_PENDING)
|
||||
}
|
||||
val threadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
val threadFRStatus = threadDB.getFriendRequestStatus(threadID)
|
||||
if (threadFRStatus == LokiThreadFriendRequestStatus.NONE || threadFRStatus == LokiThreadFriendRequestStatus.REQUEST_EXPIRED
|
||||
|| threadFRStatus == LokiThreadFriendRequestStatus.REQUEST_SENDING) {
|
||||
threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_SENT)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setFriendRequestStatusToFailedIfNeeded(context: Context, messageID: Long, threadID: Long) {
|
||||
val messageDB = DatabaseFactory.getLokiMessageDatabase(context)
|
||||
val messageFRStatus = messageDB.getFriendRequestStatus(messageID)
|
||||
if (messageFRStatus == LokiMessageFriendRequestStatus.REQUEST_SENDING) {
|
||||
messageDB.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_FAILED)
|
||||
}
|
||||
val threadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
val threadFRStatus = threadDB.getFriendRequestStatus(threadID)
|
||||
if (threadFRStatus == LokiThreadFriendRequestStatus.REQUEST_SENDING) {
|
||||
threadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.NONE)
|
||||
}
|
||||
}
|
||||
|
||||
fun sendAutoGeneratedFriendRequest(context: Context, publicKey: String) {
|
||||
val recipient = recipient(context, publicKey)
|
||||
val message = OutgoingEncryptedMessage(recipient, "Please accept to enable messages to be synced across devices", 0)
|
||||
message.isFriendRequest = true
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
|
||||
MessageSender.send(context, message, threadID, false, null)
|
||||
}
|
||||
}
|
@ -23,7 +23,6 @@ import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLinkingSession
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
||||
|
||||
object MultiDeviceProtocol {
|
||||
@ -40,36 +39,6 @@ object MultiDeviceProtocol {
|
||||
sendMessagePush(context, recipient, messageID, MessageType.Media, false)
|
||||
}
|
||||
|
||||
private fun sendMessagePushToDevice(context: Context, recipient: Recipient, messageID: Long, messageType: MessageType, isEndSession: Boolean): PushSendJob {
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
|
||||
val threadFRStatus = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID)
|
||||
val isNoteToSelf = SessionMetaProtocol.shared.isNoteToSelf(recipient.address.serialize())
|
||||
val isContactFriend = (threadFRStatus == LokiThreadFriendRequestStatus.FRIENDS || isNoteToSelf) // In the note to self case the device linking request was the FR
|
||||
val isFRMessage = !isContactFriend
|
||||
val hasVisibleContent = when (messageType) {
|
||||
MessageType.Text -> DatabaseFactory.getSmsDatabase(context).getMessage(messageID).body.isNotBlank()
|
||||
MessageType.Media -> {
|
||||
val outgoingMediaMessage = DatabaseFactory.getMmsDatabase(context).getOutgoingMessage(messageID)
|
||||
outgoingMediaMessage.body.isNotBlank() || outgoingMediaMessage.attachments.isNotEmpty()
|
||||
}
|
||||
}
|
||||
val shouldSendAutoGeneratedFR = !isContactFriend && !isFRMessage
|
||||
&& !isNoteToSelf && !recipient.address.isGroup // Group threads work through session requests
|
||||
&& hasVisibleContent && !isEndSession
|
||||
if (!shouldSendAutoGeneratedFR) {
|
||||
when (messageType) {
|
||||
MessageType.Text -> return PushTextSendJob(messageID, messageID, recipient.address, isFRMessage, null)
|
||||
MessageType.Media -> return PushMediaSendJob(messageID, messageID, recipient.address, isFRMessage, null)
|
||||
}
|
||||
} else {
|
||||
val autoGeneratedFRMessage = "Please accept to enable messages to be synced across devices"
|
||||
when (messageType) {
|
||||
MessageType.Text -> return PushTextSendJob(messageID, messageID, recipient.address, true, autoGeneratedFRMessage)
|
||||
MessageType.Media -> return PushMediaSendJob(messageID, messageID, recipient.address, true, autoGeneratedFRMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendMessagePush(context: Context, recipient: Recipient, messageID: Long, messageType: MessageType, isEndSession: Boolean) {
|
||||
val jobManager = ApplicationContext.getInstance(context).jobManager
|
||||
val isMultiDeviceRequired = !recipient.address.isOpenGroup
|
||||
@ -82,7 +51,12 @@ object MultiDeviceProtocol {
|
||||
val publicKey = recipient.address.serialize()
|
||||
FileServerAPI.shared.getDeviceLinks(publicKey).success {
|
||||
val devices = MultiDeviceProtocol.shared.getAllLinkedDevices(publicKey)
|
||||
val jobs = devices.map { sendMessagePushToDevice(context, recipient(context, it), messageID, messageType, isEndSession) }
|
||||
val jobs = devices.map {
|
||||
when (messageType) {
|
||||
MessageType.Text -> PushTextSendJob(messageID, messageID, recipient(context, it).address) as PushSendJob
|
||||
MessageType.Media -> PushMediaSendJob(messageID, messageID, recipient(context, it).address) as PushSendJob
|
||||
}
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
when (messageType) {
|
||||
MessageType.Text -> jobManager.startChain(jobs).enqueue()
|
||||
|
@ -27,8 +27,8 @@ object SessionManagementProtocol {
|
||||
val smsDB = DatabaseFactory.getSmsDatabase(context)
|
||||
val devices = lokiThreadDB.getSessionRestoreDevices(threadID)
|
||||
for (device in devices) {
|
||||
val sessionRestorationRequest = EphemeralMessage.createSessionRestorationRequest(recipient.address.serialize())
|
||||
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(sessionRestorationRequest))
|
||||
val sessionRequest = EphemeralMessage.createSessionRequest(recipient.address.serialize())
|
||||
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(sessionRequest))
|
||||
}
|
||||
val infoMessage = OutgoingTextMessage(recipient, "", 0, 0)
|
||||
val infoMessageID = smsDB.insertMessageOutbox(threadID, infoMessage, false, System.currentTimeMillis(), null)
|
||||
|
@ -11,7 +11,6 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
import java.security.MessageDigest
|
||||
|
||||
object SessionMetaProtocol {
|
||||
@ -75,31 +74,23 @@ object SessionMetaProtocol {
|
||||
* Should be invoked for the recipient's master device.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun canUserReplyToNotification(recipient: Recipient, context: Context): Boolean {
|
||||
val isGroup = recipient.isGroupRecipient
|
||||
if (isGroup) { return !recipient.address.isRSSFeed }
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
|
||||
return DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS
|
||||
fun canUserReplyToNotification(recipient: Recipient): Boolean {
|
||||
return !recipient.address.isRSSFeed
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be invoked for the recipient's master device.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun shouldSendReadReceipt(address: Address, context: Context): Boolean {
|
||||
if (address.isGroup) { return false }
|
||||
val recipient = Recipient.from(context, address,false)
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
|
||||
return DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS
|
||||
fun shouldSendReadReceipt(address: Address): Boolean {
|
||||
return !address.isGroup
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be invoked for the recipient's master device.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun shouldSendTypingIndicator(recipient: Recipient?, context: Context): Boolean {
|
||||
if (recipient == null || recipient.isGroupRecipient) { return false }
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
|
||||
return DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS
|
||||
fun shouldSendTypingIndicator(address: Address): Boolean {
|
||||
return !address.isGroup
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ import org.whispersystems.libsignal.loki.SessionResetProtocol
|
||||
import org.whispersystems.libsignal.loki.SessionResetStatus
|
||||
import org.whispersystems.libsignal.protocol.PreKeySignalMessage
|
||||
|
||||
class LokiSessionResetImplementation(private val context: Context) : SessionResetProtocol {
|
||||
class SessionResetImplementation(private val context: Context) : SessionResetProtocol {
|
||||
|
||||
override fun getSessionResetStatus(publicKey: String): SessionResetStatus {
|
||||
return DatabaseFactory.getLokiThreadDatabase(context).getSessionResetStatus(publicKey)
|
@ -24,8 +24,6 @@ import org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsI
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsInputStream
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiMessageFriendRequestStatus
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
|
||||
import java.util.*
|
||||
|
||||
@ -67,9 +65,7 @@ object SyncMessagesProtocol {
|
||||
if (!PublicKeyValidation.isValid(address.serialize())) { return false }
|
||||
if (address.serialize() == TextSecurePreferences.getMasterHexEncodedPublicKey(context)) { return false }
|
||||
if (address.serialize() == TextSecurePreferences.getLocalNumber(context)) { return false }
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(Recipient.from(context, address, false))
|
||||
val isFriend = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS
|
||||
return isFriend
|
||||
return true
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -99,29 +95,9 @@ object SyncMessagesProtocol {
|
||||
for (contactPublicKey in contactPublicKeys) {
|
||||
if (contactPublicKey == userPublicKey || !PublicKeyValidation.isValid(contactPublicKey)) { return }
|
||||
val recipient = recipient(context, contactPublicKey)
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
|
||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
val threadFRStatus = lokiThreadDB.getFriendRequestStatus(threadID)
|
||||
when (threadFRStatus) {
|
||||
LokiThreadFriendRequestStatus.NONE, LokiThreadFriendRequestStatus.REQUEST_EXPIRED -> {
|
||||
val contactLinkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(contactPublicKey)
|
||||
for (device in contactLinkedDevices) {
|
||||
FriendRequestProtocol.sendAutoGeneratedFriendRequest(context, device)
|
||||
}
|
||||
}
|
||||
LokiThreadFriendRequestStatus.REQUEST_RECEIVED -> {
|
||||
FriendRequestProtocol.acceptFriendRequest(context, recipient(context, contactPublicKey)) // Takes into account multi device internally
|
||||
lokiThreadDB.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS)
|
||||
val lastMessageID = FriendRequestProtocol.getLastMessageID(context, threadID)
|
||||
if (lastMessageID != null) {
|
||||
DatabaseFactory.getLokiMessageDatabase(context).setFriendRequestStatus(lastMessageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED)
|
||||
}
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient(context, contactPublicKey), true)
|
||||
}
|
||||
else -> {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
val applicationContext = context.applicationContext as ApplicationContext
|
||||
applicationContext.sendSessionRequestIfNeeded(contactPublicKey)
|
||||
// TODO: Make the thread visible
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,13 +112,13 @@ object SyncMessagesProtocol {
|
||||
val closedGroups = closedGroupsInputStream.readAll()
|
||||
for (closedGroup in closedGroups) {
|
||||
val signalServiceGroup = SignalServiceGroup(
|
||||
SignalServiceGroup.Type.UPDATE,
|
||||
closedGroup.id,
|
||||
SignalServiceGroup.GroupType.SIGNAL,
|
||||
closedGroup.name.orNull(),
|
||||
closedGroup.members,
|
||||
closedGroup.avatar.orNull(),
|
||||
closedGroup.admins
|
||||
SignalServiceGroup.Type.UPDATE,
|
||||
closedGroup.id,
|
||||
SignalServiceGroup.GroupType.SIGNAL,
|
||||
closedGroup.name.orNull(),
|
||||
closedGroup.members,
|
||||
closedGroup.avatar.orNull(),
|
||||
closedGroup.admins
|
||||
)
|
||||
val signalServiceDataMessage = SignalServiceDataMessage(content.timestamp, signalServiceGroup, null, null)
|
||||
// This establishes sessions internally
|
||||
|
@ -5,11 +5,9 @@ import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
|
||||
data class Contact(
|
||||
val recipient: Recipient,
|
||||
val isFriend: Boolean,
|
||||
val isSlave: Boolean,
|
||||
val isOurDevice: Boolean
|
||||
) {
|
||||
@ -31,10 +29,9 @@ object ContactUtilities {
|
||||
@JvmStatic
|
||||
fun getAllContacts(context: Context): Set<Contact> {
|
||||
val threadDatabase = DatabaseFactory.getThreadDatabase(context)
|
||||
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
val lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(context)
|
||||
val userDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userHexEncodedPublicKey)
|
||||
val userDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey)
|
||||
val cursor = threadDatabase.conversationList
|
||||
val result = mutableSetOf<Contact>()
|
||||
threadDatabase.readerFor(cursor).use { reader ->
|
||||
@ -43,13 +40,12 @@ object ContactUtilities {
|
||||
val recipient = thread.recipient
|
||||
val publicKey = recipient.address.serialize()
|
||||
val isUserDevice = userDevices.contains(publicKey)
|
||||
val isFriend = lokiThreadDatabase.getFriendRequestStatus(thread.threadId) == LokiThreadFriendRequestStatus.FRIENDS
|
||||
var isSlave = false
|
||||
if (!recipient.isGroupRecipient) {
|
||||
val deviceLinks = lokiAPIDatabase.getDeviceLinks(publicKey)
|
||||
isSlave = deviceLinks.find { it.slavePublicKey == publicKey } != null
|
||||
}
|
||||
result.add(Contact(recipient, isFriend, isSlave, isUserDevice))
|
||||
result.add(Contact(recipient, isSlave, isUserDevice))
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
@ -8,11 +8,11 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
||||
fun getOpenGroupDisplayName(recipient: Recipient, threadRecipient: Recipient, context: Context): String {
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(threadRecipient)
|
||||
val publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
||||
val hexEncodedPublicKey = recipient.address.toString()
|
||||
val publicKey = recipient.address.toString()
|
||||
val displayName = if (publicChat != null) {
|
||||
DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(publicChat.id, hexEncodedPublicKey)
|
||||
DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(publicChat.id, publicKey)
|
||||
} else {
|
||||
DatabaseFactory.getLokiUserDatabase(context).getDisplayName(hexEncodedPublicKey)
|
||||
DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey)
|
||||
}
|
||||
return displayName ?: hexEncodedPublicKey
|
||||
return displayName ?: publicKey
|
||||
}
|
@ -22,7 +22,7 @@ object OpenGroupUtilities {
|
||||
val application = ApplicationContext.getInstance(context)
|
||||
val displayName = TextSecurePreferences.getProfileName(context)
|
||||
val lokiPublicChatAPI = application.publicChatAPI ?: throw Error("LokiPublicChatAPI is not initialized.")
|
||||
return application.lokiPublicChatManager.addChat(url, channel).then { group ->
|
||||
return application.publicChatManager.addChat(url, channel).then { group ->
|
||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastMessageServerID(channel, url)
|
||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(channel, url)
|
||||
lokiPublicChatAPI.getMessages(channel, url)
|
||||
|
@ -50,18 +50,18 @@ class ConversationView : LinearLayout {
|
||||
unreadMessagesIndicatorView.visibility = if (thread.unreadCount > 0) View.VISIBLE else View.INVISIBLE
|
||||
if (thread.recipient.isGroupRecipient) {
|
||||
if ("Session Public Chat" == thread.recipient.name) {
|
||||
profilePictureView.hexEncodedPublicKey = ""
|
||||
profilePictureView.publicKey = ""
|
||||
profilePictureView.isRSSFeed = true
|
||||
} else {
|
||||
val users = MentionsManager.shared.userPublicKeyCache[thread.threadId]?.toList() ?: listOf()
|
||||
val randomUsers = users.sorted() // Sort to provide a level of stability
|
||||
profilePictureView.hexEncodedPublicKey = randomUsers.getOrNull(0) ?: ""
|
||||
profilePictureView.additionalHexEncodedPublicKey = randomUsers.getOrNull(1) ?: ""
|
||||
profilePictureView.publicKey = randomUsers.getOrNull(0) ?: ""
|
||||
profilePictureView.additionalPublicKey = randomUsers.getOrNull(1) ?: ""
|
||||
profilePictureView.isRSSFeed = thread.recipient.name == "Loki News" || thread.recipient.name == "Session Updates"
|
||||
}
|
||||
} else {
|
||||
profilePictureView.hexEncodedPublicKey = thread.recipient.address.toString()
|
||||
profilePictureView.additionalHexEncodedPublicKey = null
|
||||
profilePictureView.publicKey = thread.recipient.address.toString()
|
||||
profilePictureView.additionalPublicKey = null
|
||||
profilePictureView.isRSSFeed = false
|
||||
}
|
||||
profilePictureView.glide = glide
|
||||
|
@ -1,190 +0,0 @@
|
||||
package org.thoughtcrime.securesms.loki.views
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.util.TypedValue
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import com.github.ybq.android.spinkit.style.DoubleBounce
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
|
||||
import org.thoughtcrime.securesms.loki.utilities.toPx
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiMessageFriendRequestStatus
|
||||
|
||||
class FriendRequestView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : LinearLayout(context, attrs, defStyleAttr) {
|
||||
private var isUISetUp = false
|
||||
private var message: MessageRecord? = null
|
||||
var delegate: FriendRequestViewDelegate? = null
|
||||
|
||||
// region Components
|
||||
private val topSpacer by lazy {
|
||||
val result = View(context)
|
||||
result.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, toPx(12, resources))
|
||||
result
|
||||
}
|
||||
|
||||
private val label by lazy {
|
||||
val result = TextView(context)
|
||||
result.setTextColor(resources.getColorWithID(R.color.text, context.theme))
|
||||
result.textAlignment = TextView.TEXT_ALIGNMENT_CENTER
|
||||
result.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.small_font_size))
|
||||
result
|
||||
}
|
||||
|
||||
private val buttonLinearLayout by lazy {
|
||||
val result = LinearLayout(context)
|
||||
result.orientation = HORIZONTAL
|
||||
result.setPadding(0, resources.getDimension(R.dimen.medium_spacing).toInt(), 0, 0)
|
||||
result
|
||||
}
|
||||
|
||||
private val loaderContainer by lazy {
|
||||
val result = LinearLayout(context)
|
||||
val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, toPx(50, resources))
|
||||
result.layoutParams = layoutParams
|
||||
result.gravity = Gravity.CENTER
|
||||
result
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Initialization
|
||||
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
||||
constructor(context: Context) : this(context, null)
|
||||
// endregion
|
||||
|
||||
// region Updating
|
||||
fun update(message: MessageRecord) {
|
||||
this.message = message
|
||||
setUpUIIfNeeded()
|
||||
updateUI()
|
||||
}
|
||||
|
||||
private fun setUpUIIfNeeded() {
|
||||
if (isUISetUp) { return }
|
||||
isUISetUp = true
|
||||
orientation = VERTICAL
|
||||
setPadding(toPx(48, resources), 0, toPx(48, resources), 0)
|
||||
addView(topSpacer)
|
||||
addView(label)
|
||||
if (!message!!.isOutgoing) {
|
||||
val loader = ProgressBar(context)
|
||||
loader.isIndeterminate = true
|
||||
loader.indeterminateDrawable = DoubleBounce()
|
||||
val loaderLayoutParams = LayoutParams(LayoutParams.MATCH_PARENT, toPx(24, resources))
|
||||
loader.layoutParams = loaderLayoutParams
|
||||
loaderContainer.addView(loader)
|
||||
addView(loaderContainer)
|
||||
fun button(): Button {
|
||||
val result = Button(context)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
result.elevation = 0f
|
||||
result.stateListAnimator = null
|
||||
}
|
||||
result.setTextColor(resources.getColorWithID(R.color.text, context.theme))
|
||||
result.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.small_font_size))
|
||||
result.isAllCaps = false
|
||||
result.setPadding(0, 0, 0, 0)
|
||||
val buttonLayoutParams = LayoutParams(0, resources.getDimension(R.dimen.small_button_height).toInt())
|
||||
buttonLayoutParams.weight = 1f
|
||||
result.layoutParams = buttonLayoutParams
|
||||
return result
|
||||
}
|
||||
val rejectButton = button()
|
||||
rejectButton.text = resources.getString(R.string.view_friend_request_reject_button_title)
|
||||
rejectButton.setBackgroundResource(R.drawable.unimportant_dialog_button_background)
|
||||
rejectButton.setOnClickListener { reject() }
|
||||
buttonLinearLayout.addView(rejectButton)
|
||||
val acceptButton = button()
|
||||
acceptButton.text = resources.getString(R.string.view_friend_request_accept_button_title)
|
||||
acceptButton.setBackgroundResource(R.drawable.prominent_dialog_button_background)
|
||||
val acceptButtonLayoutParams = acceptButton.layoutParams as LayoutParams
|
||||
acceptButtonLayoutParams.setMargins(resources.getDimension(R.dimen.medium_spacing).toInt(), 0, 0, 0)
|
||||
acceptButton.layoutParams = acceptButtonLayoutParams
|
||||
acceptButton.setOnClickListener { accept() }
|
||||
buttonLinearLayout.addView(acceptButton)
|
||||
buttonLinearLayout.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, toPx(50, resources))
|
||||
addView(buttonLinearLayout)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateUI() {
|
||||
val message = message
|
||||
val lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context)
|
||||
val contactID = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(message!!.threadId)!!.address.toString()
|
||||
val contactDisplayName = DatabaseFactory.getLokiUserDatabase(context).getDisplayName(contactID) ?: contactID
|
||||
val friendRequestStatus = lokiMessageDatabase.getFriendRequestStatus(message.id)
|
||||
if (message is MediaMmsMessageRecord) {
|
||||
visibility = View.GONE
|
||||
return
|
||||
}
|
||||
if (!message.isOutgoing) {
|
||||
visibility = if (friendRequestStatus == LokiMessageFriendRequestStatus.NONE) View.GONE else View.VISIBLE
|
||||
buttonLinearLayout.visibility = if (friendRequestStatus != LokiMessageFriendRequestStatus.REQUEST_PENDING) View.GONE else View.VISIBLE
|
||||
loaderContainer.visibility = if (friendRequestStatus == LokiMessageFriendRequestStatus.REQUEST_SENDING) View.VISIBLE else View.GONE
|
||||
val formatID = when (friendRequestStatus) {
|
||||
LokiMessageFriendRequestStatus.NONE, LokiMessageFriendRequestStatus.REQUEST_SENDING, LokiMessageFriendRequestStatus.REQUEST_FAILED -> return
|
||||
LokiMessageFriendRequestStatus.REQUEST_PENDING -> R.string.view_friend_request_incoming_pending_message
|
||||
LokiMessageFriendRequestStatus.REQUEST_ACCEPTED -> R.string.view_friend_request_incoming_accepted_message
|
||||
LokiMessageFriendRequestStatus.REQUEST_REJECTED -> R.string.view_friend_request_incoming_declined_message
|
||||
LokiMessageFriendRequestStatus.REQUEST_EXPIRED -> R.string.view_friend_request_incoming_expired_message
|
||||
}
|
||||
label.text = resources.getString(formatID, contactDisplayName)
|
||||
} else {
|
||||
visibility = if (friendRequestStatus == LokiMessageFriendRequestStatus.NONE) View.GONE else View.VISIBLE
|
||||
buttonLinearLayout.visibility = View.GONE
|
||||
loaderContainer.visibility = View.GONE
|
||||
val formatID = when (friendRequestStatus) {
|
||||
LokiMessageFriendRequestStatus.NONE -> return
|
||||
LokiMessageFriendRequestStatus.REQUEST_SENDING, LokiMessageFriendRequestStatus.REQUEST_FAILED -> null
|
||||
LokiMessageFriendRequestStatus.REQUEST_PENDING, LokiMessageFriendRequestStatus.REQUEST_REJECTED -> R.string.view_friend_request_outgoing_pending_message
|
||||
LokiMessageFriendRequestStatus.REQUEST_ACCEPTED -> R.string.view_friend_request_outgoing_accepted_message
|
||||
LokiMessageFriendRequestStatus.REQUEST_EXPIRED -> R.string.view_friend_request_outgoing_expired_message
|
||||
}
|
||||
if (formatID != null) {
|
||||
label.text = resources.getString(formatID, contactDisplayName)
|
||||
}
|
||||
label.visibility = if (formatID != null) View.VISIBLE else View.GONE
|
||||
topSpacer.visibility = label.visibility
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Interaction
|
||||
private fun accept() {
|
||||
val lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context)
|
||||
lokiMessageDatabase.setFriendRequestStatus(message!!.id, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED)
|
||||
updateUI()
|
||||
delegate?.acceptFriendRequest(message!!)
|
||||
}
|
||||
|
||||
private fun reject() {
|
||||
val lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context)
|
||||
lokiMessageDatabase.setFriendRequestStatus(message!!.id, LokiMessageFriendRequestStatus.REQUEST_REJECTED)
|
||||
updateUI()
|
||||
delegate?.rejectFriendRequest(message!!)
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
||||
// region Delegate
|
||||
interface FriendRequestViewDelegate {
|
||||
/**
|
||||
* Implementations of this method should update the thread's friend request status
|
||||
* and send a friend request accepted message.
|
||||
*/
|
||||
fun acceptFriendRequest(friendRequest: MessageRecord)
|
||||
/**
|
||||
* Implementations of this method should update the thread's friend request status
|
||||
* and remove the pre keys associated with the contact.
|
||||
*/
|
||||
fun rejectFriendRequest(friendRequest: MessageRecord)
|
||||
}
|
||||
// endregion
|
@ -31,8 +31,8 @@ class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr:
|
||||
|
||||
private fun update() {
|
||||
displayNameTextView.text = mentionCandidate.displayName
|
||||
profilePictureView.hexEncodedPublicKey = mentionCandidate.publicKey
|
||||
profilePictureView.additionalHexEncodedPublicKey = null
|
||||
profilePictureView.publicKey = mentionCandidate.publicKey
|
||||
profilePictureView.additionalPublicKey = null
|
||||
profilePictureView.isRSSFeed = false
|
||||
profilePictureView.glide = glide!!
|
||||
profilePictureView.update()
|
||||
|
@ -21,8 +21,8 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
|
||||
class ProfilePictureView : RelativeLayout {
|
||||
lateinit var glide: GlideRequests
|
||||
var hexEncodedPublicKey: String? = null
|
||||
var additionalHexEncodedPublicKey: String? = null
|
||||
var publicKey: String? = null
|
||||
var additionalPublicKey: String? = null
|
||||
var isRSSFeed = false
|
||||
var isLarge = false
|
||||
|
||||
@ -52,11 +52,11 @@ class ProfilePictureView : RelativeLayout {
|
||||
|
||||
// region Updating
|
||||
fun update() {
|
||||
val hexEncodedPublicKey = hexEncodedPublicKey ?: return
|
||||
val additionalHexEncodedPublicKey = additionalHexEncodedPublicKey
|
||||
doubleModeImageViewContainer.visibility = if (additionalHexEncodedPublicKey != null && !isRSSFeed) View.VISIBLE else View.INVISIBLE
|
||||
singleModeImageViewContainer.visibility = if (additionalHexEncodedPublicKey == null && !isRSSFeed && !isLarge) View.VISIBLE else View.INVISIBLE
|
||||
largeSingleModeImageViewContainer.visibility = if (additionalHexEncodedPublicKey == null && !isRSSFeed && isLarge) View.VISIBLE else View.INVISIBLE
|
||||
val publicKey = publicKey ?: return
|
||||
val additionalPublicKey = additionalPublicKey
|
||||
doubleModeImageViewContainer.visibility = if (additionalPublicKey != null && !isRSSFeed) View.VISIBLE else View.INVISIBLE
|
||||
singleModeImageViewContainer.visibility = if (additionalPublicKey == null && !isRSSFeed && !isLarge) View.VISIBLE else View.INVISIBLE
|
||||
largeSingleModeImageViewContainer.visibility = if (additionalPublicKey == null && !isRSSFeed && isLarge) View.VISIBLE else View.INVISIBLE
|
||||
rssImageView.visibility = if (isRSSFeed) View.VISIBLE else View.INVISIBLE
|
||||
fun setProfilePictureIfNeeded(imageView: ImageView, hexEncodedPublicKey: String, @DimenRes sizeID: Int) {
|
||||
glide.clear(imageView)
|
||||
@ -76,10 +76,10 @@ class ProfilePictureView : RelativeLayout {
|
||||
imageView.setImageDrawable(null)
|
||||
}
|
||||
}
|
||||
setProfilePictureIfNeeded(doubleModeImageView1, hexEncodedPublicKey, R.dimen.small_profile_picture_size)
|
||||
setProfilePictureIfNeeded(doubleModeImageView2, additionalHexEncodedPublicKey ?: "", R.dimen.small_profile_picture_size)
|
||||
setProfilePictureIfNeeded(singleModeImageView, hexEncodedPublicKey, R.dimen.medium_profile_picture_size)
|
||||
setProfilePictureIfNeeded(largeSingleModeImageView, hexEncodedPublicKey, R.dimen.large_profile_picture_size)
|
||||
setProfilePictureIfNeeded(doubleModeImageView1, publicKey, R.dimen.small_profile_picture_size)
|
||||
setProfilePictureIfNeeded(doubleModeImageView2, additionalPublicKey ?: "", R.dimen.small_profile_picture_size)
|
||||
setProfilePictureIfNeeded(singleModeImageView, publicKey, R.dimen.medium_profile_picture_size)
|
||||
setProfilePictureIfNeeded(largeSingleModeImageView, publicKey, R.dimen.large_profile_picture_size)
|
||||
}
|
||||
// endregion
|
||||
}
|
@ -48,20 +48,20 @@ class UserView : LinearLayout {
|
||||
val address = user.address.serialize()
|
||||
if (user.isGroupRecipient) {
|
||||
if ("Session Public Chat" == user.name || user.address.isRSSFeed) {
|
||||
profilePictureView.hexEncodedPublicKey = ""
|
||||
profilePictureView.additionalHexEncodedPublicKey = null
|
||||
profilePictureView.publicKey = ""
|
||||
profilePictureView.additionalPublicKey = null
|
||||
profilePictureView.isRSSFeed = true
|
||||
} else {
|
||||
val threadID = GroupManager.getThreadIDFromGroupID(address, context)
|
||||
val users = MentionsManager.shared.userPublicKeyCache[threadID]?.toList() ?: listOf()
|
||||
val randomUsers = users.sorted() // Sort to provide a level of stability
|
||||
profilePictureView.hexEncodedPublicKey = randomUsers.getOrNull(0) ?: ""
|
||||
profilePictureView.additionalHexEncodedPublicKey = randomUsers.getOrNull(1) ?: ""
|
||||
profilePictureView.publicKey = randomUsers.getOrNull(0) ?: ""
|
||||
profilePictureView.additionalPublicKey = randomUsers.getOrNull(1) ?: ""
|
||||
profilePictureView.isRSSFeed = false
|
||||
}
|
||||
} else {
|
||||
profilePictureView.hexEncodedPublicKey = address
|
||||
profilePictureView.additionalHexEncodedPublicKey = null
|
||||
profilePictureView.publicKey = address
|
||||
profilePictureView.additionalPublicKey = null
|
||||
profilePictureView.isRSSFeed = false
|
||||
}
|
||||
profilePictureView.glide = glide
|
||||
|
@ -23,7 +23,6 @@ public class OutgoingMediaMessage {
|
||||
private final int distributionType;
|
||||
private final int subscriptionId;
|
||||
private final long expiresIn;
|
||||
public boolean isFriendRequest = false;
|
||||
private final QuoteModel outgoingQuote;
|
||||
|
||||
private final List<NetworkFailure> networkFailures = new LinkedList<>();
|
||||
|
@ -325,7 +325,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
|
||||
|
||||
ReplyMethod replyMethod = ReplyMethod.forRecipient(context, recipient);
|
||||
|
||||
boolean canReply = SessionMetaProtocol.canUserReplyToNotification(recipient, context);
|
||||
boolean canReply = SessionMetaProtocol.canUserReplyToNotification(recipient);
|
||||
|
||||
PendingIntent quickReplyIntent = canReply ? notificationState.getQuickReplyIntent(context, recipient) : null;
|
||||
PendingIntent remoteReplyIntent = canReply ? notificationState.getRemoteReplyIntent(context, recipient, replyMethod) : null;
|
||||
|
@ -93,7 +93,7 @@ public class MarkReadReceiver extends BroadcastReceiver {
|
||||
for (Address address : addressMap.keySet()) {
|
||||
List<Long> timestamps = Stream.of(addressMap.get(address)).map(SyncMessageId::getTimetamp).toList();
|
||||
// Loki - Check whether we want to send a read receipt to this user
|
||||
if (!SessionMetaProtocol.shouldSendReadReceipt(address, context)) { continue; }
|
||||
if (!SessionMetaProtocol.shouldSendReadReceipt(address)) { continue; }
|
||||
// Loki - Take into account multi device
|
||||
Set<String> linkedDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(address.serialize());
|
||||
for (String device : linkedDevices) {
|
||||
|
@ -7,7 +7,7 @@ import androidx.annotation.MainThread;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.loki.api.LokiPublicChatManager;
|
||||
import org.thoughtcrime.securesms.loki.api.PublicChatManager;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Debouncer;
|
||||
import org.whispersystems.signalservice.loki.api.Poller;
|
||||
@ -41,14 +41,14 @@ public class OptimizedMessageNotifier implements MessageNotifier {
|
||||
@Override
|
||||
public void updateNotification(@NonNull Context context) {
|
||||
Poller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
LokiPublicChatManager lokiPublicChatManager = ApplicationContext.getInstance(context).lokiPublicChatManager;
|
||||
PublicChatManager publicChatManager = ApplicationContext.getInstance(context).publicChatManager;
|
||||
boolean isCaughtUp = true;
|
||||
if (lokiPoller != null) {
|
||||
isCaughtUp = isCaughtUp && lokiPoller.isCaughtUp();
|
||||
}
|
||||
|
||||
if (lokiPublicChatManager != null) {
|
||||
isCaughtUp = isCaughtUp && lokiPublicChatManager.areAllCaughtUp();
|
||||
if (publicChatManager != null) {
|
||||
isCaughtUp = isCaughtUp && publicChatManager.areAllCaughtUp();
|
||||
}
|
||||
|
||||
if (isCaughtUp) {
|
||||
@ -61,14 +61,14 @@ public class OptimizedMessageNotifier implements MessageNotifier {
|
||||
@Override
|
||||
public void updateNotification(@NonNull Context context, long threadId) {
|
||||
Poller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
LokiPublicChatManager lokiPublicChatManager = ApplicationContext.getInstance(context).lokiPublicChatManager;
|
||||
PublicChatManager publicChatManager = ApplicationContext.getInstance(context).publicChatManager;
|
||||
boolean isCaughtUp = true;
|
||||
if (lokiPoller != null) {
|
||||
isCaughtUp = isCaughtUp && lokiPoller.isCaughtUp();
|
||||
}
|
||||
|
||||
if (lokiPublicChatManager != null) {
|
||||
isCaughtUp = isCaughtUp && lokiPublicChatManager.areAllCaughtUp();
|
||||
if (publicChatManager != null) {
|
||||
isCaughtUp = isCaughtUp && publicChatManager.areAllCaughtUp();
|
||||
}
|
||||
|
||||
if (isCaughtUp) {
|
||||
@ -81,14 +81,14 @@ public class OptimizedMessageNotifier implements MessageNotifier {
|
||||
@Override
|
||||
public void updateNotification(@NonNull Context context, long threadId, boolean signal) {
|
||||
Poller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
LokiPublicChatManager lokiPublicChatManager = ApplicationContext.getInstance(context).lokiPublicChatManager;
|
||||
PublicChatManager publicChatManager = ApplicationContext.getInstance(context).publicChatManager;
|
||||
boolean isCaughtUp = true;
|
||||
if (lokiPoller != null) {
|
||||
isCaughtUp = isCaughtUp && lokiPoller.isCaughtUp();
|
||||
}
|
||||
|
||||
if (lokiPublicChatManager != null) {
|
||||
isCaughtUp = isCaughtUp && lokiPublicChatManager.areAllCaughtUp();
|
||||
if (publicChatManager != null) {
|
||||
isCaughtUp = isCaughtUp && publicChatManager.areAllCaughtUp();
|
||||
}
|
||||
|
||||
if (isCaughtUp) {
|
||||
@ -101,14 +101,14 @@ public class OptimizedMessageNotifier implements MessageNotifier {
|
||||
@Override
|
||||
public void updateNotification(@android.support.annotation.NonNull Context context, boolean signal, int reminderCount) {
|
||||
Poller lokiPoller = ApplicationContext.getInstance(context).lokiPoller;
|
||||
LokiPublicChatManager lokiPublicChatManager = ApplicationContext.getInstance(context).lokiPublicChatManager;
|
||||
PublicChatManager publicChatManager = ApplicationContext.getInstance(context).publicChatManager;
|
||||
boolean isCaughtUp = true;
|
||||
if (lokiPoller != null) {
|
||||
isCaughtUp = isCaughtUp && lokiPoller.isCaughtUp();
|
||||
}
|
||||
|
||||
if (lokiPublicChatManager != null) {
|
||||
isCaughtUp = isCaughtUp && lokiPublicChatManager.areAllCaughtUp();
|
||||
if (publicChatManager != null) {
|
||||
isCaughtUp = isCaughtUp && publicChatManager.areAllCaughtUp();
|
||||
}
|
||||
|
||||
if (isCaughtUp) {
|
||||
|
@ -38,7 +38,6 @@ import org.thoughtcrime.securesms.jobs.MmsSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.PushGroupSendJob;
|
||||
import org.thoughtcrime.securesms.jobs.SmsSendJob;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.protocol.FriendRequestProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
@ -76,11 +75,6 @@ public class MessageSender {
|
||||
|
||||
long messageId = database.insertMessageOutbox(allocatedThreadId, message, forceSms, System.currentTimeMillis(), insertListener);
|
||||
|
||||
// Loki - Set the message's friend request status as soon as it hits the database
|
||||
if (FriendRequestProtocol.shouldUpdateFriendRequestStatusFromOutgoingTextMessage(context, message)) {
|
||||
FriendRequestProtocol.setFriendRequestStatusToSendingIfNeeded(context, messageId, allocatedThreadId);
|
||||
}
|
||||
|
||||
sendTextMessage(context, recipient, forceSms, keyExchange, messageId, message.isEndSession());
|
||||
|
||||
return allocatedThreadId;
|
||||
@ -107,11 +101,6 @@ public class MessageSender {
|
||||
Recipient recipient = message.getRecipient();
|
||||
long messageId = database.insertMessageOutbox(message, allocatedThreadId, forceSms, insertListener);
|
||||
|
||||
// Loki - Set the message's friend request status as soon as it hits the database
|
||||
if (FriendRequestProtocol.shouldUpdateFriendRequestStatusFromOutgoingMediaMessage(context, message)) {
|
||||
FriendRequestProtocol.setFriendRequestStatusToSendingIfNeeded(context, messageId, allocatedThreadId);
|
||||
}
|
||||
|
||||
sendMediaMessage(context, recipient, forceSms, messageId, message.getExpiresIn());
|
||||
return allocatedThreadId;
|
||||
} catch (MmsException e) {
|
||||
|
@ -9,7 +9,6 @@ public class OutgoingTextMessage {
|
||||
private final String message;
|
||||
private final int subscriptionId;
|
||||
private final long expiresIn;
|
||||
public boolean isFriendRequest = false;
|
||||
|
||||
public OutgoingTextMessage(Recipient recipient, String message, int subscriptionId) {
|
||||
this(recipient, message, 0, subscriptionId);
|
||||
|
Loading…
x
Reference in New Issue
Block a user