mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-17 22:18:27 +00:00
commit
1eb38a1447
@ -7,5 +7,5 @@
|
|||||||
|
|
||||||
<corners android:radius="@dimen/medium_button_corner_radius" />
|
<corners android:radius="@dimen/medium_button_corner_radius" />
|
||||||
|
|
||||||
<stroke android:width="@dimen/border_thickness" android:color="?colorAccent" />
|
<stroke android:width="@dimen/border_thickness" android:color="@color/accent" />
|
||||||
</shape>
|
</shape>
|
@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/contentView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@ -30,7 +31,7 @@
|
|||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="There are two ways Session can notify you of new messages." />
|
android:text="There are two ways Session can notify you of new messages." />
|
||||||
|
|
||||||
<LinearLayout
|
<org.thoughtcrime.securesms.loki.views.PNModeView
|
||||||
android:id="@+id/fcmOptionView"
|
android:id="@+id/fcmOptionView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -66,9 +67,9 @@
|
|||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="@string/activity_pn_mode_recommended_option_tag" />
|
android:text="@string/activity_pn_mode_recommended_option_tag" />
|
||||||
|
|
||||||
</LinearLayout>
|
</org.thoughtcrime.securesms.loki.views.PNModeView>
|
||||||
|
|
||||||
<LinearLayout
|
<org.thoughtcrime.securesms.loki.views.PNModeView
|
||||||
android:id="@+id/backgroundPollingOptionView"
|
android:id="@+id/backgroundPollingOptionView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -95,7 +96,7 @@
|
|||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="Session will occasionally check for new messages in the background. Full metadata protection is guaranteed, but message notifications will be unreliable." />
|
android:text="Session will occasionally check for new messages in the background. Full metadata protection is guaranteed, but message notifications will be unreliable." />
|
||||||
|
|
||||||
</LinearLayout>
|
</org.thoughtcrime.securesms.loki.views.PNModeView>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -76,7 +76,8 @@
|
|||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:clipChildren="false">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerView"
|
android:id="@+id/recyclerView"
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_margin="@dimen/large_spacing">
|
android:layout_margin="@dimen/large_spacing"
|
||||||
|
android:clipChildren="false">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/pathRowsContainer"
|
android:id="@+id/pathRowsContainer"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/contentView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@ -30,7 +31,7 @@
|
|||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="There are two ways Session can notify you of new messages." />
|
android:text="There are two ways Session can notify you of new messages." />
|
||||||
|
|
||||||
<LinearLayout
|
<org.thoughtcrime.securesms.loki.views.PNModeView
|
||||||
android:id="@+id/fcmOptionView"
|
android:id="@+id/fcmOptionView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -66,9 +67,9 @@
|
|||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="@string/activity_pn_mode_recommended_option_tag" />
|
android:text="@string/activity_pn_mode_recommended_option_tag" />
|
||||||
|
|
||||||
</LinearLayout>
|
</org.thoughtcrime.securesms.loki.views.PNModeView>
|
||||||
|
|
||||||
<LinearLayout
|
<org.thoughtcrime.securesms.loki.views.PNModeView
|
||||||
android:id="@+id/backgroundPollingOptionView"
|
android:id="@+id/backgroundPollingOptionView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -95,7 +96,7 @@
|
|||||||
android:textColor="@color/text"
|
android:textColor="@color/text"
|
||||||
android:text="Session will occasionally check for new messages in the background. Full metadata protection is guaranteed, but message notifications will be unreliable." />
|
android:text="Session will occasionally check for new messages in the background. Full metadata protection is guaranteed, but message notifications will be unreliable." />
|
||||||
|
|
||||||
</LinearLayout>
|
</org.thoughtcrime.securesms.loki.views.PNModeView>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -20,9 +20,15 @@
|
|||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<org.thoughtcrime.securesms.loki.views.ProfilePictureView
|
||||||
|
android:id="@+id/profilePictureView"
|
||||||
|
android:layout_width="@dimen/medium_profile_picture_size"
|
||||||
|
android:layout_height="@dimen/medium_profile_picture_size" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/medium_spacing"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -9,6 +9,13 @@
|
|||||||
app:behavior_hideable="true"
|
app:behavior_hideable="true"
|
||||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
|
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/detailsTextView"
|
||||||
|
style="@style/BottomSheetActionItem"
|
||||||
|
android:drawableStart="@drawable/ic_info_outline_white_24dp"
|
||||||
|
android:drawableTint="?attr/colorControlNormal"
|
||||||
|
android:text="@string/details" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/blockTextView"
|
android:id="@+id/blockTextView"
|
||||||
style="@style/BottomSheetActionItem"
|
style="@style/BottomSheetActionItem"
|
||||||
|
51
res/layout/fragment_user_details_bottom_sheet.xml
Normal file
51
res/layout/fragment_user_details_bottom_sheet.xml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:paddingLeft="@dimen/large_spacing"
|
||||||
|
android:paddingRight="@dimen/large_spacing"
|
||||||
|
android:paddingBottom="@dimen/large_spacing"
|
||||||
|
app:behavior_hideable="true"
|
||||||
|
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
|
||||||
|
|
||||||
|
<org.thoughtcrime.securesms.loki.views.ProfilePictureView
|
||||||
|
android:id="@+id/profilePictureView"
|
||||||
|
android:layout_width="@dimen/large_profile_picture_size"
|
||||||
|
android:layout_height="@dimen/large_profile_picture_size"
|
||||||
|
android:layout_marginTop="@dimen/large_spacing" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/nameTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/medium_spacing"
|
||||||
|
android:textSize="@dimen/massive_font_size"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/text"
|
||||||
|
android:text="Spiderman" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/SessionIDTextView"
|
||||||
|
android:id="@+id/publicKeyTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="@dimen/large_font_size"
|
||||||
|
android:layout_marginTop="@dimen/large_spacing"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/Widget.Session.Button.Common.ProminentOutline"
|
||||||
|
android:id="@+id/copyButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/medium_button_height"
|
||||||
|
android:layout_marginTop="@dimen/medium_spacing"
|
||||||
|
android:paddingLeft="@dimen/large_spacing"
|
||||||
|
android:paddingRight="@dimen/large_spacing"
|
||||||
|
android:text="@string/copy" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -5,6 +5,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingLeft="@dimen/very_large_spacing"
|
android:paddingLeft="@dimen/very_large_spacing"
|
||||||
android:paddingRight="@dimen/very_large_spacing"
|
android:paddingRight="@dimen/very_large_spacing"
|
||||||
|
android:paddingBottom="@dimen/medium_spacing"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<color name="app_icon_background">#333132</color>
|
<color name="app_icon_background">#333132</color>
|
||||||
<color name="progress_bar_background">#0AFFFFFF</color>
|
<color name="progress_bar_background">#0A000000</color>
|
||||||
<color name="quote_not_found_background">#99FFFFFF</color>
|
<color name="quote_not_found_background">#99FFFFFF</color>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -11,4 +11,14 @@
|
|||||||
<item name="android:textColor">@android:color/white</item>
|
<item name="android:textColor">@android:color/white</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="FakeChatViewMessageBubble.Incoming">
|
||||||
|
<item name="android:background">@drawable/fake_chat_view_incoming_message_background</item>
|
||||||
|
<item name="android:elevation">4dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="FakeChatViewMessageBubble.Outgoing">
|
||||||
|
<item name="android:background">@drawable/fake_chat_view_outgoing_message_background</item>
|
||||||
|
<item name="android:elevation">4dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -25,6 +25,7 @@
|
|||||||
<color name="compose_text_view_background">#141414</color>
|
<color name="compose_text_view_background">#141414</color>
|
||||||
<color name="quote_not_found_background">#99FFFFFF</color>
|
<color name="quote_not_found_background">#99FFFFFF</color>
|
||||||
<color name="new_conversation_button_collapsed_background">#1F1F1F</color>
|
<color name="new_conversation_button_collapsed_background">#1F1F1F</color>
|
||||||
|
<color name="new_conversation_button_shadow">#077C44</color>
|
||||||
<color name="pn_option_background">#1B1B1B</color>
|
<color name="pn_option_background">#1B1B1B</color>
|
||||||
<color name="pn_option_border">#212121</color>
|
<color name="pn_option_border">#212121</color>
|
||||||
<color name="paths_building">#FFCE3A</color>
|
<color name="paths_building">#FFCE3A</color>
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<dimen name="text_view_corner_radius">8dp</dimen>
|
<dimen name="text_view_corner_radius">8dp</dimen>
|
||||||
<dimen name="fake_chat_view_bubble_width">224dp</dimen>
|
<dimen name="fake_chat_view_bubble_width">224dp</dimen>
|
||||||
<dimen name="fake_chat_view_bubble_corner_radius">10dp</dimen>
|
<dimen name="fake_chat_view_bubble_corner_radius">10dp</dimen>
|
||||||
<dimen name="fake_chat_view_height">234dp</dimen>
|
<dimen name="fake_chat_view_height">250dp</dimen>
|
||||||
<dimen name="setting_button_height">56dp</dimen>
|
<dimen name="setting_button_height">56dp</dimen>
|
||||||
<dimen name="dialog_corner_radius">12dp</dimen>
|
<dimen name="dialog_corner_radius">12dp</dimen>
|
||||||
<dimen name="dialog_button_corner_radius">4dp</dimen>
|
<dimen name="dialog_button_corner_radius">4dp</dimen>
|
||||||
|
@ -1864,5 +1864,6 @@
|
|||||||
|
|
||||||
<string name="attachment">Attachment</string>
|
<string name="attachment">Attachment</string>
|
||||||
<string name="attachment_type_voice_message">Voice Message</string>
|
<string name="attachment_type_voice_message">Voice Message</string>
|
||||||
|
<string name="details">Details</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -184,10 +184,12 @@
|
|||||||
|
|
||||||
<style name="FakeChatViewMessageBubble.Incoming">
|
<style name="FakeChatViewMessageBubble.Incoming">
|
||||||
<item name="android:background">@drawable/fake_chat_view_incoming_message_background</item>
|
<item name="android:background">@drawable/fake_chat_view_incoming_message_background</item>
|
||||||
|
<item name="android:elevation">10dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="FakeChatViewMessageBubble.Outgoing">
|
<style name="FakeChatViewMessageBubble.Outgoing">
|
||||||
<item name="android:background">@drawable/fake_chat_view_outgoing_message_background</item>
|
<item name="android:background">@drawable/fake_chat_view_outgoing_message_background</item>
|
||||||
|
<item name="android:elevation">10dp</item>
|
||||||
</style>
|
</style>
|
||||||
<!-- Session -->
|
<!-- Session -->
|
||||||
|
|
||||||
|
@ -160,6 +160,7 @@ import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
|
|||||||
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
||||||
import org.thoughtcrime.securesms.loki.views.MentionCandidateSelectionView;
|
import org.thoughtcrime.securesms.loki.views.MentionCandidateSelectionView;
|
||||||
|
import org.thoughtcrime.securesms.loki.views.ProfilePictureView;
|
||||||
import org.thoughtcrime.securesms.loki.views.SessionRestoreBannerView;
|
import org.thoughtcrime.securesms.loki.views.SessionRestoreBannerView;
|
||||||
import org.thoughtcrime.securesms.mediasend.Media;
|
import org.thoughtcrime.securesms.mediasend.Media;
|
||||||
import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
|
import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
|
||||||
@ -234,6 +235,7 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -300,6 +302,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
private AnimatingToggle buttonToggle;
|
private AnimatingToggle buttonToggle;
|
||||||
private SendButton sendButton;
|
private SendButton sendButton;
|
||||||
private ImageButton attachButton;
|
private ImageButton attachButton;
|
||||||
|
private ProfilePictureView profilePictureView;
|
||||||
private TextView titleTextView;
|
private TextView titleTextView;
|
||||||
private TextView charactersLeft;
|
private TextView charactersLeft;
|
||||||
private ConversationFragment fragment;
|
private ConversationFragment fragment;
|
||||||
@ -527,6 +530,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
composeText.setTransport(sendButton.getSelectedTransport());
|
composeText.setTransport(sendButton.getSelectedTransport());
|
||||||
|
|
||||||
updateTitleTextView(recipient);
|
updateTitleTextView(recipient);
|
||||||
|
updateProfilePicture();
|
||||||
updateSubtitleTextView();
|
updateSubtitleTextView();
|
||||||
setActionBarColor(recipient.getColor());
|
setActionBarColor(recipient.getColor());
|
||||||
updateInputUI(recipient, isSecureText, isDefaultSms);
|
updateInputUI(recipient, isSecureText, isDefaultSms);
|
||||||
@ -621,6 +625,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
recipient = Recipient.from(this, data.getParcelableExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA), true);
|
recipient = Recipient.from(this, data.getParcelableExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA), true);
|
||||||
recipient.addListener(this);
|
recipient.addListener(this);
|
||||||
updateTitleTextView(recipient);
|
updateTitleTextView(recipient);
|
||||||
|
updateProfilePicture();
|
||||||
updateSubtitleTextView();
|
updateSubtitleTextView();
|
||||||
NotificationChannels.updateContactChannelName(this, recipient);
|
NotificationChannels.updateContactChannelName(this, recipient);
|
||||||
updateInputUI(recipient, isSecureText, isDefaultSms);
|
updateInputUI(recipient, isSecureText, isDefaultSms);
|
||||||
@ -1654,6 +1659,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializeViews() {
|
private void initializeViews() {
|
||||||
|
profilePictureView = findViewById(R.id.profilePictureView);
|
||||||
titleTextView = findViewById(R.id.titleTextView);
|
titleTextView = findViewById(R.id.titleTextView);
|
||||||
buttonToggle = ViewUtil.findById(this, R.id.button_toggle);
|
buttonToggle = ViewUtil.findById(this, R.id.button_toggle);
|
||||||
sendButton = ViewUtil.findById(this, R.id.send_button);
|
sendButton = ViewUtil.findById(this, R.id.send_button);
|
||||||
@ -1872,6 +1878,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
Util.runOnMain(() -> {
|
Util.runOnMain(() -> {
|
||||||
Log.i(TAG, "onModifiedRun(): " + recipient.getRegistered());
|
Log.i(TAG, "onModifiedRun(): " + recipient.getRegistered());
|
||||||
updateTitleTextView(recipient);
|
updateTitleTextView(recipient);
|
||||||
|
updateProfilePicture();
|
||||||
updateSubtitleTextView();
|
updateSubtitleTextView();
|
||||||
// titleView.setVerified(identityRecords.isVerified());
|
// titleView.setVerified(identityRecords.isVerified());
|
||||||
updateInputUI(recipient, isSecureText, isDefaultSms);
|
updateInputUI(recipient, isSecureText, isDefaultSms);
|
||||||
@ -3100,6 +3107,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateProfilePicture() {
|
||||||
|
profilePictureView.glide = GlideApp.with(this);
|
||||||
|
profilePictureView.update(recipient, threadId);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateSubtitleTextView() {
|
private void updateSubtitleTextView() {
|
||||||
muteIndicatorImageView.setVisibility(View.GONE);
|
muteIndicatorImageView.setVisibility(View.GONE);
|
||||||
subtitleTextView.setVisibility(View.VISIBLE);
|
subtitleTextView.setVisibility(View.VISIBLE);
|
||||||
|
@ -34,6 +34,7 @@ import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob
|
|||||||
import org.thoughtcrime.securesms.loki.dialogs.ConversationOptionsBottomSheet
|
import org.thoughtcrime.securesms.loki.dialogs.ConversationOptionsBottomSheet
|
||||||
import org.thoughtcrime.securesms.loki.dialogs.LightThemeFeatureIntroBottomSheet
|
import org.thoughtcrime.securesms.loki.dialogs.LightThemeFeatureIntroBottomSheet
|
||||||
import org.thoughtcrime.securesms.loki.dialogs.MultiDeviceRemovalBottomSheet
|
import org.thoughtcrime.securesms.loki.dialogs.MultiDeviceRemovalBottomSheet
|
||||||
|
import org.thoughtcrime.securesms.loki.dialogs.UserDetailsBottomSheet
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
|
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
|
||||||
import org.thoughtcrime.securesms.loki.utilities.*
|
import org.thoughtcrime.securesms.loki.utilities.*
|
||||||
@ -100,6 +101,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
|||||||
profileButton.publicKey = publicKey
|
profileButton.publicKey = publicKey
|
||||||
profileButton.update()
|
profileButton.update()
|
||||||
profileButton.setOnClickListener { openSettings() }
|
profileButton.setOnClickListener { openSettings() }
|
||||||
|
pathStatusViewContainer.disableClipping()
|
||||||
pathStatusViewContainer.setOnClickListener { showPath() }
|
pathStatusViewContainer.setOnClickListener { showPath() }
|
||||||
// Set up seed reminder view
|
// Set up seed reminder view
|
||||||
val isMasterDevice = (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == null)
|
val isMasterDevice = (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == null)
|
||||||
@ -271,6 +273,14 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
|||||||
val thread = view.thread ?: return
|
val thread = view.thread ?: return
|
||||||
val bottomSheet = ConversationOptionsBottomSheet()
|
val bottomSheet = ConversationOptionsBottomSheet()
|
||||||
bottomSheet.recipient = thread.recipient
|
bottomSheet.recipient = thread.recipient
|
||||||
|
bottomSheet.onViewDetailsTapped = {
|
||||||
|
bottomSheet.dismiss()
|
||||||
|
val userDetailsBottomSheet = UserDetailsBottomSheet()
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putString("publicKey", thread.recipient.address.toPhoneString())
|
||||||
|
userDetailsBottomSheet.arguments = bundle
|
||||||
|
userDetailsBottomSheet.show(supportFragmentManager, userDetailsBottomSheet.tag)
|
||||||
|
}
|
||||||
bottomSheet.onBlockTapped = {
|
bottomSheet.onBlockTapped = {
|
||||||
bottomSheet.dismiss()
|
bottomSheet.dismiss()
|
||||||
if (!thread.recipient.isBlocked) {
|
if (!thread.recipient.isBlocked) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.loki.activities
|
package org.thoughtcrime.securesms.loki.activities
|
||||||
|
|
||||||
|
import android.animation.ArgbEvaluator
|
||||||
|
import android.animation.ValueAnimator
|
||||||
import android.app.AlertDialog
|
import android.app.AlertDialog
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.drawable.TransitionDrawable
|
import android.graphics.drawable.TransitionDrawable
|
||||||
@ -9,27 +11,36 @@ import androidx.annotation.DrawableRes
|
|||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.ColorRes
|
||||||
import kotlinx.android.synthetic.main.activity_display_name.registerButton
|
import kotlinx.android.synthetic.main.activity_display_name.registerButton
|
||||||
import kotlinx.android.synthetic.main.activity_pn_mode.*
|
import kotlinx.android.synthetic.main.activity_pn_mode.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.disableClipping
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
|
||||||
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
|
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
|
||||||
import org.thoughtcrime.securesms.loki.utilities.show
|
import org.thoughtcrime.securesms.loki.utilities.show
|
||||||
|
import org.thoughtcrime.securesms.loki.views.GlowViewUtilities
|
||||||
|
import org.thoughtcrime.securesms.loki.views.PNModeView
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
|
|
||||||
class PNModeActivity : BaseActionBarActivity() {
|
class PNModeActivity : BaseActionBarActivity() {
|
||||||
private var selectedOptionView: LinearLayout? = null
|
private var selectedOptionView: PNModeView? = null
|
||||||
|
|
||||||
// region Lifecycle
|
// region Lifecycle
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setUpActionBarSessionLogo()
|
setUpActionBarSessionLogo()
|
||||||
setContentView(R.layout.activity_pn_mode)
|
setContentView(R.layout.activity_pn_mode)
|
||||||
|
contentView.disableClipping()
|
||||||
fcmOptionView.setOnClickListener { toggleFCM() }
|
fcmOptionView.setOnClickListener { toggleFCM() }
|
||||||
|
fcmOptionView.mainColor = resources.getColorWithID(R.color.pn_option_background, theme)
|
||||||
|
fcmOptionView.strokeColor = resources.getColorWithID(R.color.pn_option_border, theme)
|
||||||
backgroundPollingOptionView.setOnClickListener { toggleBackgroundPolling() }
|
backgroundPollingOptionView.setOnClickListener { toggleBackgroundPolling() }
|
||||||
|
backgroundPollingOptionView.mainColor = resources.getColorWithID(R.color.pn_option_background, theme)
|
||||||
|
backgroundPollingOptionView.strokeColor = resources.getColorWithID(R.color.pn_option_border, theme)
|
||||||
registerButton.setOnClickListener { register() }
|
registerButton.setOnClickListener { register() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,15 +82,23 @@ class PNModeActivity : BaseActionBarActivity() {
|
|||||||
when (selectedOptionView) {
|
when (selectedOptionView) {
|
||||||
null -> {
|
null -> {
|
||||||
performTransition(R.drawable.pn_option_background_select_transition, fcmOptionView)
|
performTransition(R.drawable.pn_option_background_select_transition, fcmOptionView)
|
||||||
|
GlowViewUtilities.animateShadowColorChange(this, fcmOptionView, R.color.transparent, R.color.accent)
|
||||||
|
animateStrokeColorChange(fcmOptionView, R.color.pn_option_border, R.color.accent)
|
||||||
selectedOptionView = fcmOptionView
|
selectedOptionView = fcmOptionView
|
||||||
}
|
}
|
||||||
fcmOptionView -> {
|
fcmOptionView -> {
|
||||||
performTransition(R.drawable.pn_option_background_deselect_transition, fcmOptionView)
|
performTransition(R.drawable.pn_option_background_deselect_transition, fcmOptionView)
|
||||||
|
GlowViewUtilities.animateShadowColorChange(this, fcmOptionView, R.color.accent, R.color.transparent)
|
||||||
|
animateStrokeColorChange(fcmOptionView, R.color.accent, R.color.pn_option_border)
|
||||||
selectedOptionView = null
|
selectedOptionView = null
|
||||||
}
|
}
|
||||||
backgroundPollingOptionView -> {
|
backgroundPollingOptionView -> {
|
||||||
performTransition(R.drawable.pn_option_background_select_transition, fcmOptionView)
|
performTransition(R.drawable.pn_option_background_select_transition, fcmOptionView)
|
||||||
|
GlowViewUtilities.animateShadowColorChange(this, fcmOptionView, R.color.transparent, R.color.accent)
|
||||||
|
animateStrokeColorChange(fcmOptionView, R.color.pn_option_border, R.color.accent)
|
||||||
performTransition(R.drawable.pn_option_background_deselect_transition, backgroundPollingOptionView)
|
performTransition(R.drawable.pn_option_background_deselect_transition, backgroundPollingOptionView)
|
||||||
|
GlowViewUtilities.animateShadowColorChange(this, backgroundPollingOptionView, R.color.accent, R.color.transparent)
|
||||||
|
animateStrokeColorChange(backgroundPollingOptionView, R.color.accent, R.color.pn_option_border)
|
||||||
selectedOptionView = fcmOptionView
|
selectedOptionView = fcmOptionView
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,20 +108,40 @@ class PNModeActivity : BaseActionBarActivity() {
|
|||||||
when (selectedOptionView) {
|
when (selectedOptionView) {
|
||||||
null -> {
|
null -> {
|
||||||
performTransition(R.drawable.pn_option_background_select_transition, backgroundPollingOptionView)
|
performTransition(R.drawable.pn_option_background_select_transition, backgroundPollingOptionView)
|
||||||
|
GlowViewUtilities.animateShadowColorChange(this, backgroundPollingOptionView, R.color.transparent, R.color.accent)
|
||||||
|
animateStrokeColorChange(backgroundPollingOptionView, R.color.pn_option_border, R.color.accent)
|
||||||
selectedOptionView = backgroundPollingOptionView
|
selectedOptionView = backgroundPollingOptionView
|
||||||
}
|
}
|
||||||
backgroundPollingOptionView -> {
|
backgroundPollingOptionView -> {
|
||||||
performTransition(R.drawable.pn_option_background_deselect_transition, backgroundPollingOptionView)
|
performTransition(R.drawable.pn_option_background_deselect_transition, backgroundPollingOptionView)
|
||||||
|
GlowViewUtilities.animateShadowColorChange(this, backgroundPollingOptionView, R.color.accent, R.color.transparent)
|
||||||
|
animateStrokeColorChange(backgroundPollingOptionView, R.color.accent, R.color.pn_option_border)
|
||||||
selectedOptionView = null
|
selectedOptionView = null
|
||||||
}
|
}
|
||||||
fcmOptionView -> {
|
fcmOptionView -> {
|
||||||
performTransition(R.drawable.pn_option_background_select_transition, backgroundPollingOptionView)
|
performTransition(R.drawable.pn_option_background_select_transition, backgroundPollingOptionView)
|
||||||
|
GlowViewUtilities.animateShadowColorChange(this, backgroundPollingOptionView, R.color.transparent, R.color.accent)
|
||||||
|
animateStrokeColorChange(backgroundPollingOptionView, R.color.pn_option_border, R.color.accent)
|
||||||
performTransition(R.drawable.pn_option_background_deselect_transition, fcmOptionView)
|
performTransition(R.drawable.pn_option_background_deselect_transition, fcmOptionView)
|
||||||
|
GlowViewUtilities.animateShadowColorChange(this, fcmOptionView, R.color.accent, R.color.transparent)
|
||||||
|
animateStrokeColorChange(fcmOptionView, R.color.accent, R.color.pn_option_border)
|
||||||
selectedOptionView = backgroundPollingOptionView
|
selectedOptionView = backgroundPollingOptionView
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun animateStrokeColorChange(bubble: PNModeView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
|
||||||
|
val startColor = resources.getColorWithID(startColorID, theme)
|
||||||
|
val endColor = resources.getColorWithID(endColorID, theme)
|
||||||
|
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
|
||||||
|
animation.duration = 250
|
||||||
|
animation.addUpdateListener { animator ->
|
||||||
|
val color = animator.animatedValue as Int
|
||||||
|
bubble.strokeColor = color
|
||||||
|
}
|
||||||
|
animation.start()
|
||||||
|
}
|
||||||
|
|
||||||
private fun register() {
|
private fun register() {
|
||||||
if (selectedOptionView == null) {
|
if (selectedOptionView == null) {
|
||||||
val dialog = AlertDialog.Builder(this)
|
val dialog = AlertDialog.Builder(this)
|
||||||
@ -111,7 +150,6 @@ class PNModeActivity : BaseActionBarActivity() {
|
|||||||
dialog.create().show()
|
dialog.create().show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val displayName = TextSecurePreferences.getProfileName(this)
|
|
||||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
|
TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
|
||||||
TextSecurePreferences.setPromptedPushRegistration(this, true)
|
TextSecurePreferences.setPromptedPushRegistration(this, true)
|
||||||
TextSecurePreferences.setIsUsingFCM(this, (selectedOptionView == fcmOptionView))
|
TextSecurePreferences.setIsUsingFCM(this, (selectedOptionView == fcmOptionView))
|
||||||
|
@ -16,10 +16,13 @@ import android.widget.LinearLayout
|
|||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.ColorRes
|
||||||
import kotlinx.android.synthetic.main.activity_path.*
|
import kotlinx.android.synthetic.main.activity_path.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.loki.utilities.*
|
import org.thoughtcrime.securesms.loki.utilities.*
|
||||||
|
import org.thoughtcrime.securesms.loki.views.GlowViewUtilities
|
||||||
|
import org.thoughtcrime.securesms.loki.views.PathDotView
|
||||||
import org.whispersystems.signalservice.loki.api.Snode
|
import org.whispersystems.signalservice.loki.api.Snode
|
||||||
import org.whispersystems.signalservice.loki.api.onionrequests.OnionRequestAPI
|
import org.whispersystems.signalservice.loki.api.onionrequests.OnionRequestAPI
|
||||||
|
|
||||||
@ -31,6 +34,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
super.onCreate(savedInstanceState, isReady)
|
super.onCreate(savedInstanceState, isReady)
|
||||||
setContentView(R.layout.activity_path)
|
setContentView(R.layout.activity_path)
|
||||||
supportActionBar!!.title = resources.getString(R.string.activity_path_title)
|
supportActionBar!!.title = resources.getString(R.string.activity_path_title)
|
||||||
|
pathRowsContainer.disableClipping()
|
||||||
learnMoreButton.setOnClickListener { learnMore() }
|
learnMoreButton.setOnClickListener { learnMore() }
|
||||||
update(false)
|
update(false)
|
||||||
registerObservers()
|
registerObservers()
|
||||||
@ -111,6 +115,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
val mainContainer = LinearLayout(this)
|
val mainContainer = LinearLayout(this)
|
||||||
mainContainer.orientation = LinearLayout.HORIZONTAL
|
mainContainer.orientation = LinearLayout.HORIZONTAL
|
||||||
mainContainer.gravity = Gravity.CENTER_VERTICAL
|
mainContainer.gravity = Gravity.CENTER_VERTICAL
|
||||||
|
mainContainer.disableClipping()
|
||||||
val mainContainerLayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
val mainContainerLayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||||
mainContainer.layoutParams = mainContainerLayoutParams
|
mainContainer.layoutParams = mainContainerLayoutParams
|
||||||
val lineView = LineView(this, location, dotAnimationStartDelay, dotAnimationRepeatInterval)
|
val lineView = LineView(this, location, dotAnimationStartDelay, dotAnimationRepeatInterval)
|
||||||
@ -170,8 +175,9 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
private var dotAnimationRepeatInterval: Long = 0
|
private var dotAnimationRepeatInterval: Long = 0
|
||||||
|
|
||||||
private val dotView by lazy {
|
private val dotView by lazy {
|
||||||
val result = View(context)
|
val result = PathDotView(context)
|
||||||
result.setBackgroundResource(R.drawable.accent_dot)
|
result.setBackgroundResource(R.drawable.accent_dot)
|
||||||
|
result.mainColor = resources.getColorWithID(R.color.accent, context.theme)
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +209,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpViewHierarchy() {
|
private fun setUpViewHierarchy() {
|
||||||
|
disableClipping()
|
||||||
val lineView = View(context)
|
val lineView = View(context)
|
||||||
lineView.setBackgroundColor(resources.getColorWithID(R.color.text, context.theme))
|
lineView.setBackgroundColor(resources.getColorWithID(R.color.text, context.theme))
|
||||||
val lineViewHeight = when (location) {
|
val lineViewHeight = when (location) {
|
||||||
@ -239,10 +246,14 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
|
|
||||||
private fun expand() {
|
private fun expand() {
|
||||||
dotView.animateSizeChange(R.dimen.path_row_dot_size, R.dimen.path_row_expanded_dot_size)
|
dotView.animateSizeChange(R.dimen.path_row_dot_size, R.dimen.path_row_expanded_dot_size)
|
||||||
|
@ColorRes val startColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
|
||||||
|
GlowViewUtilities.animateShadowColorChange(context, dotView, startColorID, R.color.accent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun collapse() {
|
private fun collapse() {
|
||||||
dotView.animateSizeChange(R.dimen.path_row_expanded_dot_size, R.dimen.path_row_dot_size)
|
dotView.animateSizeChange(R.dimen.path_row_expanded_dot_size, R.dimen.path_row_dot_size)
|
||||||
|
@ColorRes val endColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
|
||||||
|
GlowViewUtilities.animateShadowColorChange(context, dotView, R.color.accent, endColorID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -20,6 +20,7 @@ public class ConversationOptionsBottomSheet : BottomSheetDialogFragment() {
|
|||||||
// if we want to use dialog fragments properly.
|
// if we want to use dialog fragments properly.
|
||||||
lateinit var recipient: Recipient
|
lateinit var recipient: Recipient
|
||||||
|
|
||||||
|
var onViewDetailsTapped: (() -> Unit?)? = null
|
||||||
var onBlockTapped: (() -> Unit)? = null
|
var onBlockTapped: (() -> Unit)? = null
|
||||||
var onUnblockTapped: (() -> Unit)? = null
|
var onUnblockTapped: (() -> Unit)? = null
|
||||||
var onDeleteTapped: (() -> Unit)? = null
|
var onDeleteTapped: (() -> Unit)? = null
|
||||||
@ -30,18 +31,16 @@ public class ConversationOptionsBottomSheet : BottomSheetDialogFragment() {
|
|||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
if (!this::recipient.isInitialized) { return dismiss() }
|
||||||
if (!this::recipient.isInitialized) {
|
|
||||||
dismiss()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!recipient.isGroupRecipient && !recipient.isLocalNumber) {
|
if (!recipient.isGroupRecipient && !recipient.isLocalNumber) {
|
||||||
|
detailsTextView.visibility = View.VISIBLE
|
||||||
unblockTextView.visibility = if (recipient.isBlocked) View.VISIBLE else View.GONE
|
unblockTextView.visibility = if (recipient.isBlocked) View.VISIBLE else View.GONE
|
||||||
blockTextView.visibility = if (recipient.isBlocked) View.GONE else View.VISIBLE
|
blockTextView.visibility = if (recipient.isBlocked) View.GONE else View.VISIBLE
|
||||||
|
detailsTextView.setOnClickListener { onViewDetailsTapped?.invoke() }
|
||||||
blockTextView.setOnClickListener { onBlockTapped?.invoke() }
|
blockTextView.setOnClickListener { onBlockTapped?.invoke() }
|
||||||
unblockTextView.setOnClickListener { onUnblockTapped?.invoke() }
|
unblockTextView.setOnClickListener { onUnblockTapped?.invoke() }
|
||||||
|
} else {
|
||||||
|
detailsTextView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
deleteTextView.setOnClickListener { onDeleteTapped?.invoke() }
|
deleteTextView.setOnClickListener { onDeleteTapped?.invoke() }
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package org.thoughtcrime.securesms.loki.dialogs
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
|
import kotlinx.android.synthetic.main.fragment_user_details_bottom_sheet.*
|
||||||
|
import kotlinx.android.synthetic.main.view_conversation.view.*
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideApp
|
||||||
|
|
||||||
|
public class UserDetailsBottomSheet : BottomSheetDialogFragment() {
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
return inflater.inflate(R.layout.fragment_user_details_bottom_sheet, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
val publicKey = arguments?.getString("publicKey") ?: return dismiss()
|
||||||
|
profilePictureView.publicKey = publicKey
|
||||||
|
profilePictureView.glide = GlideApp.with(this)
|
||||||
|
profilePictureView.isLarge = true
|
||||||
|
profilePictureView.update()
|
||||||
|
nameTextView.text = DatabaseFactory.getLokiUserDatabase(requireContext()).getDisplayName(publicKey) ?: "Anonymous"
|
||||||
|
publicKeyTextView.text = publicKey
|
||||||
|
copyButton.setOnClickListener {
|
||||||
|
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
val clip = ClipData.newPlainText("Session ID", publicKey)
|
||||||
|
clipboard.setPrimaryClip(clip)
|
||||||
|
Toast.makeText(requireContext(), R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -55,30 +55,8 @@ class ConversationView : LinearLayout {
|
|||||||
accentView.setBackgroundResource(R.color.accent)
|
accentView.setBackgroundResource(R.color.accent)
|
||||||
accentView.visibility = if (thread.unreadCount > 0) View.VISIBLE else View.INVISIBLE
|
accentView.visibility = if (thread.unreadCount > 0) View.VISIBLE else View.INVISIBLE
|
||||||
}
|
}
|
||||||
if (thread.recipient.isGroupRecipient) {
|
|
||||||
if ("Session Public Chat" == thread.recipient.name) {
|
|
||||||
profilePictureView.publicKey = ""
|
|
||||||
profilePictureView.additionalPublicKey = null
|
|
||||||
profilePictureView.isRSSFeed = true
|
|
||||||
} else {
|
|
||||||
val users = MentionsManager.shared.userPublicKeyCache[thread.threadId]?.toMutableList() ?: mutableListOf()
|
|
||||||
users.remove(TextSecurePreferences.getLocalNumber(context))
|
|
||||||
val masterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
|
|
||||||
if (masterPublicKey != null) {
|
|
||||||
users.remove(masterPublicKey)
|
|
||||||
}
|
|
||||||
val randomUsers = users.sorted() // Sort to provide a level of stability
|
|
||||||
profilePictureView.publicKey = randomUsers.getOrNull(0) ?: ""
|
|
||||||
profilePictureView.additionalPublicKey = randomUsers.getOrNull(1) ?: ""
|
|
||||||
profilePictureView.isRSSFeed = thread.recipient.name == "Loki News" || thread.recipient.name == "Session Updates"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
profilePictureView.publicKey = thread.recipient.address.toString()
|
|
||||||
profilePictureView.additionalPublicKey = null
|
|
||||||
profilePictureView.isRSSFeed = false
|
|
||||||
}
|
|
||||||
profilePictureView.glide = glide
|
profilePictureView.glide = glide
|
||||||
profilePictureView.update()
|
profilePictureView.update(thread.recipient, thread.threadId)
|
||||||
val senderDisplayName = if (thread.recipient.isLocalNumber) context.getString(R.string.note_to_self) else if (!thread.recipient.name.isNullOrEmpty()) thread.recipient.name else thread.recipient.address.toString()
|
val senderDisplayName = if (thread.recipient.isLocalNumber) context.getString(R.string.note_to_self) else if (!thread.recipient.name.isNullOrEmpty()) thread.recipient.name else thread.recipient.address.toString()
|
||||||
btnGroupNameDisplay.text = senderDisplayName
|
btnGroupNameDisplay.text = senderDisplayName
|
||||||
timestampTextView.text = DateUtils.getBriefRelativeTimeSpanString(context, Locale.getDefault(), thread.date)
|
timestampTextView.text = DateUtils.getBriefRelativeTimeSpanString(context, Locale.getDefault(), thread.date)
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
package org.thoughtcrime.securesms.loki.views
|
package org.thoughtcrime.securesms.loki.views
|
||||||
|
|
||||||
|
import android.animation.FloatEvaluator
|
||||||
|
import android.animation.ValueAnimator
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Context.LAYOUT_INFLATER_SERVICE
|
import android.content.Context.LAYOUT_INFLATER_SERVICE
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.LinearLayout
|
||||||
import android.widget.ScrollView
|
import android.widget.ScrollView
|
||||||
import kotlinx.android.synthetic.main.view_fake_chat.view.*
|
import kotlinx.android.synthetic.main.view_fake_chat.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.disableClipping
|
||||||
|
|
||||||
class FakeChatView : ScrollView {
|
class FakeChatView : ScrollView {
|
||||||
|
|
||||||
@ -38,7 +42,8 @@ class FakeChatView : ScrollView {
|
|||||||
|
|
||||||
private fun setUpViewHierarchy() {
|
private fun setUpViewHierarchy() {
|
||||||
val inflater = context.getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
val inflater = context.getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||||
val contentView = inflater.inflate(R.layout.view_fake_chat, null)
|
val contentView = inflater.inflate(R.layout.view_fake_chat, null) as LinearLayout
|
||||||
|
contentView.disableClipping()
|
||||||
addView(contentView)
|
addView(contentView)
|
||||||
isVerticalScrollBarEnabled = false
|
isVerticalScrollBarEnabled = false
|
||||||
}
|
}
|
||||||
@ -47,8 +52,13 @@ class FakeChatView : ScrollView {
|
|||||||
// region Animation
|
// region Animation
|
||||||
fun startAnimating() {
|
fun startAnimating() {
|
||||||
listOf( bubble1, bubble2, bubble3, bubble4, bubble5 ).forEach { it.alpha = 0.0f }
|
listOf( bubble1, bubble2, bubble3, bubble4, bubble5 ).forEach { it.alpha = 0.0f }
|
||||||
fun show(view: View) {
|
fun show(bubble: View) {
|
||||||
view.animate().alpha(1.0f).setDuration(animationDuration).start()
|
val animation = ValueAnimator.ofObject(FloatEvaluator(), 0.0f, 1.0f)
|
||||||
|
animation.duration = animationDuration
|
||||||
|
animation.addUpdateListener { animator ->
|
||||||
|
bubble.alpha = animator.animatedValue as Float
|
||||||
|
}
|
||||||
|
animation.start()
|
||||||
}
|
}
|
||||||
Handler().postDelayed({
|
Handler().postDelayed({
|
||||||
show(bubble1)
|
show(bubble1)
|
||||||
|
158
src/org/thoughtcrime/securesms/loki/views/GlowView.kt
Normal file
158
src/org/thoughtcrime/securesms/loki/views/GlowView.kt
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
package org.thoughtcrime.securesms.loki.views
|
||||||
|
|
||||||
|
import android.animation.ArgbEvaluator
|
||||||
|
import android.animation.ValueAnimator
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.*
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewOutlineProvider
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.annotation.ColorInt
|
||||||
|
import androidx.annotation.ColorRes
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.toPx
|
||||||
|
|
||||||
|
interface GlowView {
|
||||||
|
var mainColor: Int
|
||||||
|
var sessionShadowColor: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
object GlowViewUtilities {
|
||||||
|
|
||||||
|
fun animateColorChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
|
||||||
|
val startColor = context.resources.getColorWithID(startColorID, context.theme)
|
||||||
|
val endColor = context.resources.getColorWithID(endColorID, context.theme)
|
||||||
|
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
|
||||||
|
animation.duration = 250
|
||||||
|
animation.addUpdateListener { animator ->
|
||||||
|
val color = animator.animatedValue as Int
|
||||||
|
view.mainColor = color
|
||||||
|
}
|
||||||
|
animation.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun animateShadowColorChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
|
||||||
|
val startColor = context.resources.getColorWithID(startColorID, context.theme)
|
||||||
|
val endColor = context.resources.getColorWithID(endColorID, context.theme)
|
||||||
|
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
|
||||||
|
animation.duration = 250
|
||||||
|
animation.addUpdateListener { animator ->
|
||||||
|
val color = animator.animatedValue as Int
|
||||||
|
view.sessionShadowColor = color
|
||||||
|
}
|
||||||
|
animation.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PNModeView : LinearLayout, GlowView {
|
||||||
|
@ColorInt override var mainColor: Int = 0
|
||||||
|
set(newValue) { field = newValue; paint.color = newValue }
|
||||||
|
@ColorInt var strokeColor: Int = 0
|
||||||
|
set(newValue) { field = newValue; strokePaint.color = newValue }
|
||||||
|
@ColorInt override var sessionShadowColor: Int = 0
|
||||||
|
set(newValue) { field = newValue; paint.setShadowLayer(toPx(4, resources).toFloat(), 0.0f, 0.0f, newValue) }
|
||||||
|
|
||||||
|
private val paint: Paint by lazy {
|
||||||
|
val result = Paint()
|
||||||
|
result.style = Paint.Style.FILL
|
||||||
|
result.isAntiAlias = true
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
private val strokePaint: Paint by lazy {
|
||||||
|
val result = Paint()
|
||||||
|
result.style = Paint.Style.STROKE
|
||||||
|
result.isAntiAlias = true
|
||||||
|
result.strokeWidth = toPx(1, resources).toFloat()
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Lifecycle
|
||||||
|
constructor(context: Context) : super(context) { }
|
||||||
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { }
|
||||||
|
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { }
|
||||||
|
|
||||||
|
init {
|
||||||
|
setWillNotDraw(false)
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Updating
|
||||||
|
override fun onDraw(c: Canvas) {
|
||||||
|
val w = width.toFloat()
|
||||||
|
val h = height.toFloat()
|
||||||
|
val r = resources.getDimension(R.dimen.pn_option_corner_radius)
|
||||||
|
c.drawRoundRect(0.0f, 0.0f, w, h, r, r, paint)
|
||||||
|
c.drawRoundRect(0.0f, 0.0f, w, h, r, r, strokePaint)
|
||||||
|
super.onDraw(c)
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
class NewConversationButtonImageView : androidx.appcompat.widget.AppCompatImageView, GlowView {
|
||||||
|
@ColorInt override var mainColor: Int = 0
|
||||||
|
set(newValue) { field = newValue; paint.color = newValue }
|
||||||
|
@ColorInt override var sessionShadowColor: Int = 0
|
||||||
|
set(newValue) { field = newValue; paint.setShadowLayer(toPx(6, resources).toFloat(), 0.0f, 0.0f, newValue) }
|
||||||
|
|
||||||
|
private val paint: Paint by lazy {
|
||||||
|
val result = Paint()
|
||||||
|
result.style = Paint.Style.FILL
|
||||||
|
result.isAntiAlias = true
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Lifecycle
|
||||||
|
constructor(context: Context) : super(context) { }
|
||||||
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { }
|
||||||
|
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { }
|
||||||
|
|
||||||
|
init {
|
||||||
|
setWillNotDraw(false)
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Updating
|
||||||
|
override fun onDraw(c: Canvas) {
|
||||||
|
val w = width.toFloat()
|
||||||
|
val h = height.toFloat()
|
||||||
|
c.drawCircle(w / 2, h / 2, w / 2, paint)
|
||||||
|
super.onDraw(c)
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
class PathDotView : View, GlowView {
|
||||||
|
@ColorInt override var mainColor: Int = 0
|
||||||
|
set(newValue) { field = newValue; paint.color = newValue }
|
||||||
|
@ColorInt override var sessionShadowColor: Int = 0
|
||||||
|
set(newValue) { field = newValue; paint.setShadowLayer(toPx(4, resources).toFloat(), 0.0f, 0.0f, newValue) }
|
||||||
|
|
||||||
|
private val paint: Paint by lazy {
|
||||||
|
val result = Paint()
|
||||||
|
result.style = Paint.Style.FILL
|
||||||
|
result.isAntiAlias = true
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Lifecycle
|
||||||
|
constructor(context: Context) : super(context) { }
|
||||||
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { }
|
||||||
|
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { }
|
||||||
|
|
||||||
|
init {
|
||||||
|
setWillNotDraw(false)
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Updating
|
||||||
|
override fun onDraw(c: Canvas) {
|
||||||
|
val w = width.toFloat()
|
||||||
|
val h = height.toFloat()
|
||||||
|
c.drawCircle(w / 2, h / 2, w / 2, paint)
|
||||||
|
super.onDraw(c)
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
}
|
@ -7,9 +7,7 @@ import android.animation.ValueAnimator
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Context.VIBRATOR_SERVICE
|
import android.content.Context.VIBRATOR_SERVICE
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
import android.graphics.drawable.GradientDrawable
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.VibrationEffect
|
import android.os.VibrationEffect
|
||||||
import android.os.VibrationEffect.DEFAULT_AMPLITUDE
|
import android.os.VibrationEffect.DEFAULT_AMPLITUDE
|
||||||
@ -66,24 +64,25 @@ class NewConversationButtonSetView : RelativeLayout {
|
|||||||
private val collapsedImageViewPosition by lazy { PointF((expandedSize - collapsedSize) / 2, (expandedSize - collapsedSize) / 2) }
|
private val collapsedImageViewPosition by lazy { PointF((expandedSize - collapsedSize) / 2, (expandedSize - collapsedSize) / 2) }
|
||||||
|
|
||||||
private val imageView by lazy {
|
private val imageView by lazy {
|
||||||
val result = ImageView(context)
|
val result = NewConversationButtonImageView(context)
|
||||||
val size = collapsedSize.toInt()
|
val size = collapsedSize.toInt()
|
||||||
result.layoutParams = LayoutParams(size, size)
|
result.layoutParams = LayoutParams(size, size)
|
||||||
result.setBackgroundResource(R.drawable.new_conversation_button_background)
|
result.setBackgroundResource(R.drawable.new_conversation_button_background)
|
||||||
val background = result.background as GradientDrawable
|
@ColorRes val backgroundColorID = if (isMain) R.color.accent else R.color.new_conversation_button_collapsed_background
|
||||||
@ColorRes val backgroundColorID = if (isMain)
|
@ColorRes val shadowColorID = if (isMain) {
|
||||||
R.color.accent else
|
R.color.new_conversation_button_shadow
|
||||||
R.color.new_conversation_button_collapsed_background
|
} else {
|
||||||
background.color = ColorStateList.valueOf(resources.getColorWithID(backgroundColorID, context.theme))
|
if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
|
||||||
|
}
|
||||||
|
result.mainColor = resources.getColorWithID(backgroundColorID, context.theme)
|
||||||
|
result.sessionShadowColor = resources.getColorWithID(shadowColorID, context.theme)
|
||||||
result.scaleType = ImageView.ScaleType.CENTER
|
result.scaleType = ImageView.ScaleType.CENTER
|
||||||
result.setImageResource(iconID)
|
result.setImageResource(iconID)
|
||||||
|
result.imageTintList = if (isMain) {
|
||||||
result.imageTintList = if (isMain)
|
|
||||||
// Always use white icon for the main button.
|
|
||||||
ColorStateList.valueOf(resources.getColorWithID(android.R.color.white, context.theme))
|
ColorStateList.valueOf(resources.getColorWithID(android.R.color.white, context.theme))
|
||||||
else
|
} else {
|
||||||
ColorStateList.valueOf(resources.getColorWithID(R.color.text, context.theme))
|
ColorStateList.valueOf(resources.getColorWithID(R.color.text, context.theme))
|
||||||
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,30 +105,21 @@ class NewConversationButtonSetView : RelativeLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun expand() {
|
fun expand() {
|
||||||
animateImageViewColorChange(R.color.new_conversation_button_collapsed_background, R.color.accent)
|
GlowViewUtilities.animateColorChange(context, imageView, R.color.new_conversation_button_collapsed_background, R.color.accent)
|
||||||
|
@ColorRes val startShadowColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
|
||||||
|
GlowViewUtilities.animateShadowColorChange(context, imageView, startShadowColorID, R.color.new_conversation_button_shadow)
|
||||||
imageView.animateSizeChange(R.dimen.new_conversation_button_collapsed_size, R.dimen.new_conversation_button_expanded_size, animationDuration)
|
imageView.animateSizeChange(R.dimen.new_conversation_button_collapsed_size, R.dimen.new_conversation_button_expanded_size, animationDuration)
|
||||||
animateImageViewPositionChange(collapsedImageViewPosition, expandedImageViewPosition)
|
animateImageViewPositionChange(collapsedImageViewPosition, expandedImageViewPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun collapse() {
|
fun collapse() {
|
||||||
animateImageViewColorChange(R.color.accent, R.color.new_conversation_button_collapsed_background)
|
GlowViewUtilities.animateColorChange(context, imageView, R.color.accent, R.color.new_conversation_button_collapsed_background)
|
||||||
|
@ColorRes val endShadowColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
|
||||||
|
GlowViewUtilities.animateShadowColorChange(context, imageView, R.color.new_conversation_button_shadow, endShadowColorID)
|
||||||
imageView.animateSizeChange(R.dimen.new_conversation_button_expanded_size, R.dimen.new_conversation_button_collapsed_size, animationDuration)
|
imageView.animateSizeChange(R.dimen.new_conversation_button_expanded_size, R.dimen.new_conversation_button_collapsed_size, animationDuration)
|
||||||
animateImageViewPositionChange(expandedImageViewPosition, collapsedImageViewPosition)
|
animateImageViewPositionChange(expandedImageViewPosition, collapsedImageViewPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun animateImageViewColorChange(@ColorRes startColorID: Int, @ColorRes endColorID: Int) {
|
|
||||||
val drawable = imageView.background as GradientDrawable
|
|
||||||
val startColor = resources.getColorWithID(startColorID, context.theme)
|
|
||||||
val endColor = resources.getColorWithID(endColorID, context.theme)
|
|
||||||
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
|
|
||||||
animation.duration = animationDuration
|
|
||||||
animation.addUpdateListener { animator ->
|
|
||||||
val color = animator.animatedValue as Int
|
|
||||||
drawable.color = ColorStateList.valueOf(color)
|
|
||||||
}
|
|
||||||
animation.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun animateImageViewPositionChange(startPosition: PointF, endPosition: PointF) {
|
private fun animateImageViewPositionChange(startPosition: PointF, endPosition: PointF) {
|
||||||
val animation = ValueAnimator.ofObject(PointFEvaluator(), startPosition, endPosition)
|
val animation = ValueAnimator.ofObject(PointFEvaluator(), startPosition, endPosition)
|
||||||
animation.duration = animationDuration
|
animation.duration = animationDuration
|
||||||
@ -170,6 +160,7 @@ class NewConversationButtonSetView : RelativeLayout {
|
|||||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { setUpViewHierarchy() }
|
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { setUpViewHierarchy() }
|
||||||
|
|
||||||
private fun setUpViewHierarchy() {
|
private fun setUpViewHierarchy() {
|
||||||
|
disableClipping()
|
||||||
// Set up session button
|
// Set up session button
|
||||||
addView(sessionButton)
|
addView(sessionButton)
|
||||||
sessionButton.alpha = 0.0f
|
sessionButton.alpha = 0.0f
|
||||||
|
@ -4,14 +4,30 @@ import android.content.BroadcastReceiver
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Paint
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.annotation.ColorInt
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
|
||||||
|
import org.thoughtcrime.securesms.loki.utilities.toPx
|
||||||
import org.whispersystems.signalservice.loki.api.onionrequests.OnionRequestAPI
|
import org.whispersystems.signalservice.loki.api.onionrequests.OnionRequestAPI
|
||||||
|
|
||||||
class PathStatusView : View {
|
class PathStatusView : View {
|
||||||
private val broadcastReceivers = mutableListOf<BroadcastReceiver>()
|
private val broadcastReceivers = mutableListOf<BroadcastReceiver>()
|
||||||
|
@ColorInt var mainColor: Int = 0
|
||||||
|
set(newValue) { field = newValue; paint.color = newValue }
|
||||||
|
@ColorInt var sessionShadowColor: Int = 0
|
||||||
|
set(newValue) { field = newValue; paint.setShadowLayer(toPx(8, resources).toFloat(), 0.0f, 0.0f, newValue) }
|
||||||
|
|
||||||
|
private val paint: Paint by lazy {
|
||||||
|
val result = Paint()
|
||||||
|
result.style = Paint.Style.FILL
|
||||||
|
result.isAntiAlias = true
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
constructor(context: Context) : super(context) {
|
constructor(context: Context) : super(context) {
|
||||||
initialize()
|
initialize()
|
||||||
@ -31,6 +47,7 @@ class PathStatusView : View {
|
|||||||
|
|
||||||
private fun initialize() {
|
private fun initialize() {
|
||||||
update()
|
update()
|
||||||
|
setWillNotDraw(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAttachedToWindow() {
|
override fun onAttachedToWindow() {
|
||||||
@ -70,8 +87,19 @@ class PathStatusView : View {
|
|||||||
private fun update() {
|
private fun update() {
|
||||||
if (OnionRequestAPI.paths.count() >= OnionRequestAPI.pathCount) {
|
if (OnionRequestAPI.paths.count() >= OnionRequestAPI.pathCount) {
|
||||||
setBackgroundResource(R.drawable.accent_dot)
|
setBackgroundResource(R.drawable.accent_dot)
|
||||||
|
mainColor = resources.getColorWithID(R.color.accent, context.theme)
|
||||||
|
sessionShadowColor = resources.getColorWithID(R.color.accent, context.theme)
|
||||||
} else {
|
} else {
|
||||||
setBackgroundResource(R.drawable.paths_building_dot)
|
setBackgroundResource(R.drawable.paths_building_dot)
|
||||||
|
mainColor = resources.getColorWithID(R.color.paths_building, context.theme)
|
||||||
|
sessionShadowColor = resources.getColorWithID(R.color.paths_building, context.theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDraw(c: Canvas) {
|
||||||
|
val w = width.toFloat()
|
||||||
|
val h = height.toFloat()
|
||||||
|
c.drawCircle(w / 2, h / 2, w / 2, paint)
|
||||||
|
super.onDraw(c)
|
||||||
|
}
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ import android.view.View
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
|
import kotlinx.android.synthetic.main.view_conversation.view.*
|
||||||
import kotlinx.android.synthetic.main.view_profile_picture.view.*
|
import kotlinx.android.synthetic.main.view_profile_picture.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto
|
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto
|
||||||
@ -16,6 +17,7 @@ import org.thoughtcrime.securesms.loki.todo.JazzIdenticonDrawable
|
|||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
|
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
|
||||||
|
|
||||||
// TODO: Look into a better way of handling different sizes. Maybe an enum (with associated values) encapsulating the different modes?
|
// TODO: Look into a better way of handling different sizes. Maybe an enum (with associated values) encapsulating the different modes?
|
||||||
|
|
||||||
@ -51,6 +53,32 @@ class ProfilePictureView : RelativeLayout {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Updating
|
// region Updating
|
||||||
|
fun update(recipient: Recipient, threadID: Long) {
|
||||||
|
if (recipient.isGroupRecipient) {
|
||||||
|
if ("Session Public Chat" == recipient.name) {
|
||||||
|
publicKey = ""
|
||||||
|
additionalPublicKey = null
|
||||||
|
isRSSFeed = true
|
||||||
|
} else {
|
||||||
|
val users = MentionsManager.shared.userPublicKeyCache[threadID]?.toMutableList() ?: mutableListOf()
|
||||||
|
users.remove(TextSecurePreferences.getLocalNumber(context))
|
||||||
|
val masterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
|
||||||
|
if (masterPublicKey != null) {
|
||||||
|
users.remove(masterPublicKey)
|
||||||
|
}
|
||||||
|
val randomUsers = users.sorted() // Sort to provide a level of stability
|
||||||
|
publicKey = randomUsers.getOrNull(0) ?: ""
|
||||||
|
additionalPublicKey = randomUsers.getOrNull(1) ?: ""
|
||||||
|
isRSSFeed = recipient.name == "Loki News" || recipient.name == "Session Updates"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
publicKey = recipient.address.toString()
|
||||||
|
additionalPublicKey = null
|
||||||
|
isRSSFeed = false
|
||||||
|
}
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
fun update() {
|
fun update() {
|
||||||
val publicKey = publicKey ?: return
|
val publicKey = publicKey ?: return
|
||||||
val additionalPublicKey = additionalPublicKey
|
val additionalPublicKey = additionalPublicKey
|
||||||
|
Loading…
x
Reference in New Issue
Block a user