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

View File

@ -1,16 +1,15 @@
import java.security.MessageDigest
buildscript { buildscript {
ext.kotlin_version = "1.3.31" ext.kotlin_version = "1.4.0"
ext.kovenant_version = "3.3.0" ext.kovenant_version = "3.3.0"
repositories { repositories {
mavenLocal() mavenLocal()
google() google()
mavenCentral() mavenCentral()
jcenter()
} }
dependencies { 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 files('libs/gradle-witness.jar')
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.gms:google-services:4.3.3" classpath "com.google.gms:google-services:4.3.3"
@ -18,8 +17,8 @@ buildscript {
} }
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'witness' apply plugin: 'witness'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'
@ -73,14 +72,15 @@ configurations.all {
dependencies { dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.recyclerview:recyclerview:1.1.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.legacy:legacy-support-v13:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.preference:preference:1.1.1' implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.legacy:legacy-preference-v14:1.0.0' implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0'
implementation 'androidx.exifinterface:exifinterface:1.2.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-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-common-java8: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-analytics'
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector' 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-core:2.9.1'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.1' implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.1'
implementation 'org.conscrypt:conscrypt-android:2.0.0' implementation 'org.conscrypt:conscrypt-android:2.0.0'
@ -141,28 +140,6 @@ dependencies {
exclude group: 'com.fasterxml.jackson.core' exclude group: 'com.fasterxml.jackson.core'
exclude group: 'org.freemarker' 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 // Loki
// Local: // Local:
implementation "org.whispersystems:signal-service-android:2.13.2" // Run ./gradlew install from session-android-service to install 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.tbruyelle:rxpermissions:0.10.2"
implementation "com.github.ybq:Android-SpinKit:1.4.0" implementation "com.github.ybq:Android-SpinKit:1.4.0"
implementation "com.opencsv:opencsv:4.6" 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 canonicalVersionCode = 93
def canonicalVersionName = "1.5.0" def canonicalVersionName = "1.5.2"
def postFixSize = 10 def postFixSize = 10
def abiPostFix = ['armeabi-v7a' : 1, def abiPostFix = ['armeabi-v7a' : 1,
@ -208,9 +207,10 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
multiDexEnabled true // Even though we're running API 21+, this is still needed for release builds
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
project.ext.set("archivesBaseName", "Signal") project.ext.set("archivesBaseName", "session")
buildConfigField "long", "BUILD_TIMESTAMP", getLastCommitTimestamp() + "L" buildConfigField "long", "BUILD_TIMESTAMP", getLastCommitTimestamp() + "L"
buildConfigField "String", "SIGNAL_URL", "\"\"" buildConfigField "String", "SIGNAL_URL", "\"\""
@ -279,7 +279,7 @@ android {
'proguard-ez-vcard.pro', 'proguard-ez-vcard.pro',
'proguard.cfg' 'proguard.cfg'
testProguardFiles 'proguard-automation.pro', testProguardFiles 'proguard-automation.pro',
'proguard.cfg' 'proguard.cfg'
} }
release { release {
minifyEnabled true minifyEnabled true
@ -349,6 +349,7 @@ android {
} }
} }
/*
def assembleWebsiteDescriptor = { variant, file -> def assembleWebsiteDescriptor = { variant, file ->
if (file.exists()) { if (file.exists()) {
MessageDigest md = MessageDigest.getInstance("SHA-256") MessageDigest md = MessageDigest.getInstance("SHA-256")
@ -372,7 +373,7 @@ def assembleWebsiteDescriptor = { variant, file ->
descriptorFile.write(descriptor) descriptorFile.write(descriptor)
} }
} }
/*
def signProductionRelease = { variant -> def signProductionRelease = { variant ->
variant.outputs.collect { output -> variant.outputs.collect { output ->
String apkName = output.outputFile.name String apkName = output.outputFile.name

View File

@ -5,5 +5,5 @@ repositories {
} }
dependencies { 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 distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists 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 zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists 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" /> <corners android:radius="@dimen/medium_button_corner_radius" />
<stroke android:width="@dimen/border_thickness" android:color="?colorAccent" /> <stroke android:width="@dimen/border_thickness" android:color="@color/accent" />
</shape> </shape>

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/contentView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
@ -30,7 +31,7 @@
android:textColor="@color/text" android:textColor="@color/text"
android:text="There are two ways Session can notify you of new messages." /> android:text="There are two ways Session can notify you of new messages." />
<LinearLayout <org.thoughtcrime.securesms.loki.views.PNModeView
android:id="@+id/fcmOptionView" android:id="@+id/fcmOptionView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -66,9 +67,9 @@
android:textStyle="bold" android:textStyle="bold"
android:text="@string/activity_pn_mode_recommended_option_tag" /> android:text="@string/activity_pn_mode_recommended_option_tag" />
</LinearLayout> </org.thoughtcrime.securesms.loki.views.PNModeView>
<LinearLayout <org.thoughtcrime.securesms.loki.views.PNModeView
android:id="@+id/backgroundPollingOptionView" android:id="@+id/backgroundPollingOptionView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -95,7 +96,7 @@
android:textColor="@color/text" android:textColor="@color/text"
android:text="Session will occasionally check for new messages in the background. Full metadata protection is guaranteed, but message notifications will be unreliable." /> android:text="Session will occasionally check for new messages in the background. Full metadata protection is guaranteed, but message notifications will be unreliable." />
</LinearLayout> </org.thoughtcrime.securesms.loki.views.PNModeView>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/contentView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
@ -30,7 +31,7 @@
android:textColor="@color/text" android:textColor="@color/text"
android:text="There are two ways Session can notify you of new messages." /> android:text="There are two ways Session can notify you of new messages." />
<LinearLayout <org.thoughtcrime.securesms.loki.views.PNModeView
android:id="@+id/fcmOptionView" android:id="@+id/fcmOptionView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -66,9 +67,9 @@
android:textStyle="bold" android:textStyle="bold"
android:text="@string/activity_pn_mode_recommended_option_tag" /> android:text="@string/activity_pn_mode_recommended_option_tag" />
</LinearLayout> </org.thoughtcrime.securesms.loki.views.PNModeView>
<LinearLayout <org.thoughtcrime.securesms.loki.views.PNModeView
android:id="@+id/backgroundPollingOptionView" android:id="@+id/backgroundPollingOptionView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -95,7 +96,7 @@
android:textColor="@color/text" android:textColor="@color/text"
android:text="Session will occasionally check for new messages in the background. Full metadata protection is guaranteed, but message notifications will be unreliable." /> android:text="Session will occasionally check for new messages in the background. Full metadata protection is guaranteed, but message notifications will be unreliable." />
</LinearLayout> </org.thoughtcrime.securesms.loki.views.PNModeView>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -20,9 +20,15 @@
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
<org.thoughtcrime.securesms.loki.views.ProfilePictureView
android:id="@+id/profilePictureView"
android:layout_width="@dimen/medium_profile_picture_size"
android:layout_height="@dimen/medium_profile_picture_size" />
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/medium_spacing"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView

View File

@ -9,5 +9,5 @@
android:visibility="gone" android:visibility="gone"
app:doc_titleColor="?conversation_item_sent_text_primary_color" app:doc_titleColor="?conversation_item_sent_text_primary_color"
app:doc_captionColor="?conversation_item_sent_text_secondary_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"/> tools:visibility="visible"/>

View File

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

View File

@ -9,13 +9,20 @@
app:behavior_hideable="true" app:behavior_hideable="true"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"> app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<TextView
android:id="@+id/detailsTextView"
style="@style/BottomSheetActionItem"
android:drawableStart="@drawable/ic_info_outline_white_24dp"
android:drawableTint="?attr/colorControlNormal"
android:text="@string/details" />
<TextView <TextView
android:id="@+id/blockTextView" android:id="@+id/blockTextView"
style="@style/BottomSheetActionItem" style="@style/BottomSheetActionItem"
android:drawableStart="?attr/menu_block_icon" android:drawableStart="?attr/menu_block_icon"
android:text="@string/RecipientPreferenceActivity_block" android:text="@string/RecipientPreferenceActivity_block"
android:visibility="gone" android:visibility="gone"
tools:visibility="visible"/> tools:visibility="visible" />
<TextView <TextView
android:id="@+id/unblockTextView" android:id="@+id/unblockTextView"
@ -23,7 +30,7 @@
android:drawableStart="?attr/menu_accept_icon" android:drawableStart="?attr/menu_accept_icon"
android:text="@string/RecipientPreferenceActivity_unblock" android:text="@string/RecipientPreferenceActivity_unblock"
android:visibility="gone" android:visibility="gone"
tools:visibility="visible"/> tools:visibility="visible" />
<TextView <TextView
android:id="@+id/deleteTextView" android:id="@+id/deleteTextView"

View File

@ -9,7 +9,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center" android:gravity="center"
android:background="?attr/search_background" android:background="?android:windowBackground"
android:visibility="gone" /> android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView <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_height="wrap_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:padding="10dp" android:padding="10dp">
android:background="?attr/invite_background">
<ImageView android:id="@+id/heart" <ImageView android:id="@+id/heart"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -17,7 +17,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="6dp" android:layout_marginStart="6dp"
android:padding="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:tint="?media_keyboard_button_color"
android:background="?selectableItemBackgroundBorderless" android:background="?selectableItemBackgroundBorderless"
android:visibility="invisible" android:visibility="invisible"
@ -98,7 +98,7 @@
android:tint="?media_keyboard_button_color" android:tint="?media_keyboard_button_color"
android:visibility="gone" android:visibility="gone"
android:background="?selectableItemBackground" 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_constraintBottom_toBottomOf="@id/media_keyboard_tabs"
app:layout_constraintTop_toTopOf="@id/media_keyboard_tabs" app:layout_constraintTop_toTopOf="@id/media_keyboard_tabs"
app:layout_constraintEnd_toStartOf="@id/media_keyboard_backspace_backup" app:layout_constraintEnd_toStartOf="@id/media_keyboard_backspace_backup"

View File

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

View File

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

View File

@ -28,7 +28,7 @@
<color name="app_icon_background">#333132</color> <color name="app_icon_background">#333132</color>
<color name="progress_bar_background">#0AFFFFFF</color> <color name="progress_bar_background">#0A000000</color>
<color name="quote_not_found_background">#99FFFFFF</color> <color name="quote_not_found_background">#99FFFFFF</color>
</resources> </resources>

View File

@ -11,4 +11,14 @@
<item name="android:textColor">@android:color/white</item> <item name="android:textColor">@android:color/white</item>
</style> </style>
<style name="FakeChatViewMessageBubble.Incoming">
<item name="android:background">@drawable/fake_chat_view_incoming_message_background</item>
<item name="android:elevation">4dp</item>
</style>
<style name="FakeChatViewMessageBubble.Outgoing">
<item name="android:background">@drawable/fake_chat_view_outgoing_message_background</item>
<item name="android:elevation">4dp</item>
</style>
</resources> </resources>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?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"> <style name="Theme.Session.Light" parent="Base.Theme.Session">
<item name="android:navigationBarColor">?android:navigationBarColor</item> <item name="android:navigationBarColor">?android:navigationBarColor</item>
@ -23,6 +23,8 @@
<item name="conversation_input_background">@drawable/compose_background_light</item> <item name="conversation_input_background">@drawable/compose_background_light</item>
<item name="quick_camera_icon">@drawable/ic_outline_photo_camera_24</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>
<style name="Theme.Session.DayNight" parent="Theme.Session.Light"> <style name="Theme.Session.DayNight" parent="Theme.Session.Light">
@ -39,8 +41,6 @@
<item name="alertDialogTheme">@style/AppCompatAlertDialogStyleLight</item> <item name="alertDialogTheme">@style/AppCompatAlertDialogStyleLight</item>
<item name="android:alertDialogTheme">@style/AppCompatDialogStyleLight</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_background">@drawable/conversation_list_item_background</item>
<item name="conversation_list_item_contact_color">@color/core_grey_90</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> <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_footer_icon_color">@color/core_grey_60</item>
<item name="conversation_sticker_author_color">@color/core_grey_95</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="verification_background">@color/core_grey_05</item>
<item name="emoji_tab_strip_background">@color/cell_background</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_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_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_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_sent_text_indicator_tab_color">#99000000</item>
<item name="conversation_item_received_text_primary_color">@color/text</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_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_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_sticky_date_text_color">@color/core_grey_60</item>
<item name="conversation_item_image_outline_color">@color/transparent_black_30</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="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> <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="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_background_color">@color/core_white</item>
<item name="linkpreview_primary_text_color">@color/core_black</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_secondary_text_color">@color/core_grey_60</item>
<item name="linkpreview_divider_color">@color/core_grey_25</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_audio">@drawable/ic_audio_light</item>
<item name="conversation_icon_attach_video">@drawable/ic_video_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_icon">@drawable/sticker_button_light</item>
<item name="sticker_management_divider_color">@color/core_grey_15</item> <item name="sticker_management_divider_color">@color/core_grey_15</item>
<item name="sticker_management_empty_background_color">@color/core_grey_05</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_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="group_members_dialog_icon">@drawable/ic_group_grey600_24dp</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.Fix</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_header_background">@color/grey_100</item>
<item name="shared_contact_details_titlebar">@color/grey_400</item> <item name="shared_contact_details_titlebar">@color/grey_400</item>
<item name="shared_contact_item_button_color">@color/core_grey_02</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"?> <?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"> <style name="Theme.Session.DayNight" parent="Theme.Session.Light">
<item name="android:statusBarColor">@color/transparent</item> <item name="android:statusBarColor">@color/transparent</item>

View File

@ -8,7 +8,7 @@
<dimen name="small_font_size">13sp</dimen> <dimen name="small_font_size">13sp</dimen>
<dimen name="medium_font_size">15sp</dimen> <dimen name="medium_font_size">15sp</dimen>
<dimen name="large_font_size">20sp</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> <dimen name="massive_font_size">50sp</dimen>
<!-- Session --> <!-- Session -->

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?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"> <style name="Theme.Session.ForceDark" parent="Base.Theme.Session.ForceDark">
<item name="android:windowLightStatusBar">false</item> <item name="android:windowLightStatusBar">false</item>

View File

@ -19,16 +19,13 @@
<attr name="conversation_list_toolbar_background" format="reference"/> <attr name="conversation_list_toolbar_background" format="reference"/>
<attr name="conversation_list_typing_tint" format="color"/> <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_group_member_name" format="reference|color"/>
<attr name="conversation_received_card_background" format="reference|color"/>
<attr name="fab_color" format="reference|color" /> <attr name="fab_color" format="reference|color" />
<attr name="lower_right_divet" format="reference" /> <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_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="ic_visibility_off" format="reference" />
<attr name="conversation_background" format="reference|color"/> <attr name="conversation_background" format="reference|color"/>
@ -76,9 +73,6 @@
<attr name="quick_camera_icon" format="reference"/> <attr name="quick_camera_icon" format="reference"/>
<attr name="quick_mic_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_bubble_background" format="reference|color"/>
<attr name="conversation_item_sent_text_primary_color" 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"/> <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_text_indicator_tab_color" format="reference|color"/>
<attr name="conversation_item_sent_indicator_text_background" format="reference" /> <attr name="conversation_item_sent_indicator_text_background" format="reference" />
<attr name="conversation_item_sent_icon_color" format="color" /> <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_background" format="reference" />
<attr name="conversation_item_sticky_date_text_color" format="color" /> <attr name="conversation_item_sticky_date_text_color" format="color" />
<attr name="conversation_item_image_outline_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_audio" format="reference"/>
<attr name="conversation_icon_attach_video" 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="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_background_color" format="color" />
<attr name="linkpreview_primary_text_color" format="color" /> <attr name="linkpreview_primary_text_color" format="color" />
<attr name="linkpreview_secondary_text_color" format="color" /> <attr name="linkpreview_secondary_text_color" format="color" />
<attr name="linkpreview_divider_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="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_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_trash_icon" format="reference" />
<attr name="menu_selectall_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_split_icon" format="reference" />
<attr name="menu_accept_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_copy_icon" format="reference" />
<attr name="menu_info_icon" format="reference" />
<attr name="menu_forward_icon" format="reference" /> <attr name="menu_forward_icon" format="reference" />
<attr name="menu_save_icon" format="reference" /> <attr name="menu_save_icon" format="reference" />
<attr name="menu_reply_icon" format="reference" /> <attr name="menu_reply_icon" format="reference" />
@ -152,40 +116,23 @@
<attr name="pref_icon_tint" format="color"/> <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_start" format="color|reference" />
<attr name="home_gradient_end" format="color|reference" /> <attr name="home_gradient_end" format="color|reference" />
<attr name="message_received_background_color" format="color|reference" /> <attr name="message_received_background_color" format="color|reference" />
<attr name="message_sent_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="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="verification_background" format="color"/>
<attr name="media_overview_toolbar_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_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_header_background" format="color"/>
<attr name="shared_contact_details_titlebar" format="color"/> <attr name="shared_contact_details_titlebar" format="color"/>
<attr name="shared_contact_item_button_color" 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_icon" format="reference" />
<attr name="sticker_management_divider_color" format="color" /> <attr name="sticker_management_divider_color" format="color" />
<attr name="sticker_management_empty_background_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="tooltip_default_color" format="reference|color" />
<attr name="contact_list_divider" format="reference"/> <declare-styleable name="CustomDefaultPreference">
<attr name="custom_pref_toggle" format="string"/>
<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> </declare-styleable>
<declare-styleable name="AvatarImageView"> <declare-styleable name="AvatarImageView">
@ -270,22 +210,12 @@
<attr name="emoji_maxLength" format="integer" /> <attr name="emoji_maxLength" format="integer" />
</declare-styleable> </declare-styleable>
<declare-styleable name="RingtonePreference">
<attr name="showAdd" format="boolean" />
<attr name="summaryHasRingtone" format="string|reference" />
</declare-styleable>
<declare-styleable name="ColorPickerPreference"> <declare-styleable name="ColorPickerPreference">
<attr name="currentColor" format="reference" /> <attr name="currentColor" format="reference" />
<attr name="colors" format="reference" /> <attr name="colors" format="reference" />
<attr name="sortColors" format="boolean|reference" /> <attr name="sortColors" format="boolean|reference" />
<attr name="colorDescriptions" format="reference" /> <attr name="colorDescriptions" format="reference" />
<attr name="columns" format="integer|reference" /> <attr name="columns" format="integer|reference" />
<attr name="colorSize" format="enum|reference"> <attr name="colorSize" format="enum|reference">
<enum name="large" value="1" /> <enum name="large" value="1" />
<enum name="small" value="2" /> <enum name="small" value="2" />

View File

@ -25,6 +25,7 @@
<color name="compose_text_view_background">#141414</color> <color name="compose_text_view_background">#141414</color>
<color name="quote_not_found_background">#99FFFFFF</color> <color name="quote_not_found_background">#99FFFFFF</color>
<color name="new_conversation_button_collapsed_background">#1F1F1F</color> <color name="new_conversation_button_collapsed_background">#1F1F1F</color>
<color name="new_conversation_button_shadow">#077C44</color>
<color name="pn_option_background">#1B1B1B</color> <color name="pn_option_background">#1B1B1B</color>
<color name="pn_option_border">#212121</color> <color name="pn_option_border">#212121</color>
<color name="paths_building">#FFCE3A</color> <color name="paths_building">#FFCE3A</color>

View File

@ -8,7 +8,7 @@
<dimen name="small_font_size">15sp</dimen> <dimen name="small_font_size">15sp</dimen>
<dimen name="medium_font_size">17sp</dimen> <dimen name="medium_font_size">17sp</dimen>
<dimen name="large_font_size">22sp</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> <dimen name="massive_font_size">50sp</dimen>
<!-- Element Sizes --> <!-- Element Sizes -->
@ -29,9 +29,9 @@
<dimen name="text_view_corner_radius">8dp</dimen> <dimen name="text_view_corner_radius">8dp</dimen>
<dimen name="fake_chat_view_bubble_width">224dp</dimen> <dimen name="fake_chat_view_bubble_width">224dp</dimen>
<dimen name="fake_chat_view_bubble_corner_radius">10dp</dimen> <dimen name="fake_chat_view_bubble_corner_radius">10dp</dimen>
<dimen name="fake_chat_view_height">234dp</dimen> <dimen name="fake_chat_view_height">250dp</dimen>
<dimen name="setting_button_height">56dp</dimen> <dimen name="setting_button_height">56dp</dimen>
<dimen name="dialog_corner_radius">12dp</dimen> <dimen name="dialog_corner_radius">8dp</dimen>
<dimen name="dialog_button_corner_radius">4dp</dimen> <dimen name="dialog_button_corner_radius">4dp</dimen>
<dimen name="pn_option_corner_radius">8dp</dimen> <dimen name="pn_option_corner_radius">8dp</dimen>
<dimen name="path_status_view_size">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="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> <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">Attachment</string>
<string name="attachment_type_voice_message">Voice Message</string> <string name="attachment_type_voice_message">Voice Message</string>
<string name="details">Details</string>
</resources> </resources>

View File

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

View File

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Session --> <!-- Session -->
@ -43,16 +42,14 @@
<item name="dividerHorizontal">?dividerVertical</item> <item name="dividerHorizontal">?dividerVertical</item>
<!-- App specific attributes --> <!-- App specific attributes -->
<item name="search_toolbar_background">@color/black</item> <item name="ic_visibility_on">@drawable/ic_baseline_visibility_24</item>
<item name="search_background">@color/black</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="dialog_background_color">@color/dialog_background</item>
<item name="media_overview_toolbar_background">@color/transparent</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_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="media_keyboard_button_color">@color/core_grey_25</item>
<item name="searchViewStyle">@style/TextSecure.BaseDarkTheme.SearchView</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="conversation_input_background">@drawable/compose_background_dark</item>
<item name="quick_camera_icon">@drawable/ic_baseline_photo_camera_24</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> </style>
<!-- This should be the default theme for the application. --> <!-- This should be the default theme for the application. -->
@ -158,14 +156,7 @@
<item name="colorPrimary">@color/action_bar_background</item> <item name="colorPrimary">@color/action_bar_background</item>
<item name="colorPrimaryDark">@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_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_header_foreground">@color/text</item>
<item name="theme_type">dark</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_small">@drawable/ic_document_small_dark</item>
<item name="attachment_document_icon_large">@drawable/ic_document_large_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_background">@drawable/conversation_list_item_background_dark</item>
<item name="conversation_list_item_contact_color">#ffdddddd</item> <item name="conversation_list_item_contact_color">#ffdddddd</item>
<item name="conversation_list_item_subject_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_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_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_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_sent_text_indicator_tab_color">#99ffffff</item>
<item name="conversation_item_received_text_primary_color">@color/text</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_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_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_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_sticky_date_text_color">@color/core_grey_45</item>
<item name="conversation_item_image_outline_color">@color/transparent_white_30</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="verification_background">@color/core_grey_95</item>
<item name="dialog_info_icon">@drawable/ic_info_outline_dark</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="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="fab_color">@color/textsecure_primary_dark</item>
<item name="lower_right_divet">@drawable/divet_lower_right_light</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_secondary_text_color">@color/text</item>
<item name="linkpreview_divider_color">@color/transparent</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_audio">@drawable/ic_audio_dark</item>
<item name="conversation_icon_attach_video">@drawable/ic_video_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_icon">@drawable/sticker_button_dark</item>
<item name="sticker_management_divider_color">@color/core_grey_75</item> <item name="sticker_management_divider_color">@color/core_grey_75</item>
<item name="sticker_management_empty_background_color">@color/core_grey_85</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_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="group_members_dialog_icon">@drawable/ic_group_white_24dp</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.Fix</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_header_background">@color/grey_800</item>
<item name="shared_contact_details_titlebar">@color/grey_900</item> <item name="shared_contact_details_titlebar">@color/grey_900</item>

View File

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

View File

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

View File

@ -23,9 +23,6 @@ import android.content.Intent;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.os.Build; import android.os.Build;
import android.os.Bundle; 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.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.SpannableString; import android.text.SpannableString;
@ -49,6 +46,9 @@ import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; 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.animation.AnimationCompleteListener;
import org.thoughtcrime.securesms.components.AnimatingToggle; import org.thoughtcrime.securesms.components.AnimatingToggle;
import org.thoughtcrime.securesms.crypto.InvalidPassphraseException; import org.thoughtcrime.securesms.crypto.InvalidPassphraseException;
@ -91,8 +91,6 @@ public class PassphrasePromptActivity extends PassphraseActivity {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate()"); Log.i(TAG, "onCreate()");
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.prompt_passphrase_activity); setContentView(R.layout.prompt_passphrase_activity);
@ -204,7 +202,6 @@ public class PassphrasePromptActivity extends PassphraseActivity {
private void initializeResources() { private void initializeResources() {
ImageButton okButton = findViewById(R.id.ok_button); ImageButton okButton = findViewById(R.id.ok_button);
Toolbar toolbar = findViewById(R.id.toolbar);
showButton = findViewById(R.id.passphrase_visibility); showButton = findViewById(R.id.passphrase_visibility);
hideButton = findViewById(R.id.passphrase_visibility_off); hideButton = findViewById(R.id.passphrase_visibility_off);
@ -217,9 +214,6 @@ public class PassphrasePromptActivity extends PassphraseActivity {
fingerprintCancellationSignal = new CancellationSignal(); fingerprintCancellationSignal = new CancellationSignal();
fingerprintListener = new FingerprintListener(); fingerprintListener = new FingerprintListener();
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("");
SpannableString hint = new SpannableString(" " + getString(R.string.PassphrasePromptActivity_enter_passphrase)); 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 RelativeSizeSpan(0.9f), 0, hint.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
hint.setSpan(new TypefaceSpan("sans-serif"), 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()); showButton.setOnClickListener(new ShowButtonOnClickListener());
hideButton.setOnClickListener(new HideButtonOnClickListener()); hideButton.setOnClickListener(new HideButtonOnClickListener());
passphraseText.setOnEditorActionListener(new PassphraseActionListener()); passphraseText.setOnEditorActionListener(new PassphraseActionListener());
passphraseText.setImeActionLabel(getString(R.string.prompt_passphrase_activity__unlock), passphraseText.setImeActionLabel(getString(R.string.prompt_passphrase_activity__unlock), EditorInfo.IME_ACTION_DONE);
EditorInfo.IME_ACTION_DONE);
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp); fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN); 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.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.os.Build; import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
@ -17,11 +14,16 @@ import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.annimon.stream.Stream; import com.annimon.stream.Stream;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
import org.thoughtcrime.securesms.attachments.Attachment; import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.database.DatabaseFactory; 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.DecryptableStreamUriLoader.DecryptableUri;
import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.Slide; 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); 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 // 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(), mainView.setBackgroundColor(ThemeUtil.getThemedColor(getContext(),
outgoing ? R.attr.message_received_background_color : R.attr.message_sent_background_color)); 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.protocol.SessionManagementProtocol;
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities; import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
import org.thoughtcrime.securesms.loki.views.MentionCandidateSelectionView; import org.thoughtcrime.securesms.loki.views.MentionCandidateSelectionView;
import org.thoughtcrime.securesms.loki.views.ProfilePictureView;
import org.thoughtcrime.securesms.loki.views.SessionRestoreBannerView; import org.thoughtcrime.securesms.loki.views.SessionRestoreBannerView;
import org.thoughtcrime.securesms.mediasend.Media; import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.mediasend.MediaSendActivity; import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
@ -234,6 +235,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -300,6 +302,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private AnimatingToggle buttonToggle; private AnimatingToggle buttonToggle;
private SendButton sendButton; private SendButton sendButton;
private ImageButton attachButton; private ImageButton attachButton;
private ProfilePictureView profilePictureView;
private TextView titleTextView; private TextView titleTextView;
private TextView charactersLeft; private TextView charactersLeft;
private ConversationFragment fragment; private ConversationFragment fragment;
@ -527,6 +530,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
composeText.setTransport(sendButton.getSelectedTransport()); composeText.setTransport(sendButton.getSelectedTransport());
updateTitleTextView(recipient); updateTitleTextView(recipient);
updateProfilePicture();
updateSubtitleTextView(); updateSubtitleTextView();
setActionBarColor(recipient.getColor()); setActionBarColor(recipient.getColor());
updateInputUI(recipient, isSecureText, isDefaultSms); updateInputUI(recipient, isSecureText, isDefaultSms);
@ -621,6 +625,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
recipient = Recipient.from(this, data.getParcelableExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA), true); recipient = Recipient.from(this, data.getParcelableExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA), true);
recipient.addListener(this); recipient.addListener(this);
updateTitleTextView(recipient); updateTitleTextView(recipient);
updateProfilePicture();
updateSubtitleTextView(); updateSubtitleTextView();
NotificationChannels.updateContactChannelName(this, recipient); NotificationChannels.updateContactChannelName(this, recipient);
updateInputUI(recipient, isSecureText, isDefaultSms); updateInputUI(recipient, isSecureText, isDefaultSms);
@ -1654,6 +1659,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} }
private void initializeViews() { private void initializeViews() {
profilePictureView = findViewById(R.id.profilePictureView);
titleTextView = findViewById(R.id.titleTextView); titleTextView = findViewById(R.id.titleTextView);
buttonToggle = ViewUtil.findById(this, R.id.button_toggle); buttonToggle = ViewUtil.findById(this, R.id.button_toggle);
sendButton = ViewUtil.findById(this, R.id.send_button); sendButton = ViewUtil.findById(this, R.id.send_button);
@ -1872,6 +1878,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
Util.runOnMain(() -> { Util.runOnMain(() -> {
Log.i(TAG, "onModifiedRun(): " + recipient.getRegistered()); Log.i(TAG, "onModifiedRun(): " + recipient.getRegistered());
updateTitleTextView(recipient); updateTitleTextView(recipient);
updateProfilePicture();
updateSubtitleTextView(); updateSubtitleTextView();
// titleView.setVerified(identityRecords.isVerified()); // titleView.setVerified(identityRecords.isVerified());
updateInputUI(recipient, isSecureText, isDefaultSms); updateInputUI(recipient, isSecureText, isDefaultSms);
@ -3100,18 +3107,15 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} }
} }
private void updateProfilePicture() {
profilePictureView.glide = GlideApp.with(this);
profilePictureView.update(recipient, threadId);
}
private void updateSubtitleTextView() { private void updateSubtitleTextView() {
muteIndicatorImageView.setVisibility(View.GONE); muteIndicatorImageView.setVisibility(View.GONE);
subtitleTextView.setVisibility(View.VISIBLE); subtitleTextView.setVisibility(View.VISIBLE);
if (messageStatus != null) { if (recipient.isMuted()) {
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()) {
muteIndicatorImageView.setVisibility(View.VISIBLE); muteIndicatorImageView.setVisibility(View.VISIBLE);
subtitleTextView.setText("Muted until " + DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault())); 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")) { } 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 { } else {
subtitleTextView.setVisibility(View.GONE); 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 { } else {
subtitleTextView.setVisibility(View.GONE); subtitleTextView.setVisibility(View.GONE);
} }

View File

@ -528,6 +528,7 @@ public class ThreadDatabase extends Database {
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
return cursor.getLong(cursor.getColumnIndexOrThrow(ID)); return cursor.getLong(cursor.getColumnIndexOrThrow(ID));
} else { } else {
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
return createThreadForRecipient(recipient.getAddress(), recipient.isGroupRecipient(), distributionType); return createThreadForRecipient(recipient.getAddress(), recipient.isGroupRecipient(), distributionType);
} }
} finally { } 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.ConversationOptionsBottomSheet
import org.thoughtcrime.securesms.loki.dialogs.LightThemeFeatureIntroBottomSheet import org.thoughtcrime.securesms.loki.dialogs.LightThemeFeatureIntroBottomSheet
import org.thoughtcrime.securesms.loki.dialogs.MultiDeviceRemovalBottomSheet import org.thoughtcrime.securesms.loki.dialogs.MultiDeviceRemovalBottomSheet
import org.thoughtcrime.securesms.loki.dialogs.UserDetailsBottomSheet
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
import org.thoughtcrime.securesms.loki.utilities.* import org.thoughtcrime.securesms.loki.utilities.*
@ -100,6 +101,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
profileButton.displayName = TextSecurePreferences.getProfileName(this) profileButton.displayName = TextSecurePreferences.getProfileName(this)
profileButton.update() profileButton.update()
profileButton.setOnClickListener { openSettings() } profileButton.setOnClickListener { openSettings() }
pathStatusViewContainer.disableClipping()
pathStatusViewContainer.setOnClickListener { showPath() } pathStatusViewContainer.setOnClickListener { showPath() }
// Set up seed reminder view // Set up seed reminder view
val isMasterDevice = (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == null) val isMasterDevice = (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == null)
@ -202,7 +204,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
seedReminderView.visibility = View.GONE seedReminderView.visibility = View.GONE
} }
// Multiple device removal notification // Multi device removal sheet
if (!TextSecurePreferences.getHasSeenMultiDeviceRemovalSheet(this)) { if (!TextSecurePreferences.getHasSeenMultiDeviceRemovalSheet(this)) {
TextSecurePreferences.setHasSeenMultiDeviceRemovalSheet(this) TextSecurePreferences.setHasSeenMultiDeviceRemovalSheet(this)
val userPublicKey = TextSecurePreferences.getLocalNumber(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) && if (!TextSecurePreferences.hasSeenLightThemeIntroSheet(this) &&
UiModeUtilities.isDayUiMode(this)) { UiModeUtilities.isDayUiMode(this)) {
TextSecurePreferences.setHasSeenLightThemeIntroSheet(this) TextSecurePreferences.setHasSeenLightThemeIntroSheet(this)
@ -271,6 +273,14 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
val thread = view.thread ?: return val thread = view.thread ?: return
val bottomSheet = ConversationOptionsBottomSheet() val bottomSheet = ConversationOptionsBottomSheet()
bottomSheet.recipient = thread.recipient bottomSheet.recipient = thread.recipient
bottomSheet.onViewDetailsTapped = {
bottomSheet.dismiss()
val userDetailsBottomSheet = UserDetailsBottomSheet()
val bundle = Bundle()
bundle.putString("publicKey", thread.recipient.address.toPhoneString())
userDetailsBottomSheet.arguments = bundle
userDetailsBottomSheet.show(supportFragmentManager, userDetailsBottomSheet.tag)
}
bottomSheet.onBlockTapped = { bottomSheet.onBlockTapped = {
bottomSheet.dismiss() bottomSheet.dismiss()
if (!thread.recipient.isBlocked) { if (!thread.recipient.isBlocked) {

View File

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

View File

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

View File

@ -33,8 +33,14 @@ class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database
return TextSecurePreferences.getProfileName(context) return TextSecurePreferences.getProfileName(context)
} else { } else {
val database = databaseHelper.readableDatabase 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)) 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. // if we want to use dialog fragments properly.
lateinit var recipient: Recipient lateinit var recipient: Recipient
var onViewDetailsTapped: (() -> Unit?)? = null
var onBlockTapped: (() -> Unit)? = null var onBlockTapped: (() -> Unit)? = null
var onUnblockTapped: (() -> Unit)? = null var onUnblockTapped: (() -> Unit)? = null
var onDeleteTapped: (() -> Unit)? = null var onDeleteTapped: (() -> Unit)? = null
@ -30,18 +31,16 @@ public class ConversationOptionsBottomSheet : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
if (!this::recipient.isInitialized) { return dismiss() }
if (!this::recipient.isInitialized) {
dismiss()
return
}
if (!recipient.isGroupRecipient && !recipient.isLocalNumber) { if (!recipient.isGroupRecipient && !recipient.isLocalNumber) {
detailsTextView.visibility = View.VISIBLE
unblockTextView.visibility = if (recipient.isBlocked) View.VISIBLE else View.GONE unblockTextView.visibility = if (recipient.isBlocked) View.VISIBLE else View.GONE
blockTextView.visibility = if (recipient.isBlocked) View.GONE else View.VISIBLE blockTextView.visibility = if (recipient.isBlocked) View.GONE else View.VISIBLE
detailsTextView.setOnClickListener { onViewDetailsTapped?.invoke() }
blockTextView.setOnClickListener { onBlockTapped?.invoke() } blockTextView.setOnClickListener { onBlockTapped?.invoke() }
unblockTextView.setOnClickListener { onUnblockTapped?.invoke() } unblockTextView.setOnClickListener { onUnblockTapped?.invoke() }
} else {
detailsTextView.visibility = View.GONE
} }
deleteTextView.setOnClickListener { onDeleteTapped?.invoke() } deleteTextView.setOnClickListener { onDeleteTapped?.invoke() }
} }

View File

@ -7,17 +7,18 @@ import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.appcompat.app.AlertDialog
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.WindowManager
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import kotlinx.android.synthetic.main.dialog_seed.view.* import kotlinx.android.synthetic.main.dialog_seed.view.*
import network.loki.messenger.R import network.loki.messenger.R
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
import org.whispersystems.signalservice.loki.utilities.hexEncodedPrivateKey import org.whispersystems.signalservice.loki.utilities.hexEncodedPrivateKey
import java.io.File
class SeedDialog : DialogFragment() { 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.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.api.messages.SignalServiceContent import org.whispersystems.signalservice.api.messages.SignalServiceContent
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.MultiDeviceProtocol
import java.security.MessageDigest import java.security.MessageDigest
object SessionMetaProtocol { object SessionMetaProtocol {
@ -37,24 +36,16 @@ object SessionMetaProtocol {
@JvmStatic @JvmStatic
fun handleProfileUpdateIfNeeded(context: Context, content: SignalServiceContent) { fun handleProfileUpdateIfNeeded(context: Context, content: SignalServiceContent) {
val rawDisplayName = content.senderDisplayName.orNull() ?: return val displayName = content.senderDisplayName.orNull() ?: return
if (rawDisplayName.isBlank()) { return } if (displayName.isBlank()) { return }
val userPublicKey = TextSecurePreferences.getLocalNumber(context) val userPublicKey = TextSecurePreferences.getLocalNumber(context)
val userMasterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context) val userMasterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
val sender = content.sender.toLowerCase() val sender = content.sender.toLowerCase()
if (userMasterPublicKey == sender) { if (userMasterPublicKey == sender) {
// Update the user's local name if the message came from their master device // 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)
} }
DatabaseFactory.getLokiUserDatabase(context).setDisplayName(sender, displayName)
} }
@JvmStatic @JvmStatic

View File

@ -53,7 +53,9 @@ object MentionUtilities {
} }
val result = SpannableString(text) val result = SpannableString(text)
for (mention in mentions) { 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) result.setSpan(StyleSpan(Typeface.BOLD), mention.first.lower, mention.first.upper, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
} }
return result return result

View File

@ -57,37 +57,8 @@ class ConversationView : LinearLayout {
accentView.setBackgroundResource(R.color.accent) accentView.setBackgroundResource(R.color.accent)
accentView.visibility = if (thread.unreadCount > 0) View.VISIBLE else View.INVISIBLE accentView.visibility = if (thread.unreadCount > 0) View.VISIBLE else View.INVISIBLE
} }
if (thread.recipient.isGroupRecipient) {
if ("Session Public Chat" == thread.recipient.name) {
profilePictureView.publicKey = ""
profilePictureView.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.glide = glide
profilePictureView.update() profilePictureView.update(thread.recipient, thread.threadId)
val senderDisplayName = if (thread.recipient.isLocalNumber) context.getString(R.string.note_to_self) else if (!thread.recipient.name.isNullOrEmpty()) thread.recipient.name else thread.recipient.address.toString() val senderDisplayName = if (thread.recipient.isLocalNumber) context.getString(R.string.note_to_self) else if (!thread.recipient.name.isNullOrEmpty()) thread.recipient.name else thread.recipient.address.toString()
btnGroupNameDisplay.text = senderDisplayName btnGroupNameDisplay.text = senderDisplayName
timestampTextView.text = DateUtils.getBriefRelativeTimeSpanString(context, Locale.getDefault(), thread.date) timestampTextView.text = DateUtils.getBriefRelativeTimeSpanString(context, Locale.getDefault(), thread.date)

View File

@ -1,14 +1,18 @@
package org.thoughtcrime.securesms.loki.views package org.thoughtcrime.securesms.loki.views
import android.animation.FloatEvaluator
import android.animation.ValueAnimator
import android.content.Context import android.content.Context
import android.content.Context.LAYOUT_INFLATER_SERVICE import android.content.Context.LAYOUT_INFLATER_SERVICE
import android.os.Handler import android.os.Handler
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.LinearLayout
import android.widget.ScrollView import android.widget.ScrollView
import kotlinx.android.synthetic.main.view_fake_chat.view.* import kotlinx.android.synthetic.main.view_fake_chat.view.*
import network.loki.messenger.R import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.disableClipping
class FakeChatView : ScrollView { class FakeChatView : ScrollView {
@ -38,7 +42,8 @@ class FakeChatView : ScrollView {
private fun setUpViewHierarchy() { private fun setUpViewHierarchy() {
val inflater = context.getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater val inflater = context.getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
val contentView = inflater.inflate(R.layout.view_fake_chat, null) val contentView = inflater.inflate(R.layout.view_fake_chat, null) as LinearLayout
contentView.disableClipping()
addView(contentView) addView(contentView)
isVerticalScrollBarEnabled = false isVerticalScrollBarEnabled = false
} }
@ -47,8 +52,13 @@ class FakeChatView : ScrollView {
// region Animation // region Animation
fun startAnimating() { fun startAnimating() {
listOf( bubble1, bubble2, bubble3, bubble4, bubble5 ).forEach { it.alpha = 0.0f } listOf( bubble1, bubble2, bubble3, bubble4, bubble5 ).forEach { it.alpha = 0.0f }
fun show(view: View) { fun show(bubble: View) {
view.animate().alpha(1.0f).setDuration(animationDuration).start() val animation = ValueAnimator.ofObject(FloatEvaluator(), 0.0f, 1.0f)
animation.duration = animationDuration
animation.addUpdateListener { animator ->
bubble.alpha = animator.animatedValue as Float
}
animation.start()
} }
Handler().postDelayed({ Handler().postDelayed({
show(bubble1) show(bubble1)

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

@ -16,7 +16,7 @@ class LabeledSeparatorView : RelativeLayout {
private val path = Path() private val path = Path()
private val paint: Paint by lazy{ private val paint: Paint by lazy {
val result = Paint() val result = Paint()
result.style = Paint.Style.STROKE result.style = Paint.Style.STROKE
result.color = ThemeUtil.getThemedColor(context, R.attr.dividerHorizontal) result.color = ThemeUtil.getThemedColor(context, R.attr.dividerHorizontal)

View File

@ -7,9 +7,7 @@ import android.animation.ValueAnimator
import android.content.Context import android.content.Context
import android.content.Context.VIBRATOR_SERVICE import android.content.Context.VIBRATOR_SERVICE
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.PointF import android.graphics.PointF
import android.graphics.drawable.GradientDrawable
import android.os.Build import android.os.Build
import android.os.VibrationEffect import android.os.VibrationEffect
import android.os.VibrationEffect.DEFAULT_AMPLITUDE import android.os.VibrationEffect.DEFAULT_AMPLITUDE
@ -66,24 +64,25 @@ class NewConversationButtonSetView : RelativeLayout {
private val collapsedImageViewPosition by lazy { PointF((expandedSize - collapsedSize) / 2, (expandedSize - collapsedSize) / 2) } private val collapsedImageViewPosition by lazy { PointF((expandedSize - collapsedSize) / 2, (expandedSize - collapsedSize) / 2) }
private val imageView by lazy { private val imageView by lazy {
val result = ImageView(context) val result = NewConversationButtonImageView(context)
val size = collapsedSize.toInt() val size = collapsedSize.toInt()
result.layoutParams = LayoutParams(size, size) result.layoutParams = LayoutParams(size, size)
result.setBackgroundResource(R.drawable.new_conversation_button_background) result.setBackgroundResource(R.drawable.new_conversation_button_background)
val background = result.background as GradientDrawable @ColorRes val backgroundColorID = if (isMain) R.color.accent else R.color.new_conversation_button_collapsed_background
@ColorRes val backgroundColorID = if (isMain) @ColorRes val shadowColorID = if (isMain) {
R.color.accent else R.color.new_conversation_button_shadow
R.color.new_conversation_button_collapsed_background } else {
background.color = ColorStateList.valueOf(resources.getColorWithID(backgroundColorID, context.theme)) if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
}
result.mainColor = resources.getColorWithID(backgroundColorID, context.theme)
result.sessionShadowColor = resources.getColorWithID(shadowColorID, context.theme)
result.scaleType = ImageView.ScaleType.CENTER result.scaleType = ImageView.ScaleType.CENTER
result.setImageResource(iconID) result.setImageResource(iconID)
result.imageTintList = if (isMain) {
result.imageTintList = if (isMain)
// Always use white icon for the main button.
ColorStateList.valueOf(resources.getColorWithID(android.R.color.white, context.theme)) ColorStateList.valueOf(resources.getColorWithID(android.R.color.white, context.theme))
else } else {
ColorStateList.valueOf(resources.getColorWithID(R.color.text, context.theme)) ColorStateList.valueOf(resources.getColorWithID(R.color.text, context.theme))
}
result result
} }
@ -106,30 +105,21 @@ class NewConversationButtonSetView : RelativeLayout {
} }
fun expand() { fun expand() {
animateImageViewColorChange(R.color.new_conversation_button_collapsed_background, R.color.accent) GlowViewUtilities.animateColorChange(context, imageView, R.color.new_conversation_button_collapsed_background, R.color.accent)
@ColorRes val startShadowColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
GlowViewUtilities.animateShadowColorChange(context, imageView, startShadowColorID, R.color.new_conversation_button_shadow)
imageView.animateSizeChange(R.dimen.new_conversation_button_collapsed_size, R.dimen.new_conversation_button_expanded_size, animationDuration) imageView.animateSizeChange(R.dimen.new_conversation_button_collapsed_size, R.dimen.new_conversation_button_expanded_size, animationDuration)
animateImageViewPositionChange(collapsedImageViewPosition, expandedImageViewPosition) animateImageViewPositionChange(collapsedImageViewPosition, expandedImageViewPosition)
} }
fun collapse() { fun collapse() {
animateImageViewColorChange(R.color.accent, R.color.new_conversation_button_collapsed_background) GlowViewUtilities.animateColorChange(context, imageView, R.color.accent, R.color.new_conversation_button_collapsed_background)
@ColorRes val endShadowColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
GlowViewUtilities.animateShadowColorChange(context, imageView, R.color.new_conversation_button_shadow, endShadowColorID)
imageView.animateSizeChange(R.dimen.new_conversation_button_expanded_size, R.dimen.new_conversation_button_collapsed_size, animationDuration) imageView.animateSizeChange(R.dimen.new_conversation_button_expanded_size, R.dimen.new_conversation_button_collapsed_size, animationDuration)
animateImageViewPositionChange(expandedImageViewPosition, collapsedImageViewPosition) animateImageViewPositionChange(expandedImageViewPosition, collapsedImageViewPosition)
} }
private fun animateImageViewColorChange(@ColorRes startColorID: Int, @ColorRes endColorID: Int) {
val drawable = imageView.background as GradientDrawable
val startColor = resources.getColorWithID(startColorID, context.theme)
val endColor = resources.getColorWithID(endColorID, context.theme)
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
animation.duration = animationDuration
animation.addUpdateListener { animator ->
val color = animator.animatedValue as Int
drawable.color = ColorStateList.valueOf(color)
}
animation.start()
}
private fun animateImageViewPositionChange(startPosition: PointF, endPosition: PointF) { private fun animateImageViewPositionChange(startPosition: PointF, endPosition: PointF) {
val animation = ValueAnimator.ofObject(PointFEvaluator(), startPosition, endPosition) val animation = ValueAnimator.ofObject(PointFEvaluator(), startPosition, endPosition)
animation.duration = animationDuration animation.duration = animationDuration
@ -170,6 +160,7 @@ class NewConversationButtonSetView : RelativeLayout {
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { setUpViewHierarchy() } constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { setUpViewHierarchy() }
private fun setUpViewHierarchy() { private fun setUpViewHierarchy() {
disableClipping()
// Set up session button // Set up session button
addView(sessionButton) addView(sessionButton)
sessionButton.alpha = 0.0f sessionButton.alpha = 0.0f

View File

@ -4,14 +4,30 @@ import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.graphics.Canvas
import android.graphics.Paint
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.View
import androidx.annotation.ColorInt
import network.loki.messenger.R import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.whispersystems.signalservice.loki.api.onionrequests.OnionRequestAPI import org.whispersystems.signalservice.loki.api.onionrequests.OnionRequestAPI
class PathStatusView : View { class PathStatusView : View {
private val broadcastReceivers = mutableListOf<BroadcastReceiver>() private val broadcastReceivers = mutableListOf<BroadcastReceiver>()
@ColorInt var mainColor: Int = 0
set(newValue) { field = newValue; paint.color = newValue }
@ColorInt var sessionShadowColor: Int = 0
set(newValue) { field = newValue; paint.setShadowLayer(toPx(8, resources).toFloat(), 0.0f, 0.0f, newValue) }
private val paint: Paint by lazy {
val result = Paint()
result.style = Paint.Style.FILL
result.isAntiAlias = true
result
}
constructor(context: Context) : super(context) { constructor(context: Context) : super(context) {
initialize() initialize()
@ -31,6 +47,7 @@ class PathStatusView : View {
private fun initialize() { private fun initialize() {
update() update()
setWillNotDraw(false)
} }
override fun onAttachedToWindow() { override fun onAttachedToWindow() {
@ -70,8 +87,19 @@ class PathStatusView : View {
private fun update() { private fun update() {
if (OnionRequestAPI.paths.count() >= OnionRequestAPI.pathCount) { if (OnionRequestAPI.paths.count() >= OnionRequestAPI.pathCount) {
setBackgroundResource(R.drawable.accent_dot) setBackgroundResource(R.drawable.accent_dot)
mainColor = resources.getColorWithID(R.color.accent, context.theme)
sessionShadowColor = resources.getColorWithID(R.color.accent, context.theme)
} else { } else {
setBackgroundResource(R.drawable.paths_building_dot) setBackgroundResource(R.drawable.paths_building_dot)
mainColor = resources.getColorWithID(R.color.paths_building, context.theme)
sessionShadowColor = resources.getColorWithID(R.color.paths_building, context.theme)
} }
} }
override fun onDraw(c: Canvas) {
val w = width.toFloat()
val h = height.toFloat()
c.drawCircle(w / 2, h / 2, w / 2, paint)
super.onDraw(c)
}
} }

View File

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.loki.views package org.thoughtcrime.securesms.loki.views
import android.content.Context import android.content.Context
import android.text.TextUtils
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -8,14 +9,17 @@ import android.widget.ImageView
import android.widget.RelativeLayout import android.widget.RelativeLayout
import androidx.annotation.DimenRes import androidx.annotation.DimenRes
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
import kotlinx.android.synthetic.main.view_conversation.view.*
import kotlinx.android.synthetic.main.view_profile_picture.view.* import kotlinx.android.synthetic.main.view_profile_picture.view.*
import network.loki.messenger.R import network.loki.messenger.R
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto
import org.thoughtcrime.securesms.database.Address import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.todo.AvatarPlaceholderGenerator import org.thoughtcrime.securesms.loki.todo.AvatarPlaceholderGenerator
import org.thoughtcrime.securesms.mms.GlideRequests import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
// TODO: Look into a better way of handling different sizes. Maybe an enum (with associated values) encapsulating the different modes? // TODO: Look into a better way of handling different sizes. Maybe an enum (with associated values) encapsulating the different modes?
@ -53,6 +57,43 @@ class ProfilePictureView : RelativeLayout {
// endregion // endregion
// region Updating // 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() { fun update() {
val publicKey = publicKey ?: return val publicKey = publicKey ?: return
val additionalPublicKey = additionalPublicKey val additionalPublicKey = additionalPublicKey