Merge branch 'dev' into profile-pictures

This commit is contained in:
nielsandriesse 2020-09-09 13:14:46 +10:00
commit 49d344f7f7
84 changed files with 646 additions and 373 deletions

View File

@ -342,7 +342,8 @@
<activity
android:name="org.thoughtcrime.securesms.PassphrasePromptActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
android:launchMode="singleTask" />
android:launchMode="singleTask"
android:theme="@style/Theme.Session.DayNight.NoActionBar"/>
<activity
android:name="org.thoughtcrime.securesms.NewConversationActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"

View File

@ -1,16 +1,15 @@
import java.security.MessageDigest
buildscript {
ext.kotlin_version = "1.3.31"
ext.kotlin_version = "1.4.0"
ext.kovenant_version = "3.3.0"
repositories {
mavenLocal()
google()
mavenCentral()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:3.4.1"
classpath "com.android.tools.build:gradle:4.0.1"
classpath files('libs/gradle-witness.jar')
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.gms:google-services:4.3.3"
@ -18,8 +17,8 @@ buildscript {
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'witness'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.gms.google-services'
@ -73,14 +72,15 @@ configurations.all {
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.google.android.material:material:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
implementation 'androidx.gridlayout:gridlayout:1.0.0'
implementation 'androidx.exifinterface:exifinterface:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-common-java8:2.2.0'
@ -89,7 +89,6 @@ dependencies {
exclude group: 'com.google.firebase', module: 'firebase-analytics'
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
}
implementation 'com.google.android.exoplayer:exoplayer-core:2.9.1'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.1'
implementation 'org.conscrypt:conscrypt-android:2.0.0'
@ -141,28 +140,6 @@ dependencies {
exclude group: 'com.fasterxml.jackson.core'
exclude group: 'org.freemarker'
}
testImplementation 'junit:junit:4.12'
testImplementation 'org.assertj:assertj-core:3.11.1'
testImplementation 'org.mockito:mockito-core:1.9.5'
testImplementation 'org.powermock:powermock-api-mockito:1.6.1'
testImplementation 'org.powermock:powermock-module-junit4:1.6.1'
testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.1'
testImplementation 'org.powermock:powermock-classloading-xstream:1.6.1'
testImplementation 'androidx.test:core:1.3.0-rc03'
androidTestImplementation 'com.google.dexmaker:dexmaker:1.2'
androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'
androidTestImplementation ('org.assertj:assertj-core:1.7.1') {
exclude group: 'org.hamcrest', module: 'hamcrest-core'
}
androidTestImplementation ('com.squareup.assertj:assertj-android:1.1.1') {
exclude group: 'org.hamcrest', module: 'hamcrest-core'
exclude group: 'com.android.support', module: 'support-annotations'
}
testImplementation 'org.robolectric:robolectric:4.2'
testImplementation 'org.robolectric:shadows-multidex:4.2'
// Loki
// Local:
implementation "org.whispersystems:signal-service-android:2.13.2" // Run ./gradlew install from session-android-service to install
@ -180,10 +157,32 @@ dependencies {
implementation "com.github.tbruyelle:rxpermissions:0.10.2"
implementation "com.github.ybq:Android-SpinKit:1.4.0"
implementation "com.opencsv:opencsv:4.6"
testImplementation 'junit:junit:4.12'
testImplementation 'org.assertj:assertj-core:3.11.1'
testImplementation 'org.mockito:mockito-core:1.9.5'
testImplementation 'org.powermock:powermock-api-mockito:1.6.1'
testImplementation 'org.powermock:powermock-module-junit4:1.6.1'
testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.1'
testImplementation 'org.powermock:powermock-classloading-xstream:1.6.1'
testImplementation 'androidx.test:core:1.3.0'
androidTestImplementation 'androidx.multidex:multidex:2.0.1'
androidTestImplementation 'androidx.multidex:multidex-instrumentation:2.0.0'
androidTestImplementation 'com.google.dexmaker:dexmaker:1.2'
androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'
androidTestImplementation ('org.assertj:assertj-core:1.7.1') {
exclude group: 'org.hamcrest', module: 'hamcrest-core'
}
androidTestImplementation ('com.squareup.assertj:assertj-android:1.1.1') {
exclude group: 'org.hamcrest', module: 'hamcrest-core'
exclude group: 'com.android.support', module: 'support-annotations'
}
testImplementation 'org.robolectric:robolectric:4.2'
testImplementation 'org.robolectric:shadows-multidex:4.2'
}
def canonicalVersionCode = 84
def canonicalVersionName = "1.5.0"
def canonicalVersionCode = 93
def canonicalVersionName = "1.5.2"
def postFixSize = 10
def abiPostFix = ['armeabi-v7a' : 1,
@ -208,9 +207,10 @@ android {
minSdkVersion 21
targetSdkVersion 29
multiDexEnabled true // Even though we're running API 21+, this is still needed for release builds
vectorDrawables.useSupportLibrary = true
project.ext.set("archivesBaseName", "Signal")
project.ext.set("archivesBaseName", "session")
buildConfigField "long", "BUILD_TIMESTAMP", getLastCommitTimestamp() + "L"
buildConfigField "String", "SIGNAL_URL", "\"\""
@ -349,6 +349,7 @@ android {
}
}
/*
def assembleWebsiteDescriptor = { variant, file ->
if (file.exists()) {
MessageDigest md = MessageDigest.getInstance("SHA-256")
@ -372,7 +373,7 @@ def assembleWebsiteDescriptor = { variant, file ->
descriptorFile.write(descriptor)
}
}
/*
def signProductionRelease = { variant ->
variant.outputs.collect { output ->
String apkName = output.outputFile.name

View File

@ -5,5 +5,5 @@ repositories {
}
dependencies {
compile 'com.android.tools.build:apksig:3.3.2'
implementation 'com.android.tools.build:apksig:4.0.1'
}

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1019 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 919 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 846 B

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,14c1.66,0 2.99,-1.34 2.99,-3L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM17.3,11c0,3 -2.54,5.1 -5.3,5.1S6.7,14 6.7,11L5,11c0,3.41 2.72,6.23 6,6.72L11,21h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,7c2.76,0 5,2.24 5,5 0,0.65 -0.13,1.26 -0.36,1.83l2.92,2.92c1.51,-1.26 2.7,-2.89 3.43,-4.75 -1.73,-4.39 -6,-7.5 -11,-7.5 -1.4,0 -2.74,0.25 -3.98,0.7l2.16,2.16C10.74,7.13 11.35,7 12,7zM2,4.27l2.28,2.28 0.46,0.46C3.08,8.3 1.78,10.02 1,12c1.73,4.39 6,7.5 11,7.5 1.55,0 3.03,-0.3 4.38,-0.84l0.42,0.42L19.73,22 21,20.73 3.27,3 2,4.27zM7.53,9.8l1.55,1.55c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.66 1.34,3 3,3 0.22,0 0.44,-0.03 0.65,-0.08l1.55,1.55c-0.67,0.33 -1.41,0.53 -2.2,0.53 -2.76,0 -5,-2.24 -5,-5 0,-0.79 0.2,-1.53 0.53,-2.2zM11.84,9.02l3.15,3.15 0.02,-0.16c0,-1.66 -1.34,-3 -3,-3l-0.17,0.01z"/>
</vector>

View File

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

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/contentView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@ -30,7 +31,7 @@
android:textColor="@color/text"
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:layout_width="match_parent"
android:layout_height="wrap_content"
@ -66,9 +67,9 @@
android:textStyle="bold"
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:layout_width="match_parent"
android:layout_height="wrap_content"
@ -95,7 +96,7 @@
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." />
</LinearLayout>
</org.thoughtcrime.securesms.loki.views.PNModeView>
<View
android:layout_width="match_parent"

View File

@ -23,7 +23,7 @@
android:layout_weight="1" />
<Button
style="@style/Widget.Session.Button.Common.ProminentFilled"
style="@style/Widget.Session.Button.Common.ProminentOutline"
android:id="@+id/joinPublicChatButton"
android:layout_width="196dp"
android:layout_height="@dimen/medium_button_height"

View File

@ -90,7 +90,7 @@
android:layout_weight="1" />
<Button
style="@style/Widget.Session.Button.Common.ProminentFilled"
style="@style/Widget.Session.Button.Common.ProminentOutline"
android:id="@+id/createPrivateChatButton"
android:layout_width="196dp"
android:layout_height="@dimen/medium_button_height"

View File

@ -77,7 +77,8 @@
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:clipChildren="false">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"

View File

@ -23,7 +23,8 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin="@dimen/large_spacing">
android:layout_margin="@dimen/large_spacing"
android:clipChildren="false">
<LinearLayout
android:id="@+id/pathRowsContainer"

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/contentView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@ -30,7 +31,7 @@
android:textColor="@color/text"
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:layout_width="match_parent"
android:layout_height="wrap_content"
@ -66,9 +67,9 @@
android:textStyle="bold"
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:layout_width="match_parent"
android:layout_height="wrap_content"
@ -95,7 +96,7 @@
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." />
</LinearLayout>
</org.thoughtcrime.securesms.loki.views.PNModeView>
<View
android:layout_width="match_parent"

View File

@ -20,9 +20,15 @@
android:gravity="center_vertical"
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
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/medium_spacing"
android:orientation="vertical">
<TextView

View File

@ -9,5 +9,5 @@
android:visibility="gone"
app:doc_titleColor="?conversation_item_sent_text_primary_color"
app:doc_captionColor="?conversation_item_sent_text_secondary_color"
app:doc_downloadButtonTint="?conversation_item_sent_download_icon_color"
app:doc_downloadButtonTint="?android:colorControlNormal"
tools:visibility="visible"/>

View File

@ -21,10 +21,12 @@
android:textSize="@dimen/medium_font_size" />
<TextView
style="@style/SessionIDTextView"
android:id="@+id/seedTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/large_spacing"
android:padding="@dimen/small_spacing"
android:text="habitat kiwi amply iceberg dog nerves spiderman soft match partial awakened maximum degrees"
android:textColor="@color/text"
android:textSize="@dimen/small_font_size"
@ -70,9 +72,9 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/large_spacing"
android:text="@string/dialog_seed_disclaimer"
android:textStyle="bold"
android:textColor="@color/text"
android:textSize="@dimen/very_small_font_size"
android:alpha="0.6"
android:textSize="10sp"
android:textAlignment="center" />
</LinearLayout>

View File

@ -9,6 +9,13 @@
app:behavior_hideable="true"
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
android:id="@+id/blockTextView"
style="@style/BottomSheetActionItem"

View File

@ -9,7 +9,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="?attr/search_background"
android:background="?android:windowBackground"
android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView

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

View File

@ -13,8 +13,7 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical"
android:padding="10dp"
android:background="?attr/invite_background">
android:padding="10dp">
<ImageView android:id="@+id/heart"
android:layout_width="wrap_content"

View File

@ -17,7 +17,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:padding="6dp"
android:src="@drawable/ic_search_white_24dp"
android:src="@drawable/ic_baseline_search_24"
android:tint="?media_keyboard_button_color"
android:background="?selectableItemBackgroundBorderless"
android:visibility="invisible"
@ -98,7 +98,7 @@
android:tint="?media_keyboard_button_color"
android:visibility="gone"
android:background="?selectableItemBackground"
app:srcCompat="@drawable/ic_plus_24"
app:srcCompat="@drawable/ic_baseline_add_24"
app:layout_constraintBottom_toBottomOf="@id/media_keyboard_tabs"
app:layout_constraintTop_toTopOf="@id/media_keyboard_tabs"
app:layout_constraintEnd_toStartOf="@id/media_keyboard_backspace_backup"

View File

@ -6,7 +6,8 @@
android:id="@+id/prompt_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical"
tools:context="org.thoughtcrime.securesms.PassphrasePromptActivity">
<View android:id="@+id/shim"
android:layout_width="match_parent"
@ -25,7 +26,7 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginTop="20dp">
android:layout_alignParentTop="true">
<ImageView
android:layout_width="wrap_content"
@ -78,7 +79,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp"
tools:visibility="gone">
tools:visibility="visible">
<EditText android:id="@+id/passphrase_edit"
android:layout_width="match_parent"
@ -88,7 +89,8 @@
android:layout_marginEnd="50dp"
android:singleLine="true"
android:paddingStart="10dp"
android:paddingEnd="40dp"/>
android:paddingEnd="40dp"
tools:text="password"/>
<org.thoughtcrime.securesms.components.AnimatingToggle
android:id="@+id/button_toggle"
@ -100,7 +102,7 @@
android:gravity="center">
<ImageButton android:id="@+id/passphrase_visibility"
android:src="?ic_visibility"
android:src="?ic_visibility_on"
android:background="@drawable/touch_highlight_background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@ -5,6 +5,7 @@
android:layout_height="wrap_content"
android:paddingLeft="@dimen/very_large_spacing"
android:paddingRight="@dimen/very_large_spacing"
android:paddingBottom="@dimen/medium_spacing"
android:orientation="vertical">
<TextView

View File

@ -28,7 +28,7 @@
<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>
</resources>

View File

@ -11,4 +11,14 @@
<item name="android:textColor">@android:color/white</item>
</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>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<resources>
<style name="Theme.Session.Light" parent="Base.Theme.Session">
<item name="android:navigationBarColor">?android:navigationBarColor</item>
@ -23,6 +23,8 @@
<item name="conversation_input_background">@drawable/compose_background_light</item>
<item name="quick_camera_icon">@drawable/ic_outline_photo_camera_24</item>
<item name="media_keyboard_button_color">@color/core_grey_60</item>
</style>
<style name="Theme.Session.DayNight" parent="Theme.Session.Light">
@ -39,8 +41,6 @@
<item name="alertDialogTheme">@style/AppCompatAlertDialogStyleLight</item>
<item name="android:alertDialogTheme">@style/AppCompatDialogStyleLight</item>
<item name="compose_icon_tint">@color/core_grey_60</item>
<item name="conversation_list_item_background">@drawable/conversation_list_item_background</item>
<item name="conversation_list_item_contact_color">@color/core_grey_90</item>
<item name="conversation_list_item_subject_color">@color/core_grey_60</item>
@ -74,8 +74,6 @@
<item name="conversation_sticker_footer_icon_color">@color/core_grey_60</item>
<item name="conversation_sticker_author_color">@color/core_grey_95</item>
<item name="contact_list_divider">@drawable/contact_list_divider_light</item>
<item name="verification_background">@color/core_grey_05</item>
<item name="emoji_tab_strip_background">@color/cell_background</item>
@ -101,21 +99,13 @@
<item name="conversation_item_sent_text_primary_color">@color/core_grey_90</item>
<item name="conversation_item_sent_text_secondary_color">@color/transparent_black_90</item>
<item name="conversation_item_sent_icon_color">@color/core_grey_60</item>
<item name="conversation_item_sent_download_icon_color">@color/core_grey_60</item>
<item name="conversation_item_sent_text_indicator_tab_color">#99000000</item>
<item name="conversation_item_received_text_primary_color">@color/text</item>
<item name="conversation_item_received_text_secondary_color">@color/text</item>
<item name="conversation_item_update_text_color">@color/core_grey_60</item>
<item name="conversation_item_last_seen_text_color">@color/core_grey_90</item>
<item name="conversation_item_last_seen_line_color">@color/core_grey_60</item>
<item name="conversation_item_date_line_color">@color/core_grey_25</item>
<item name="conversation_item_quote_text_color">@color/core_grey_90</item>
<item name="conversation_item_sticky_date_background">@drawable/sticky_date_header_background_light</item>
<item name="conversation_item_sticky_date_text_color">@color/core_grey_60</item>
<item name="conversation_item_image_outline_color">@color/transparent_black_30</item>
<item name="quick_mic_icon">@drawable/ic_mic_grey600_24dp</item>
<item name="conversation_item_sent_indicator_text_background">@drawable/conversation_item_sent_indicator_text_shape</item>
<item name="dialog_info_icon">@drawable/ic_info_outline_light</item>
@ -124,34 +114,14 @@
<item name="device_link_item_card_background">@color/device_link_item_background_light</item>
<item name="mediapicker_image_outline">@drawable/mediapicker_item_border_light</item>
<item name="import_export_item_background_color">@color/import_export_item_background_light</item>
<item name="import_export_item_background_shadow_color">@color/import_export_item_background_shadow_light</item>
<item name="import_export_item_card_background">@drawable/clickable_card_light</item>
<item name="linkpreview_background_color">@color/core_white</item>
<item name="linkpreview_primary_text_color">@color/core_black</item>
<item name="linkpreview_secondary_text_color">@color/core_grey_60</item>
<item name="linkpreview_divider_color">@color/core_grey_25</item>
<item name="media_keyboard_button_color">@color/core_grey_60</item>
<item name="menu_new_conversation_icon">@drawable/ic_add_white_24dp</item>
<item name="menu_group_icon">@drawable/ic_group_white_24dp</item>
<item name="menu_search_icon">@drawable/ic_search_white_24dp</item>
<item name="menu_call_icon">@drawable/ic_call_white_24dp</item>
<item name="menu_unlock_icon">@drawable/ic_unlocked_white_24dp</item>
<item name="menu_lock_icon">@drawable/ic_lock_white_24dp</item>
<item name="menu_lock_icon_small">@drawable/ic_lock_white_18dp</item>
<item name="menu_refresh_directory">@drawable/ic_refresh_white_24dp</item>
<item name="menu_info_icon">@drawable/ic_info_outline_white_24dp</item>
<item name="conversation_icon_attach_audio">@drawable/ic_audio_light</item>
<item name="conversation_icon_attach_video">@drawable/ic_video_light</item>
<item name="reminder_header_background">#ff1d85d7</item>
<item name="sticker_management_icon">@drawable/sticker_button_light</item>
<item name="sticker_management_divider_color">@color/core_grey_15</item>
<item name="sticker_management_empty_background_color">@color/core_grey_05</item>
@ -165,17 +135,9 @@
<item name="pref_icon_tint">@color/textsecure_primary_dark</item>
<item name="pref_divider">@drawable/preference_divider_light</item>
<item name="quote_missing_icon_color">@color/core_grey_60</item>
<item name="group_members_dialog_icon">@drawable/ic_group_grey600_24dp</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.Fix</item>
<item name="search_toolbar_background">@color/white</item>
<item name="search_background">@color/white</item>
<item name="invite_background">@color/signal_primary</item>
<item name="shared_contact_details_header_background">@color/grey_100</item>
<item name="shared_contact_details_titlebar">@color/grey_400</item>
<item name="shared_contact_item_button_color">@color/core_grey_02</item>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<resources>
<style name="Theme.Session.DayNight" parent="Theme.Session.Light">
<item name="android:statusBarColor">@color/transparent</item>

View File

@ -8,7 +8,7 @@
<dimen name="small_font_size">13sp</dimen>
<dimen name="medium_font_size">15sp</dimen>
<dimen name="large_font_size">20sp</dimen>
<dimen name="very_large_font_size">25sp</dimen>
<dimen name="very_large_font_size">24sp</dimen>
<dimen name="massive_font_size">50sp</dimen>
<!-- Session -->

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<resources>
<style name="Theme.Session.ForceDark" parent="Base.Theme.Session.ForceDark">
<item name="android:windowLightStatusBar">false</item>

View File

@ -19,16 +19,13 @@
<attr name="conversation_list_toolbar_background" format="reference"/>
<attr name="conversation_list_typing_tint" format="color"/>
<attr name="conversation_sent_card_background" format="reference|color"/>
<attr name="conversation_group_member_name" format="reference|color"/>
<attr name="conversation_received_card_background" format="reference|color"/>
<attr name="fab_color" format="reference|color" />
<attr name="lower_right_divet" format="reference" />
<attr name="centered_app_title_color" format="reference|color" />
<attr name="ic_arrow_forward" format="reference" />
<attr name="ic_visibility" format="reference" />
<attr name="ic_visibility_on" format="reference" />
<attr name="ic_visibility_off" format="reference" />
<attr name="conversation_background" format="reference|color"/>
@ -76,9 +73,6 @@
<attr name="quick_camera_icon" format="reference"/>
<attr name="quick_mic_icon" format="reference"/>
<attr name="compose_icon_tint" />
<attr name="conversation_item_background" format="reference"/>
<attr name="conversation_item_bubble_background" format="reference|color"/>
<attr name="conversation_item_sent_text_primary_color" format="reference|color"/>
<attr name="conversation_item_sent_text_secondary_color" format="reference|color"/>
@ -87,12 +81,6 @@
<attr name="conversation_item_sent_text_indicator_tab_color" format="reference|color"/>
<attr name="conversation_item_sent_indicator_text_background" format="reference" />
<attr name="conversation_item_sent_icon_color" format="color" />
<attr name="conversation_item_sent_download_icon_color" format="reference|color"/>
<attr name="conversation_item_update_text_color" format="reference"/>
<attr name="conversation_item_last_seen_text_color" format="reference"/>
<attr name="conversation_item_last_seen_line_color" format="reference"/>
<attr name="conversation_item_date_line_color" format="reference"/>
<attr name="conversation_item_quote_text_color" format="reference"/>
<attr name="conversation_item_sticky_date_background" format="reference" />
<attr name="conversation_item_sticky_date_text_color" format="color" />
<attr name="conversation_item_image_outline_color" format="color" />
@ -104,45 +92,21 @@
<attr name="conversation_icon_attach_audio" format="reference"/>
<attr name="conversation_icon_attach_video" format="reference" />
<attr name="contact_selection_push_user" format="reference|color" />
<attr name="contact_selection_lay_user" format="reference|color" />
<attr name="contact_selection_label_text" format="reference|color" />
<attr name="contact_selection_header_text" format="reference|color" />
<attr name="device_link_item_card_background" format="reference|color" />
<attr name="mediapicker_image_outline" format="reference" />
<attr name="import_export_item_background_color" format="reference|color" />
<attr name="import_export_item_background_shadow_color" format="reference|color" />
<attr name="import_export_item_card_background" format="reference" />
<attr name="invite_background" format="color"/>
<attr name="linkpreview_background_color" format="color" />
<attr name="linkpreview_primary_text_color" format="color" />
<attr name="linkpreview_secondary_text_color" format="color" />
<attr name="linkpreview_divider_color" format="color" />
<attr name="reminder_header_background" format="color"/>
<attr name="media_keyboard_button_color" format="color" />
<attr name="menu_new_conversation_icon" format="reference" />
<attr name="menu_search_icon" format="reference" />
<attr name="menu_call_icon" format="reference" />
<attr name="menu_popup_expand" format="reference"/>
<attr name="menu_unlock_icon" format="reference" />
<attr name="menu_lock_icon" format="reference" />
<attr name="menu_lock_icon_small" format="reference" />
<attr name="menu_trash_icon" format="reference" />
<attr name="menu_selectall_icon" format="reference" />
<attr name="menu_group_icon" format="reference" />
<attr name="menu_split_icon" format="reference" />
<attr name="menu_accept_icon" format="reference" />
<attr name="menu_refresh_directory" format="reference" />
<attr name="menu_copy_icon" format="reference" />
<attr name="menu_info_icon" format="reference" />
<attr name="menu_forward_icon" format="reference" />
<attr name="menu_save_icon" format="reference" />
<attr name="menu_reply_icon" format="reference" />
@ -152,40 +116,23 @@
<attr name="pref_icon_tint" format="color"/>
<attr name="pref_divider" format="reference" />
<attr name="quote_missing_icon_color" format="color" />
<attr name="home_gradient_start" format="color|reference" />
<attr name="home_gradient_end" format="color|reference" />
<attr name="message_received_background_color" format="color|reference" />
<attr name="message_sent_background_color" format="color|reference" />
<declare-styleable name="CustomDefaultPreference">
<attr name="custom_pref_toggle" format="string"/>
</declare-styleable>
<attr name="group_members_dialog_icon" format="reference"/>
<attr name="lockscreen_watermark" format="reference" />
<attr name="recipient_preference_blocked" format="color"/>
<attr name="verification_background" format="color"/>
<attr name="media_overview_toolbar_background" format="color"/>
<attr name="media_overview_toolbar_foreground" format="color"/>
<attr name="media_overview_header_foreground" format="color"/>
<attr name="media_overview_document_primary" format="color"/>
<attr name="media_overview_document_secondary" format="color"/>
<attr name="shared_contact_details_header_background" format="color"/>
<attr name="shared_contact_details_titlebar" format="color"/>
<attr name="shared_contact_item_button_color" format="color"/>
<attr name="search_toolbar_background" format="color"/>
<attr name="search_background" format="color"/>
<attr name="sticker_management_icon" format="reference" />
<attr name="sticker_management_divider_color" format="color" />
<attr name="sticker_management_empty_background_color" format="color" />
@ -197,15 +144,8 @@
<attr name="tooltip_default_color" format="reference|color" />
<attr name="contact_list_divider" format="reference"/>
<attr name="login_top_background" format="color"/>
<attr name="login_floating_background" format="reference"/>
<declare-styleable name="ColorPreference">
<attr name="itemLayout" format="reference" />
<attr name="choices" format="reference" />
<attr name="numColumns" format="integer" />
<declare-styleable name="CustomDefaultPreference">
<attr name="custom_pref_toggle" format="string"/>
</declare-styleable>
<declare-styleable name="AvatarImageView">
@ -270,22 +210,12 @@
<attr name="emoji_maxLength" format="integer" />
</declare-styleable>
<declare-styleable name="RingtonePreference">
<attr name="showAdd" format="boolean" />
<attr name="summaryHasRingtone" format="string|reference" />
</declare-styleable>
<declare-styleable name="ColorPickerPreference">
<attr name="currentColor" format="reference" />
<attr name="colors" format="reference" />
<attr name="sortColors" format="boolean|reference" />
<attr name="colorDescriptions" format="reference" />
<attr name="columns" format="integer|reference" />
<attr name="colorSize" format="enum|reference">
<enum name="large" value="1" />
<enum name="small" value="2" />

View File

@ -25,6 +25,7 @@
<color name="compose_text_view_background">#141414</color>
<color name="quote_not_found_background">#99FFFFFF</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_border">#212121</color>
<color name="paths_building">#FFCE3A</color>

View File

@ -8,7 +8,7 @@
<dimen name="small_font_size">15sp</dimen>
<dimen name="medium_font_size">17sp</dimen>
<dimen name="large_font_size">22sp</dimen>
<dimen name="very_large_font_size">27sp</dimen>
<dimen name="very_large_font_size">26sp</dimen>
<dimen name="massive_font_size">50sp</dimen>
<!-- Element Sizes -->
@ -29,9 +29,9 @@
<dimen name="text_view_corner_radius">8dp</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_height">234dp</dimen>
<dimen name="fake_chat_view_height">250dp</dimen>
<dimen name="setting_button_height">56dp</dimen>
<dimen name="dialog_corner_radius">12dp</dimen>
<dimen name="dialog_corner_radius">8dp</dimen>
<dimen name="dialog_button_corner_radius">4dp</dimen>
<dimen name="pn_option_corner_radius">8dp</dimen>
<dimen name="path_status_view_size">8dp</dimen>

View File

@ -1851,7 +1851,7 @@
<string name="activity_select_contacts_title">Select Contacts</string>
<string name="dialog_seed_disclaimer">*Please note that it is not possible to use the same Session ID on multiple devices simultaneously</string>
<string name="dialog_seed_disclaimer">It is not possible to use the same Session ID on multiple devices simultaneously</string>
<string name="view_reset_secure_session_done_message">Secure session reset done</string>
@ -1864,5 +1864,6 @@
<string name="attachment">Attachment</string>
<string name="attachment_type_voice_message">Voice Message</string>
<string name="details">Details</string>
</resources>

View File

@ -6,7 +6,6 @@
<item name="android:background">?colorPrimary</item>
<item name="elevation">1dp</item>
<item name="titleTextStyle">@style/TextAppearance.Session.DarkActionBar.TitleTextStyle</item>
<item name="popupTheme">@style/Widget.Session.ActionBar</item>
</style>
<style name="Widget.Session.ActionBar.Flat">
@ -184,10 +183,12 @@
<style name="FakeChatViewMessageBubble.Incoming">
<item name="android:background">@drawable/fake_chat_view_incoming_message_background</item>
<item name="android:elevation">10dp</item>
</style>
<style name="FakeChatViewMessageBubble.Outgoing">
<item name="android:background">@drawable/fake_chat_view_outgoing_message_background</item>
<item name="android:elevation">10dp</item>
</style>
<!-- Session -->

View File

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Session -->
@ -43,16 +42,14 @@
<item name="dividerHorizontal">?dividerVertical</item>
<!-- App specific attributes -->
<item name="search_toolbar_background">@color/black</item>
<item name="search_background">@color/black</item>
<item name="ic_visibility_on">@drawable/ic_baseline_visibility_24</item>
<item name="ic_visibility_off">@drawable/ic_baseline_visibility_off_24</item>
<item name="ic_arrow_forward">@drawable/ic_baseline_arrow_forward_24</item>
<item name="dialog_background_color">@color/dialog_background</item>
<item name="media_overview_toolbar_background">@color/transparent</item>
<item name="media_overview_toolbar_foreground">@color/white</item>
<item name="media_overview_header_foreground">@color/text</item>
<item name="media_overview_document_primary">@color/core_grey_05</item>
<item name="media_overview_document_secondary">#99FFFFFF</item>
<item name="media_keyboard_button_color">@color/core_grey_25</item>
<item name="searchViewStyle">@style/TextSecure.BaseDarkTheme.SearchView</item>
@ -87,6 +84,7 @@
<item name="conversation_input_background">@drawable/compose_background_dark</item>
<item name="quick_camera_icon">@drawable/ic_baseline_photo_camera_24</item>
<item name="quick_mic_icon">@drawable/ic_baseline_mic_24</item>
</style>
<!-- This should be the default theme for the application. -->
@ -158,14 +156,7 @@
<item name="colorPrimary">@color/action_bar_background</item>
<item name="colorPrimaryDark">@color/action_bar_background</item>
<item name="recipient_preference_blocked">#d00000</item>
<item name="contact_selection_label_text">#66eeeeee</item>
<item name="contact_selection_push_user">#ffeeeeee</item>
<item name="contact_selection_lay_user">#afeeeeee</item>
<item name="contact_selection_header_text">#66eeeeee</item>
<item name="media_overview_toolbar_background">@color/transparent</item>
<item name="media_overview_toolbar_foreground">@color/white</item>
<item name="media_overview_header_foreground">@color/text</item>
<item name="theme_type">dark</item>
@ -175,8 +166,6 @@
<item name="attachment_document_icon_small">@drawable/ic_document_small_dark</item>
<item name="attachment_document_icon_large">@drawable/ic_document_large_dark</item>
<item name="compose_icon_tint">@color/core_grey_25</item>
<item name="conversation_list_item_background">@drawable/conversation_list_item_background_dark</item>
<item name="conversation_list_item_contact_color">#ffdddddd</item>
<item name="conversation_list_item_subject_color">#ffdddddd</item>
@ -194,22 +183,14 @@
<item name="conversation_item_sent_text_primary_color">@color/core_grey_05</item>
<item name="conversation_item_sent_text_secondary_color">@color/core_grey_25</item>
<item name="conversation_item_sent_icon_color">@color/core_grey_25</item>
<item name="conversation_item_sent_download_icon_color">@color/core_white</item>
<item name="conversation_item_sent_text_indicator_tab_color">#99ffffff</item>
<item name="conversation_item_received_text_primary_color">@color/text</item>
<item name="conversation_item_received_text_secondary_color">@color/text</item>
<item name="conversation_item_sent_indicator_text_background">@drawable/conversation_item_sent_indicator_text_shape_dark</item>
<item name="conversation_item_update_text_color">@color/core_grey_45</item>
<item name="conversation_item_last_seen_text_color">@color/core_grey_25</item>
<item name="conversation_item_last_seen_line_color">@color/core_grey_25</item>
<item name="conversation_item_date_line_color">@color/core_grey_45</item>
<item name="conversation_item_quote_text_color">@color/core_grey_05</item>
<item name="conversation_item_sticky_date_background">@drawable/sticky_date_header_background_dark</item>
<item name="conversation_item_sticky_date_text_color">@color/core_grey_45</item>
<item name="conversation_item_image_outline_color">@color/transparent_white_30</item>
<item name="contact_list_divider">@drawable/contact_list_divider_dark</item>
<item name="verification_background">@color/core_grey_95</item>
<item name="dialog_info_icon">@drawable/ic_info_outline_dark</item>
@ -217,12 +198,6 @@
<item name="device_link_item_card_background">@color/device_link_item_background_dark</item>
<item name="mediapicker_image_outline">@drawable/mediapicker_item_border_dark</item>
<item name="import_export_item_background_color">@color/import_export_item_background_dark</item>
<item name="import_export_item_background_shadow_color">@color/import_export_item_background_shadow_dark</item>
<item name="import_export_item_card_background">@drawable/clickable_card_dark</item>
<item name="fab_color">@color/textsecure_primary_dark</item>
<item name="lower_right_divet">@drawable/divet_lower_right_light</item>
@ -269,27 +244,9 @@
<item name="linkpreview_secondary_text_color">@color/text</item>
<item name="linkpreview_divider_color">@color/transparent</item>
<!-- <item name="quick_camera_icon">@drawable/ic_baseline_photo_camera_24</item>-->
<item name="quick_mic_icon">@drawable/ic_mic_white_24dp</item>
<item name="media_keyboard_button_color">@color/core_grey_25</item>
<item name="menu_new_conversation_icon">@drawable/ic_add_white_24dp</item>
<item name="menu_group_icon">@drawable/ic_group_white_24dp</item>
<item name="menu_search_icon">@drawable/ic_search_white_24dp</item>
<item name="menu_call_icon">@drawable/ic_call_white_24dp</item>
<item name="menu_unlock_icon">@drawable/ic_unlocked_white_24dp</item>
<item name="menu_lock_icon">@drawable/ic_lock_white_24dp</item>
<item name="menu_lock_icon_small">@drawable/ic_lock_white_18dp</item>
<item name="menu_accept_icon">@drawable/ic_check_white_24dp</item>
<item name="menu_refresh_directory">@drawable/ic_refresh_white_24dp</item>
<item name="menu_info_icon">@drawable/ic_info_outline_white_24dp</item>
<item name="conversation_icon_attach_audio">@drawable/ic_audio_dark</item>
<item name="conversation_icon_attach_video">@drawable/ic_video_dark</item>
<item name="reminder_header_background">@color/textsecure_primary_dark</item>
<item name="sticker_management_icon">@drawable/sticker_button_dark</item>
<item name="sticker_management_divider_color">@color/core_grey_75</item>
<item name="sticker_management_empty_background_color">@color/core_grey_85</item>
@ -303,15 +260,8 @@
<item name="pref_icon_tint">#FFFFFF</item>
<item name="pref_divider">@drawable/preference_divider_dark</item>
<item name="quote_missing_icon_color">@color/core_grey_05</item>
<item name="group_members_dialog_icon">@drawable/ic_group_white_24dp</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.Fix</item>
<item name="search_toolbar_background">@color/black</item>
<item name="search_background">@color/black</item>
<item name="invite_background">@color/black</item>
<item name="shared_contact_details_header_background">@color/grey_800</item>
<item name="shared_contact_details_titlebar">@color/grey_900</item>

View File

@ -44,7 +44,7 @@
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:persistent="false"
app:numColumns="5" />
app:columns="5" />
</PreferenceCategory>
<PreferenceCategory android:layout="@layout/preference_divider"/>

View File

@ -16,18 +16,17 @@
*/
package org.thoughtcrime.securesms;
import android.app.Application;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ProcessLifecycleOwner;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ProcessLifecycleOwner;
import androidx.multidex.MultiDexApplication;
import com.google.firebase.iid.FirebaseInstanceId;
@ -116,10 +115,10 @@ import org.whispersystems.signalservice.loki.protocol.closedgroups.SharedSenderK
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
import org.whispersystems.signalservice.loki.protocol.meta.TTLUtilities;
import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocol;
import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocolDelegate;
import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.DeviceLink;
import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.MultiDeviceProtocol;
import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocol;
import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocolDelegate;
import org.whispersystems.signalservice.loki.protocol.shelved.syncmessages.SyncMessagesProtocol;
import java.io.File;
@ -145,10 +144,11 @@ import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
*
* @author Moxie Marlinspike
*/
public class ApplicationContext extends Application implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate,
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate,
SessionManagementProtocolDelegate, SharedSenderKeysImplementationDelegate {
private static final String TAG = ApplicationContext.class.getSimpleName();
private final static int OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10 MB
private ExpiringMessageManager expiringMessageManager;
private TypingStatusRepository typingStatusRepository;

View File

@ -23,9 +23,6 @@ import android.content.Intent;
import android.graphics.PorterDuff;
import android.os.Build;
import android.os.Bundle;
import androidx.core.hardware.fingerprint.FingerprintManagerCompat;
import androidx.core.os.CancellationSignal;
import androidx.appcompat.widget.Toolbar;
import android.text.Editable;
import android.text.InputType;
import android.text.SpannableString;
@ -49,6 +46,9 @@ import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.core.hardware.fingerprint.FingerprintManagerCompat;
import androidx.core.os.CancellationSignal;
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
import org.thoughtcrime.securesms.components.AnimatingToggle;
import org.thoughtcrime.securesms.crypto.InvalidPassphraseException;
@ -91,8 +91,6 @@ public class PassphrasePromptActivity extends PassphraseActivity {
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate()");
dynamicLanguage.onCreate(this);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
super.onCreate(savedInstanceState);
setContentView(R.layout.prompt_passphrase_activity);
@ -204,7 +202,6 @@ public class PassphrasePromptActivity extends PassphraseActivity {
private void initializeResources() {
ImageButton okButton = findViewById(R.id.ok_button);
Toolbar toolbar = findViewById(R.id.toolbar);
showButton = findViewById(R.id.passphrase_visibility);
hideButton = findViewById(R.id.passphrase_visibility_off);
@ -217,9 +214,6 @@ public class PassphrasePromptActivity extends PassphraseActivity {
fingerprintCancellationSignal = new CancellationSignal();
fingerprintListener = new FingerprintListener();
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("");
SpannableString hint = new SpannableString(" " + getString(R.string.PassphrasePromptActivity_enter_passphrase));
hint.setSpan(new RelativeSizeSpan(0.9f), 0, hint.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
hint.setSpan(new TypefaceSpan("sans-serif"), 0, hint.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
@ -229,8 +223,7 @@ public class PassphrasePromptActivity extends PassphraseActivity {
showButton.setOnClickListener(new ShowButtonOnClickListener());
hideButton.setOnClickListener(new HideButtonOnClickListener());
passphraseText.setOnEditorActionListener(new PassphraseActionListener());
passphraseText.setImeActionLabel(getString(R.string.prompt_passphrase_activity__unlock),
EditorInfo.IME_ACTION_DONE);
passphraseText.setImeActionLabel(getString(R.string.prompt_passphrase_activity__unlock), EditorInfo.IME_ACTION_DONE);
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN);

View File

@ -6,9 +6,6 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
@ -17,11 +14,16 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.annimon.stream.Stream;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.Slide;
@ -209,7 +211,8 @@ public class QuoteView extends FrameLayout implements RecipientModifiedListener
authorView.setText(isOwnNumber ? getContext().getString(R.string.QuoteView_you) : quoteeDisplayName);
// We use the raw color resource because Android 4.x was struggling with tints here
quoteBarView.setImageResource(R.color.accent);
int colorID = UiModeUtilities.isDayUiMode(getContext()) ? R.color.black : R.color.accent;
quoteBarView.setImageResource(colorID);
mainView.setBackgroundColor(ThemeUtil.getThemedColor(getContext(),
outgoing ? R.attr.message_received_background_color : R.attr.message_sent_background_color));
}

View File

@ -160,6 +160,7 @@ import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
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.mediasend.Media;
import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
@ -234,6 +235,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
@ -300,6 +302,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private AnimatingToggle buttonToggle;
private SendButton sendButton;
private ImageButton attachButton;
private ProfilePictureView profilePictureView;
private TextView titleTextView;
private TextView charactersLeft;
private ConversationFragment fragment;
@ -527,6 +530,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
composeText.setTransport(sendButton.getSelectedTransport());
updateTitleTextView(recipient);
updateProfilePicture();
updateSubtitleTextView();
setActionBarColor(recipient.getColor());
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.addListener(this);
updateTitleTextView(recipient);
updateProfilePicture();
updateSubtitleTextView();
NotificationChannels.updateContactChannelName(this, recipient);
updateInputUI(recipient, isSecureText, isDefaultSms);
@ -1654,6 +1659,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void initializeViews() {
profilePictureView = findViewById(R.id.profilePictureView);
titleTextView = findViewById(R.id.titleTextView);
buttonToggle = ViewUtil.findById(this, R.id.button_toggle);
sendButton = ViewUtil.findById(this, R.id.send_button);
@ -1872,6 +1878,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
Util.runOnMain(() -> {
Log.i(TAG, "onModifiedRun(): " + recipient.getRegistered());
updateTitleTextView(recipient);
updateProfilePicture();
updateSubtitleTextView();
// titleView.setVerified(identityRecords.isVerified());
updateInputUI(recipient, isSecureText, isDefaultSms);
@ -3100,18 +3107,15 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
}
private void updateProfilePicture() {
profilePictureView.glide = GlideApp.with(this);
profilePictureView.update(recipient, threadId);
}
private void updateSubtitleTextView() {
muteIndicatorImageView.setVisibility(View.GONE);
subtitleTextView.setVisibility(View.VISIBLE);
if (messageStatus != null) {
switch (messageStatus) {
case "calculatingPoW": subtitleTextView.setText("Encrypting message"); break;
case "contactingNetwork": subtitleTextView.setText("Tracing a path"); break;
case "sendingMessage": subtitleTextView.setText("Sending message"); break;
case "messageSent": subtitleTextView.setText("Message sent securely"); break;
case "messageFailed": subtitleTextView.setText("Message failed to send"); break;
}
} else if (recipient.isMuted()) {
if (recipient.isMuted()) {
muteIndicatorImageView.setVisibility(View.VISIBLE);
subtitleTextView.setText("Muted until " + DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault()));
} else if (recipient.isGroupRecipient() && recipient.getName() != null && !recipient.getName().equals("Session Updates") && !recipient.getName().equals("Loki News")) {
@ -3125,10 +3129,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} else {
subtitleTextView.setVisibility(View.GONE);
}
} else if (PublicKeyValidation.isValid(recipient.getAddress().toString())) {
String ourMasterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(this);
String hexEncodedPublicKey = (recipient.isLocalNumber() && ourMasterHexEncodedPublicKey != null) ? ourMasterHexEncodedPublicKey : recipient.getAddress().toPhoneString();
subtitleTextView.setText(hexEncodedPublicKey);
} else {
subtitleTextView.setVisibility(View.GONE);
}

View File

@ -528,6 +528,7 @@ public class ThreadDatabase extends Database {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getLong(cursor.getColumnIndexOrThrow(ID));
} else {
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
return createThreadForRecipient(recipient.getAddress(), recipient.isGroupRecipient(), distributionType);
}
} finally {

View File

@ -34,6 +34,7 @@ import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob
import org.thoughtcrime.securesms.loki.dialogs.ConversationOptionsBottomSheet
import org.thoughtcrime.securesms.loki.dialogs.LightThemeFeatureIntroBottomSheet
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.SessionResetImplementation
import org.thoughtcrime.securesms.loki.utilities.*
@ -100,6 +101,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
profileButton.displayName = TextSecurePreferences.getProfileName(this)
profileButton.update()
profileButton.setOnClickListener { openSettings() }
pathStatusViewContainer.disableClipping()
pathStatusViewContainer.setOnClickListener { showPath() }
// Set up seed reminder view
val isMasterDevice = (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == null)
@ -202,7 +204,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
seedReminderView.visibility = View.GONE
}
// Multiple device removal notification
// Multi device removal sheet
if (!TextSecurePreferences.getHasSeenMultiDeviceRemovalSheet(this)) {
TextSecurePreferences.setHasSeenMultiDeviceRemovalSheet(this)
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
@ -223,7 +225,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
}
}
// Light theme introduction
// Light theme introduction sheet
if (!TextSecurePreferences.hasSeenLightThemeIntroSheet(this) &&
UiModeUtilities.isDayUiMode(this)) {
TextSecurePreferences.setHasSeenLightThemeIntroSheet(this)
@ -271,6 +273,14 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
val thread = view.thread ?: return
val bottomSheet = ConversationOptionsBottomSheet()
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.dismiss()
if (!thread.recipient.isBlocked) {

View File

@ -1,5 +1,7 @@
package org.thoughtcrime.securesms.loki.activities
import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.app.AlertDialog
import android.content.Intent
import android.graphics.drawable.TransitionDrawable
@ -9,27 +11,36 @@ import androidx.annotation.DrawableRes
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.LinearLayout
import android.widget.Toast
import androidx.annotation.ColorRes
import kotlinx.android.synthetic.main.activity_display_name.registerButton
import kotlinx.android.synthetic.main.activity_pn_mode.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.ApplicationContext
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.show
import org.thoughtcrime.securesms.loki.views.GlowViewUtilities
import org.thoughtcrime.securesms.loki.views.PNModeView
import org.thoughtcrime.securesms.util.TextSecurePreferences
class PNModeActivity : BaseActionBarActivity() {
private var selectedOptionView: LinearLayout? = null
private var selectedOptionView: PNModeView? = null
// region Lifecycle
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setUpActionBarSessionLogo()
setContentView(R.layout.activity_pn_mode)
contentView.disableClipping()
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.mainColor = resources.getColorWithID(R.color.pn_option_background, theme)
backgroundPollingOptionView.strokeColor = resources.getColorWithID(R.color.pn_option_border, theme)
registerButton.setOnClickListener { register() }
}
@ -71,15 +82,23 @@ class PNModeActivity : BaseActionBarActivity() {
when (selectedOptionView) {
null -> {
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
}
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
}
backgroundPollingOptionView -> {
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)
GlowViewUtilities.animateShadowColorChange(this, backgroundPollingOptionView, R.color.accent, R.color.transparent)
animateStrokeColorChange(backgroundPollingOptionView, R.color.accent, R.color.pn_option_border)
selectedOptionView = fcmOptionView
}
}
@ -89,20 +108,40 @@ class PNModeActivity : BaseActionBarActivity() {
when (selectedOptionView) {
null -> {
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
}
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
}
fcmOptionView -> {
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)
GlowViewUtilities.animateShadowColorChange(this, fcmOptionView, R.color.accent, R.color.transparent)
animateStrokeColorChange(fcmOptionView, R.color.accent, R.color.pn_option_border)
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() {
if (selectedOptionView == null) {
val dialog = AlertDialog.Builder(this)
@ -111,7 +150,6 @@ class PNModeActivity : BaseActionBarActivity() {
dialog.create().show()
return
}
val displayName = TextSecurePreferences.getProfileName(this)
TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
TextSecurePreferences.setPromptedPushRegistration(this, true)
TextSecurePreferences.setIsUsingFCM(this, (selectedOptionView == fcmOptionView))

View File

@ -16,10 +16,13 @@ import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.ColorRes
import kotlinx.android.synthetic.main.activity_path.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
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.onionrequests.OnionRequestAPI
@ -31,6 +34,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
super.onCreate(savedInstanceState, isReady)
setContentView(R.layout.activity_path)
supportActionBar!!.title = resources.getString(R.string.activity_path_title)
pathRowsContainer.disableClipping()
learnMoreButton.setOnClickListener { learnMore() }
update(false)
registerObservers()
@ -111,6 +115,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
val mainContainer = LinearLayout(this)
mainContainer.orientation = LinearLayout.HORIZONTAL
mainContainer.gravity = Gravity.CENTER_VERTICAL
mainContainer.disableClipping()
val mainContainerLayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
mainContainer.layoutParams = mainContainerLayoutParams
val lineView = LineView(this, location, dotAnimationStartDelay, dotAnimationRepeatInterval)
@ -170,8 +175,9 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
private var dotAnimationRepeatInterval: Long = 0
private val dotView by lazy {
val result = View(context)
val result = PathDotView(context)
result.setBackgroundResource(R.drawable.accent_dot)
result.mainColor = resources.getColorWithID(R.color.accent, context.theme)
result
}
@ -203,6 +209,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
}
private fun setUpViewHierarchy() {
disableClipping()
val lineView = View(context)
lineView.setBackgroundColor(resources.getColorWithID(R.color.text, context.theme))
val lineViewHeight = when (location) {
@ -239,10 +246,14 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
private fun expand() {
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() {
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

View File

@ -33,8 +33,14 @@ class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database
return TextSecurePreferences.getProfileName(context)
} else {
val database = databaseHelper.readableDatabase
return database.get(displayNameTable, "${Companion.publicKey} = ?", arrayOf( publicKey )) { cursor ->
val result = database.get(displayNameTable, "${Companion.publicKey} = ?", arrayOf( publicKey )) { cursor ->
cursor.getString(cursor.getColumnIndexOrThrow(displayName))
} ?: return null
val suffix = " (...${publicKey.substring(publicKey.count() - 8)})"
if (result.endsWith(suffix)) {
return result.substring(0..(result.count() - suffix.count()))
} else {
return result
}
}
}

View File

@ -20,6 +20,7 @@ public class ConversationOptionsBottomSheet : BottomSheetDialogFragment() {
// if we want to use dialog fragments properly.
lateinit var recipient: Recipient
var onViewDetailsTapped: (() -> Unit?)? = null
var onBlockTapped: (() -> Unit)? = null
var onUnblockTapped: (() -> Unit)? = null
var onDeleteTapped: (() -> Unit)? = null
@ -30,18 +31,16 @@ public class ConversationOptionsBottomSheet : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (!this::recipient.isInitialized) {
dismiss()
return
}
if (!this::recipient.isInitialized) { return dismiss() }
if (!recipient.isGroupRecipient && !recipient.isLocalNumber) {
detailsTextView.visibility = View.VISIBLE
unblockTextView.visibility = if (recipient.isBlocked) View.VISIBLE else View.GONE
blockTextView.visibility = if (recipient.isBlocked) View.GONE else View.VISIBLE
detailsTextView.setOnClickListener { onViewDetailsTapped?.invoke() }
blockTextView.setOnClickListener { onBlockTapped?.invoke() }
unblockTextView.setOnClickListener { onUnblockTapped?.invoke() }
} else {
detailsTextView.visibility = View.GONE
}
deleteTextView.setOnClickListener { onDeleteTapped?.invoke() }
}

View File

@ -7,17 +7,18 @@ import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.appcompat.app.AlertDialog
import android.view.LayoutInflater
import android.view.WindowManager
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import kotlinx.android.synthetic.main.dialog_seed.view.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
import org.whispersystems.signalservice.loki.utilities.hexEncodedPrivateKey
import java.io.File
class SeedDialog : DialogFragment() {

View File

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

View File

@ -10,7 +10,6 @@ import org.thoughtcrime.securesms.recipients.Recipient
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.shelved.multidevice.MultiDeviceProtocol
import java.security.MessageDigest
object SessionMetaProtocol {
@ -37,24 +36,16 @@ object SessionMetaProtocol {
@JvmStatic
fun handleProfileUpdateIfNeeded(context: Context, content: SignalServiceContent) {
val rawDisplayName = content.senderDisplayName.orNull() ?: return
if (rawDisplayName.isBlank()) { return }
val displayName = content.senderDisplayName.orNull() ?: return
if (displayName.isBlank()) { return }
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
val userMasterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
val sender = content.sender.toLowerCase()
if (userMasterPublicKey == sender) {
// Update the user's local name if the message came from their master device
TextSecurePreferences.setProfileName(context, rawDisplayName)
TextSecurePreferences.setProfileName(context, displayName)
}
// Don't overwrite if the message came from a linked device; the device name is
// stored as a user name
val allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey)
if (!allUserDevices.contains(sender)) {
val displayName = rawDisplayName + " (..." + sender.substring(sender.length - 8) + ")"
DatabaseFactory.getLokiUserDatabase(context).setDisplayName(sender, displayName)
} else {
DatabaseFactory.getLokiUserDatabase(context).setDisplayName(sender, rawDisplayName)
}
}
@JvmStatic

View File

@ -53,7 +53,9 @@ object MentionUtilities {
}
val result = SpannableString(text)
for (mention in mentions) {
result.setSpan(ForegroundColorSpan(context.resources.getColorWithID(R.color.accent, context.theme)), mention.first.lower, mention.first.upper, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
val isLightMode = UiModeUtilities.isDayUiMode(context)
val colorID = if (isLightMode && isOutgoingMessage) R.color.black else R.color.accent
result.setSpan(ForegroundColorSpan(context.resources.getColorWithID(colorID, context.theme)), mention.first.lower, mention.first.upper, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
result.setSpan(StyleSpan(Typeface.BOLD), mention.first.lower, mention.first.upper, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
return result

View File

@ -57,37 +57,8 @@ class ConversationView : LinearLayout {
accentView.setBackgroundResource(R.color.accent)
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.displayName = ""
profilePictureView.additionalPublicKey = null
profilePictureView.isRSSFeed = true
} else {
val userKeys = MentionsManager.shared.userPublicKeyCache[thread.threadId]?.toMutableList() ?: mutableListOf()
userKeys.remove(TextSecurePreferences.getLocalNumber(context))
val masterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
if (masterPublicKey != null) {
userKeys.remove(masterPublicKey)
}
val sortedUserKeys = userKeys.sorted() // Sort to provide a level of stability
val userKey0 = sortedUserKeys.getOrNull(0) ?: ""
val userKey1 = sortedUserKeys.getOrNull(1) ?: ""
profilePictureView.publicKey = userKey0
profilePictureView.displayName = getUserDisplayName(userKey0)
profilePictureView.additionalPublicKey = userKey1
profilePictureView.additionalDisplayName = getUserDisplayName(userKey1)
profilePictureView.isRSSFeed = thread.recipient.name == "Loki News" || thread.recipient.name == "Session Updates"
}
} else {
profilePictureView.publicKey = thread.recipient.address.toString()
profilePictureView.displayName = thread.recipient.name
profilePictureView.additionalPublicKey = null
profilePictureView.isRSSFeed = false
}
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()
btnGroupNameDisplay.text = senderDisplayName
timestampTextView.text = DateUtils.getBriefRelativeTimeSpanString(context, Locale.getDefault(), thread.date)

View File

@ -1,14 +1,18 @@
package org.thoughtcrime.securesms.loki.views
import android.animation.FloatEvaluator
import android.animation.ValueAnimator
import android.content.Context
import android.content.Context.LAYOUT_INFLATER_SERVICE
import android.os.Handler
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import android.widget.ScrollView
import kotlinx.android.synthetic.main.view_fake_chat.view.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.disableClipping
class FakeChatView : ScrollView {
@ -38,7 +42,8 @@ class FakeChatView : ScrollView {
private fun setUpViewHierarchy() {
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)
isVerticalScrollBarEnabled = false
}
@ -47,8 +52,13 @@ class FakeChatView : ScrollView {
// region Animation
fun startAnimating() {
listOf( bubble1, bubble2, bubble3, bubble4, bubble5 ).forEach { it.alpha = 0.0f }
fun show(view: View) {
view.animate().alpha(1.0f).setDuration(animationDuration).start()
fun show(bubble: View) {
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({
show(bubble1)

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

View File

@ -7,9 +7,7 @@ import android.animation.ValueAnimator
import android.content.Context
import android.content.Context.VIBRATOR_SERVICE
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.PointF
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.os.VibrationEffect
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 imageView by lazy {
val result = ImageView(context)
val result = NewConversationButtonImageView(context)
val size = collapsedSize.toInt()
result.layoutParams = LayoutParams(size, size)
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
background.color = ColorStateList.valueOf(resources.getColorWithID(backgroundColorID, context.theme))
@ColorRes val backgroundColorID = if (isMain) R.color.accent else R.color.new_conversation_button_collapsed_background
@ColorRes val shadowColorID = if (isMain) {
R.color.new_conversation_button_shadow
} else {
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.setImageResource(iconID)
result.imageTintList = if (isMain)
// Always use white icon for the main button.
result.imageTintList = if (isMain) {
ColorStateList.valueOf(resources.getColorWithID(android.R.color.white, context.theme))
else
} else {
ColorStateList.valueOf(resources.getColorWithID(R.color.text, context.theme))
}
result
}
@ -106,30 +105,21 @@ class NewConversationButtonSetView : RelativeLayout {
}
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)
animateImageViewPositionChange(collapsedImageViewPosition, expandedImageViewPosition)
}
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)
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) {
val animation = ValueAnimator.ofObject(PointFEvaluator(), startPosition, endPosition)
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() }
private fun setUpViewHierarchy() {
disableClipping()
// Set up session button
addView(sessionButton)
sessionButton.alpha = 0.0f

View File

@ -4,14 +4,30 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Canvas
import android.graphics.Paint
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import android.util.AttributeSet
import android.view.View
import androidx.annotation.ColorInt
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
class PathStatusView : View {
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) {
initialize()
@ -31,6 +47,7 @@ class PathStatusView : View {
private fun initialize() {
update()
setWillNotDraw(false)
}
override fun onAttachedToWindow() {
@ -70,8 +87,19 @@ class PathStatusView : View {
private fun update() {
if (OnionRequestAPI.paths.count() >= OnionRequestAPI.pathCount) {
setBackgroundResource(R.drawable.accent_dot)
mainColor = resources.getColorWithID(R.color.accent, context.theme)
sessionShadowColor = resources.getColorWithID(R.color.accent, context.theme)
} else {
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)
}
}

View File

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.loki.views
import android.content.Context
import android.text.TextUtils
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
@ -8,14 +9,17 @@ import android.widget.ImageView
import android.widget.RelativeLayout
import androidx.annotation.DimenRes
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 network.loki.messenger.R
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto
import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.todo.AvatarPlaceholderGenerator
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.recipients.Recipient
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?
@ -53,6 +57,43 @@ class ProfilePictureView : RelativeLayout {
// endregion
// region Updating
fun update(recipient: Recipient, threadID: Long) {
fun getUserDisplayName(publicKey: String?): String? {
if (publicKey == null || publicKey.isBlank()) {
return null
} else {
return DatabaseFactory.getLokiUserDatabase(context).getDisplayName(publicKey!!)
}
}
if (recipient.isGroupRecipient) {
if ("Session Public Chat" == recipient.name) {
publicKey = ""
displayName = ""
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) ?: ""
displayName = getUserDisplayName(randomUsers.getOrNull(0) ?: "")
additionalPublicKey = randomUsers.getOrNull(1) ?: ""
additionalDisplayName = getUserDisplayName(randomUsers.getOrNull(1) ?: "")
isRSSFeed = recipient.name == "Loki News" || recipient.name == "Session Updates"
}
} else {
publicKey = recipient.address.toString()
displayName = recipient.name
additionalPublicKey = null
isRSSFeed = false
}
update()
}
fun update() {
val publicKey = publicKey ?: return
val additionalPublicKey = additionalPublicKey